X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fpdf%2FInfoOutputDev.cc;h=a977970deed31c5972a7544789e7df1b20d6509e;hp=8a00d98ea11cdb047116b3ee291dde3798f9e522;hb=5244627ce001a4b2c49595fe38042628856be1d3;hpb=cdcf434411b35bb57bc3de9dffa6314d6ac70d5f diff --git a/lib/pdf/InfoOutputDev.cc b/lib/pdf/InfoOutputDev.cc index 8a00d98..a977970 100644 --- a/lib/pdf/InfoOutputDev.cc +++ b/lib/pdf/InfoOutputDev.cc @@ -15,9 +15,13 @@ #endif #include "GfxState.h" #include "../log.h" +#include "../types.h" +#include "../q.h" +#include "../gfxfont.h" #include +#include -/* there's not yet a way to set this */ +int config_addspace = 1; int config_fontquality = 10; int config_bigchar = 0; @@ -50,35 +54,37 @@ InfoOutputDev::~InfoOutputDev() delete id2font;id2font=0; delete splash;splash=0; } + void FontInfo::grow(int size) { if(size >= this->num_glyphs) { this->glyphs = (GlyphInfo**)realloc(this->glyphs, sizeof(GlyphInfo*)*(size)); + this->kerning = (dict_t**)realloc(this->kerning, sizeof(dict_t*)*(size)); memset(&this->glyphs[this->num_glyphs], 0, sizeof(SplashPath*)*((size)-this->num_glyphs)); + memset(&this->kerning[this->num_glyphs], 0, sizeof(dict_t*)*((size)-this->num_glyphs)); this->num_glyphs = size; } } FontInfo::FontInfo(char*id) { this->id = strdup(id); - this->charid2glyph = 0; this->seen = 0; this->num_glyphs = 0; this->glyphs = 0; + this->kerning = 0; this->splash_font = 0; this->lastchar = -1; this->lastx = 0; this->lasty = 0; this->gfxfont = 0; + this->space_char = -1; + this->ascender = 0; + this->descender = 0; } FontInfo::~FontInfo() { if(this->id) {free(this->id);this->id=0;} this->font = 0; - if(this->charid2glyph) { - free(this->charid2glyph); - this->charid2glyph = 0; - } int t; for(t=0;tgfxfont) + gfxfont_free(this->gfxfont); + + if(kerning) { + for(t=0;tnum_glyphs;t++) { + gfxglyph_t*g = &font->glyphs[t]; + if(GLYPH_IS_SPACE(g)) { + if(g->unicode == 32) return t; + } + } + return -1; +} + +static int addSpace(gfxfont_t*font) +{ + /* first, make sure the new space char is the only char that'll use unicode 32 */ + int t; + for(t=0;tnum_glyphs;t++) { + if(font->glyphs[t].unicode==32) + font->glyphs[t].unicode=0; + } + font->num_glyphs++; + font->glyphs = (gfxglyph_t*)realloc(font->glyphs, sizeof(gfxglyph_t)*font->num_glyphs); + gfxglyph_t*g = &font->glyphs[font->num_glyphs-1]; + memset(g, 0, sizeof(*g)); + g->unicode = 32; + g->advance = fabs(font->ascent + font->descent)*2 / 3; + if(font->max_unicode > 32) + font->unicode2glyph[32] = font->num_glyphs-1; +#if 0 + g->line = gfxline_makerectangle(0, -font->ascent, g->advance, font->descent); +#endif + return font->num_glyphs-1; +} + +static gfxfont_t* createGfxFont(FontInfo*src) +{ + gfxfont_t*font = (gfxfont_t*)rfx_calloc(sizeof(gfxfont_t)); font->glyphs = (gfxglyph_t*)malloc(sizeof(gfxglyph_t)*src->num_glyphs); memset(font->glyphs, 0, sizeof(gfxglyph_t)*src->num_glyphs); @@ -104,8 +159,8 @@ gfxfont_t* createGfxFont(FontInfo*src) double scale = 1; //printf("%d glyphs\n", font->num_glyphs); font->num_glyphs = 0; - font->ascent = fabs(src->descender); - font->descent = fabs(src->ascender); + font->ascent = fabs(src->ascender); + font->descent = fabs(src->descender); for(t=0;tnum_glyphs;t++) { if(src->glyphs[t]) { @@ -115,8 +170,6 @@ gfxfont_t* createGfxFont(FontInfo*src) gfxglyph_t*glyph = &font->glyphs[font->num_glyphs]; src->glyphs[t]->glyphid = font->num_glyphs; glyph->unicode = src->glyphs[t]->unicode; - if(glyph->unicode >= font->max_unicode) - font->max_unicode = glyph->unicode+1; gfxdrawer_t drawer; gfxdrawer_target_gfxline(&drawer); int s; @@ -153,7 +206,6 @@ gfxfont_t* createGfxFont(FontInfo*src) if(src->glyphs[t]->advance>0) { glyph->advance = src->glyphs[t]->advance; } else { - msg(" Approximating advance value for glyph %d", t); glyph->advance = xmax*scale; } if(config_bigchar) { @@ -166,23 +218,69 @@ gfxfont_t* createGfxFont(FontInfo*src) font->num_glyphs++; } } - font->unicode2glyph = (int*)malloc(sizeof(int)*font->max_unicode); - memset(font->unicode2glyph, -1, sizeof(int)*font->max_unicode); - for(t=0;tnum_glyphs;t++) { - if(font->glyphs[t].unicode>0 && font->glyphs[t].unicodemax_unicode) { - font->unicode2glyph[font->glyphs[t].unicode] = t; - } + int kerning_size = 0; + for(t=0;tnum_glyphs;t++) { + dict_t* d = src->kerning[t]; + if(!d) continue; + DICT_ITERATE_ITEMS(d,void*,key,mtf_t*,m) { + if(m) { + kerning_size++; + } + } + } + font->kerning_size = kerning_size; + font->kerning = (gfxkerning_t*)malloc(sizeof(gfxkerning_t)*kerning_size); + int pos = 0; + for(t=0;tnum_glyphs;t++) { + dict_t* d = src->kerning[t]; + if(!d) continue; + DICT_ITERATE_ITEMS(d,void*,key,mtf_t*,m) { + if(m) { + font->kerning[pos].c1 = src->glyphs[t]->glyphid; + font->kerning[pos].c2 = src->glyphs[(int)(ptroff_t)key]->glyphid; + font->kerning[pos].advance = (int)(ptroff_t)m->first->key; + pos++; + } + } } + //int advance = (int)(ptroff_t)m->first->key; + return font; } +static float find_average_glyph_advance(gfxfont_t*f) +{ + if(!f->num_glyphs) + return 0.0; + + float*values = (float*)malloc(sizeof(float)*f->num_glyphs); + int t; + for(t=0;tnum_glyphs;t++) { + values[t] = f->glyphs[t].advance; + } + float m = medianf(values, f->num_glyphs); + free(values); + return m; +} gfxfont_t* FontInfo::getGfxFont() { if(!this->gfxfont) { this->gfxfont = createGfxFont(this); this->gfxfont->id = strdup(this->id); + this->space_char = findSpace(this->gfxfont); + this->average_advance = find_average_glyph_advance(this->gfxfont); + + if(this->space_char>=0) { + msg(" Font %s has space char %d (unicode=%d)", + this->id, this->space_char, + this->gfxfont->glyphs[this->space_char].unicode); + } else if(config_addspace) { + this->space_char = addSpace(this->gfxfont); + msg(" Appending space char to font %s, position %d, width %f", this->gfxfont->id, this->space_char, this->gfxfont->glyphs[this->space_char].advance); + } + gfxfont_fix_unicode(this->gfxfont); } return this->gfxfont; } @@ -338,19 +436,35 @@ void InfoOutputDev::drawChar(GfxState *state, double x, double y, g->advance = currentfont->splash_font->last_advance; g->unicode = 0; } - if(uLen && (u[0]>=32 && u[0]unicode || !g->unicode)) { + if(uLen && ((u[0]>=32 && u[0]unicode) || !g->unicode)) { g->unicode = u[0]; } if(currentfont->lastchar>=0 && currentfont->lasty == y) { - double xshift = x - currentfont->lastx; + double xshift = (x - currentfont->lastx); if(xshift>=0 && xshift > g->advance_max) { g->advance_max = xshift; } + int advance = (int)xshift; + if(advance>=0 && advanceadvance*4 && advance!=currentfont->lastadvance) { + int c1 = currentfont->lastchar; + int c2 = code; + dict_t*d = currentfont->kerning[c1]; + if(!d) { + d = currentfont->kerning[c1] = dict_new2(&int_type); + } + mtf_t*k = (mtf_t*)dict_lookup(d, (void*)(ptroff_t)c2); + if(!k) { + k = mtf_new(&int_type); + dict_put(d, (void*)(ptroff_t)c2, k); + } + mtf_increase(k, (void*)(ptroff_t)advance); + } } currentfont->lastx = x; currentfont->lasty = y; currentfont->lastchar = code; + currentfont->lastadvance = (int)(g->advance+0.5); } GBool InfoOutputDev::beginType3Char(GfxState *state, double x, double y, double dx, double dy, CharCode code, Unicode *u, int uLen) @@ -382,6 +496,7 @@ GBool InfoOutputDev::beginType3Char(GfxState *state, double x, double y, double currentglyph->y1=0; currentglyph->x2=dx; currentglyph->y2=dy; + currentglyph->advance=dx; return gFalse; } else { return gTrue; @@ -398,6 +513,11 @@ void InfoOutputDev::type3D0(GfxState *state, double wx, double wy) void InfoOutputDev::type3D1(GfxState *state, double wx, double wy, double llx, double lly, double urx, double ury) { + if(-lly>currentfont->descender) + currentfont->descender = -lly; + if(ury>currentfont->ascender) + currentfont->ascender = ury; + currentglyph->x1=llx; currentglyph->y1=lly; currentglyph->x2=urx;