X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fgfxfont.c;h=8a704fd3a717961614b7a4475c5c86cbb659faca;hb=2b25c0cafdddc108712f89d1a4e4ade858fbe854;hp=c60c86b5c578aa3fd7306818f78a4b819a9f3b6e;hpb=328cd76b365ba8ea45127e06bb4bf87d6da0709b;p=swftools.git diff --git a/lib/gfxfont.c b/lib/gfxfont.c index c60c86b..8a704fd 100644 --- a/lib/gfxfont.c +++ b/lib/gfxfont.c @@ -21,11 +21,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "../config.h" #include "gfxdevice.h" #include "gfxtools.h" static int loadfont_scale = 64; -static int skip_unused = 0; static int full_unicode = 1; #ifdef HAVE_FREETYPE @@ -55,9 +55,15 @@ static int full_unicode = 1; #define FT_SCALE 1 #define FT_SUBPIXELS 64 +typedef struct _gfxdrawinfo_t { + gfxdrawer_t* draw; + double quality; +} gfxdrawinfo_t; + static int ft_move_to(FT_Vector* _to, void* user) { - gfxdrawer_t* draw = (gfxdrawer_t*)user; + gfxdrawinfo_t* info = (gfxdrawinfo_t*)user; + gfxdrawer_t* draw = info->draw; double x = _to->x*FT_SCALE/(float)FT_SUBPIXELS; double y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS; draw->moveTo(draw, x,y); @@ -65,7 +71,8 @@ static int ft_move_to(FT_Vector* _to, void* user) } static int ft_line_to(FT_Vector* _to, void* user) { - gfxdrawer_t* draw = (gfxdrawer_t*)user; + gfxdrawinfo_t* info = (gfxdrawinfo_t*)user; + gfxdrawer_t* draw = info->draw; double x = _to->x*FT_SCALE/(float)FT_SUBPIXELS; double y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS; draw->lineTo(draw, x,y); @@ -73,24 +80,26 @@ static int ft_line_to(FT_Vector* _to, void* user) } static int ft_cubic_to(FT_Vector* _c1, FT_Vector* _c2, FT_Vector* _to, void* user) { - gfxdrawer_t* draw = (gfxdrawer_t*)user; + gfxdrawinfo_t* info = (gfxdrawinfo_t*)user; + gfxdrawer_t* draw = info->draw; double tox = _to->x*FT_SCALE/(float)FT_SUBPIXELS; double toy = -_to->y*FT_SCALE/(float)FT_SUBPIXELS; double c1x = _c1->x*FT_SCALE/(float)FT_SUBPIXELS; double c1y = -_c1->y*FT_SCALE/(float)FT_SUBPIXELS; double c2x = _c2->x*FT_SCALE/(float)FT_SUBPIXELS; double c2y = -_c2->y*FT_SCALE/(float)FT_SUBPIXELS; - gfxdraw_cubicTo(draw, c1x, c1y, c2x, c2y, tox, toy); + gfxdraw_cubicTo(draw, c1x, c1y, c2x, c2y, tox, toy, info->quality); return 0; } static int ft_conic_to(FT_Vector* _c, FT_Vector* _to, void* user) { - gfxdrawer_t* draw = (gfxdrawer_t*)user; + gfxdrawinfo_t* info = (gfxdrawinfo_t*)user; + gfxdrawer_t* draw = info->draw; double tox = _to->x*FT_SCALE/(float)FT_SUBPIXELS; double toy = -_to->y*FT_SCALE/(float)FT_SUBPIXELS; double cx = _c->x*FT_SCALE/(float)FT_SUBPIXELS; double cy = -_c->y*FT_SCALE/(float)FT_SUBPIXELS; - gfxdraw_conicTo(draw, cx,cy, tox,toy); + gfxdraw_conicTo(draw, cx,cy, tox,toy, info->quality); return 0; } static FT_Outline_Funcs outline_functions = @@ -125,27 +134,13 @@ static void glyph_clear(gfxglyph_t*g) gfxline_free(g->line);g->line = 0; } -void gfxfont_free(gfxfont_t*font) -{ - int t; - for(t=0;tnum_glyphs;t++) { - glyph_clear(&font->glyphs[t]); - } - if(font->glyphs) { - free(font->glyphs);font->glyphs = 0; - } - font->num_glyphs = 0; - if(font->unicode2glyph) { - free(font->unicode2glyph);font->unicode2glyph = 0; - } - free(font); -} +static int errorno = 0; -gfxfont_t* gfxfont_load(char*filename) +gfxfont_t* gfxfont_load(char*filename, double quality) { FT_Face face; FT_Error error; - const char* name = 0; + const char* fontname = 0; FT_ULong charcode; FT_UInt gindex; gfxfont_t* font; @@ -156,7 +151,9 @@ gfxfont_t* gfxfont_load(char*filename) int max_unicode = 0; int charmap = -1; int isunicode = 1; - + int has_had_errors = 0; + int num_names = 0; + if(ftlibrary == 0) { if(FT_Init_FreeType(&ftlibrary)) { fprintf(stderr, "Couldn't init freetype library!\n"); @@ -191,9 +188,7 @@ gfxfont_t* gfxfont_load(char*filename) //font->glyphnames = rfx_calloc(face->num_glyphs*sizeof(char*)); } - /*name = FT_Get_Postscript_Name(face); - if(name && *name) - font->name = strdup(name);*/ + fontname = FT_Get_Postscript_Name(face); while(1) { @@ -219,7 +214,6 @@ gfxfont_t* gfxfont_load(char*filename) if(font->max_unicode == 0 && charmap < face->num_charmaps - 1) { charmap++; FT_Set_Charmap(face, face->charmaps[charmap]); - //font->encoding = 0;//anything but unicode FIXME isunicode = 0; } else break; @@ -249,85 +243,139 @@ gfxfont_t* gfxfont_load(char*filename) font->num_glyphs = 0; + + for(t=0; t < face->num_glyphs; t++) { + if(FT_HAS_GLYPH_NAMES(face)) { + char name[128]; + error = FT_Get_Glyph_Name(face, t, name, 127); + if(!error && name[0] && !strstr(name, "notdef")) { + num_names++; + } + } + } + + for(t=0; t < face->num_glyphs; t++) { FT_Glyph glyph; FT_BBox bbox; FT_Matrix matrix; char name[128]; gfxdrawer_t draw; + gfxdrawinfo_t info; int ret; char hasname = 0; + int omit = 0; name[0]=0; - if(FT_HAS_GLYPH_NAMES(face)) { + + font->glyphs[font->num_glyphs].advance = 0; + font->glyphs[font->num_glyphs].line = 0; + font->glyphs[font->num_glyphs].unicode = glyph2unicode[t]; + font->glyphs[font->num_glyphs].name = 0; + + if(FT_HAS_GLYPH_NAMES(face) && (num_names >= face->num_glyphs/10 || num_names > 2)) { + name[0] = 0; error = FT_Get_Glyph_Name(face, t, name, 127); if(!error && name[0] && !strstr(name, "notdef")) { font->glyphs[font->num_glyphs].name = strdup(name); hasname = 1; } } - if(!glyph2unicode[t] && !hasname && skip_unused) { - continue; - } - error = FT_Load_Glyph(face, t, FT_LOAD_NO_BITMAP); - if(error) { - fprintf(stderr, "Couldn't load glyph %d, error:%d\n", t, error); - continue; - } - error = FT_Get_Glyph(face->glyph, &glyph); - if(error) { - fprintf(stderr, "Couldn't get glyph %d, error:%d\n", t, error); - continue; + if(has_had_errors && (isunicode && !glyph2unicode[t]) && !hasname) { + /* some freetype versions crash or corrupt memory if we try to load + characters (without unicode index or name) above 256 for some fonts. + So skip those characters once the first error occured */ + omit = 1; } + if(!omit) { + error = FT_Load_Glyph(face, t, FT_LOAD_NO_BITMAP); + if(error) { + if(hasname) + fprintf(stderr, "Warning: glyph %d/%d (unicode %d, name %s) has return code %d\n", t, face->num_glyphs, glyph2unicode[t], name, error); + else + fprintf(stderr, "Warning: glyph %d/%d (unicode %d) has return code %d\n", t, face->num_glyphs, glyph2unicode[t], error); + omit = 2; - FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_unscaled, &bbox); - bbox.yMin = -bbox.yMin; - bbox.yMax = -bbox.yMax; - if(bbox.xMax < bbox.xMin) { - // swap - bbox.xMax ^= bbox.xMin; - bbox.xMin ^= bbox.xMax; - bbox.xMax ^= bbox.xMin; +#if 0 + if(!has_had_errors) { + char buf[256]; + if(fontname && *fontname) { + fprintf(stderr, "font has been copied to %s.ttf\n", fontname); + sprintf(buf, "cp %s %s.ttf", filename, fontname); + } else { + fprintf(stderr, "font has been copied to badfont%d.ttf\n", errorno); + sprintf(buf, "cp %s badfont%d.ttf", filename, errorno); + errorno++; + } + system(buf); + } +#endif + has_had_errors = 1; + } } - if(bbox.yMax < bbox.yMin) { - // swap - bbox.yMax ^= bbox.yMin; - bbox.yMin ^= bbox.yMax; - bbox.yMax ^= bbox.yMin; + if(!omit) { + error = FT_Get_Glyph(face->glyph, &glyph); + if(error) { + fprintf(stderr, "Couldn't get glyph %d/%d, error:%d\n", t, face->num_glyphs, error); + omit = 3; + } } - gfxdrawer_target_gfxline(&draw); - - //error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &draw); - error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &draw); - - if(error) { - fprintf(stderr, "Couldn't decompose glyph %d\n", t); - gfxline_free((gfxline_t*)draw.result(&draw)); - continue; + if(!omit) { + gfxline_t*l; + int ok=0; + gfxdrawer_target_gfxline(&draw); + info.draw = &draw; + info.quality = quality; + + //error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info); + error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info); + + if(error) { + fprintf(stderr, "Couldn't decompose glyph %d\n", t); + gfxline_free((gfxline_t*)draw.result(&draw)); + FT_Done_Glyph(glyph); + omit = 4; + } else { + font->glyphs[font->num_glyphs].advance = glyph->advance.x*20/65536; + font->glyphs[font->num_glyphs].line = (gfxline_t*)draw.result(&draw); + } + l = font->glyphs[font->num_glyphs].line; + while(l) { + if(l->type != gfx_moveTo) { + ok = 1; + } + l = l->next; + } + if(!ok && !name) { + gfxline_free(font->glyphs[font->num_glyphs].line); + font->glyphs[font->num_glyphs].line = 0; + font->glyphs[font->num_glyphs].advance = 0; + + /* Some PDFs created e.g. by InDesign tend to create + fonts with reduced (empty) characters, which still + have unicode indices attached to them. + Remove that information, in order to not confuse + any converter applications. + */ + font->glyphs[font->num_glyphs].unicode = 0; + if(font->glyphs[font->num_glyphs].name) { + free(font->glyphs[font->num_glyphs].name); + font->glyphs[font->num_glyphs].name = 0; + } + FT_Done_Glyph(glyph); + omit = 5; + } } -#if 0 - if(bbox.xMin > 0) { - font->glyph[font->num_glyphs].advance = (bbox.xMax*20*FT_SCALE)/FT_SUBPIXELS; - } else { - font->glyph[font->num_glyphs].advance = ((bbox.xMax - bbox.xMin)*20*FT_SCALE)/FT_SUBPIXELS; + if(!omit) { + FT_Done_Glyph(glyph); + font->glyphs[font->num_glyphs].unicode = glyph2unicode[t]; } -#else - font->glyphs[font->num_glyphs].advance = glyph->advance.x*20/65536; -#endif - - font->glyphs[font->num_glyphs].line = (gfxline_t*)draw.result(&draw); - - /*font->glyphs[font->num_glyphs].bbox.xmin = (bbox.xMin*FT_SCALE*20)/FT_SUBPIXELS; - font->glyphs[font->num_glyphs].bbox.ymin = (bbox.yMin*FT_SCALE*20)/FT_SUBPIXELS; - font->glyphs[font->num_glyphs].bbox.xmax = (bbox.xMax*FT_SCALE*20)/FT_SUBPIXELS; - font->glyphs[font->num_glyphs].bbox.ymax = (bbox.yMax*FT_SCALE*20)/FT_SUBPIXELS;*/ - FT_Done_Glyph(glyph); - font->glyphs[font->num_glyphs].unicode = glyph2unicode[t]; glyph2glyph[t] = font->num_glyphs; font->num_glyphs++; } + /* notice: if skip_unused is true, font->glyph2unicode, font->glyphnames and font->layout->bounds will have more memory allocated than just font->num_glyphs, but only the first font->numchars are used/valid */ @@ -342,8 +390,8 @@ gfxfont_t* gfxfont_load(char*filename) FT_Done_Face(face); FT_Done_FreeType(ftlibrary);ftlibrary=0; - - if(!isunicode && font->num_glyphs>0) { + + if(!isunicode && font->num_glyphs>0 && font->max_unicode) { /* if the encoding isn't unicode, remap the font so that the encoding equals the char position, and remove the unicode table */ @@ -404,3 +452,19 @@ gfxfont_t* gfxfont_load(char*filename) #endif +void gfxfont_free(gfxfont_t*font) +{ + int t; + for(t=0;tnum_glyphs;t++) { + glyph_clear(&font->glyphs[t]); + } + if(font->glyphs) { + free(font->glyphs);font->glyphs = 0; + } + font->num_glyphs = 0; + if(font->unicode2glyph) { + free(font->unicode2glyph);font->unicode2glyph = 0; + } + free(font); +} +