X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fgfxfont.c;h=8e392728b3fb343ea7fc656cb85c7e65d2adef18;hp=6ec1a4fc865af8e2f885ce0c1d7928a2c137c98b;hb=687def0f4060cf9e48dba017316314c05f7b0480;hpb=796482f45946c67804ab2ca5f8b33a020d71a779 diff --git a/lib/gfxfont.c b/lib/gfxfont.c index 6ec1a4f..8e39272 100644 --- a/lib/gfxfont.c +++ b/lib/gfxfont.c @@ -24,6 +24,8 @@ #include "../config.h" #include "gfxdevice.h" #include "gfxtools.h" +#include "gfxfont.h" +#include "ttf.h" static int loadfont_scale = 64; static int full_unicode = 1; @@ -60,7 +62,7 @@ typedef struct _gfxdrawinfo_t { double quality; } gfxdrawinfo_t; -static int ft_move_to(FT_Vector* _to, void* user) +static int ft_move_to(const FT_Vector* _to, void* user) { gfxdrawinfo_t* info = (gfxdrawinfo_t*)user; gfxdrawer_t* draw = info->draw; @@ -69,7 +71,7 @@ static int ft_move_to(FT_Vector* _to, void* user) draw->moveTo(draw, x,y); return 0; } -static int ft_line_to(FT_Vector* _to, void* user) +static int ft_line_to(const FT_Vector* _to, void* user) { gfxdrawinfo_t* info = (gfxdrawinfo_t*)user; gfxdrawer_t* draw = info->draw; @@ -78,7 +80,7 @@ static int ft_line_to(FT_Vector* _to, void* user) draw->lineTo(draw, x,y); return 0; } -static int ft_cubic_to(FT_Vector* _c1, FT_Vector* _c2, FT_Vector* _to, void* user) +static int ft_cubic_to(const FT_Vector* _c1, const FT_Vector* _c2, const FT_Vector* _to, void* user) { gfxdrawinfo_t* info = (gfxdrawinfo_t*)user; gfxdrawer_t* draw = info->draw; @@ -91,7 +93,7 @@ static int ft_cubic_to(FT_Vector* _c1, FT_Vector* _c2, FT_Vector* _to, void* use 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) +static int ft_conic_to(const FT_Vector* _c, const FT_Vector* _to, void* user) { gfxdrawinfo_t* info = (gfxdrawinfo_t*)user; gfxdrawer_t* draw = info->draw; @@ -129,14 +131,16 @@ static void glyph_clear(gfxglyph_t*g) { gfxline_t*line; if(g->name) { - free(g->name); g->name = 0; + free((void*)g->name); g->name = 0; } gfxline_free(g->line);g->line = 0; } static int errorno = 0; -gfxfont_t* gfxfont_load(char*filename, double quality) +//#define DEBUG 1 + +gfxfont_t* gfxfont_load(char*id, char*filename, unsigned int flags, double quality) { FT_Face face; FT_Error error; @@ -147,7 +151,6 @@ gfxfont_t* gfxfont_load(char*filename, double quality) int t; int*glyph2glyph = 0; int*glyph2unicode = 0; - FT_Size size; int max_unicode = 0; int charmap = -1; int isunicode = 1; @@ -162,27 +165,31 @@ gfxfont_t* gfxfont_load(char*filename, double quality) } error = FT_New_Face(ftlibrary, filename, 0, &face); FT_Set_Pixel_Sizes (face, 16*loadfont_scale, 16*loadfont_scale); +#ifdef DEBUG + printf("gfxfont_load(%s, %s, %f)\n", id, filename, quality); +#endif if(error) { - fprintf(stderr, "Couldn't load file %s- not a TTF file?\n", filename); + fprintf(stderr, "Couldn't load file %s- not a TTF file? (error=%02x)\n", filename, error); return 0; } if(face->num_glyphs <= 0) { - fprintf(stderr, "File %s contains %d glyphs\n", face->num_glyphs); + fprintf(stderr, "File %s contains %d glyphs\n", filename, (int)face->num_glyphs); return 0; } - font = rfx_calloc(sizeof(gfxfont_t)); + font = (gfxfont_t*)rfx_calloc(sizeof(gfxfont_t)); //font->style = ((face->style_flags&FT_STYLE_FLAG_ITALIC)?FONT_STYLE_ITALIC:0) |((face->style_flags&FT_STYLE_FLAG_BOLD)?FONT_STYLE_BOLD:0); //font->ascent = abs(face->ascender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMin; //font->descent = abs(face->descender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMax; //font->leading = font->layout->ascent + font->layout->descent; //font->encoding = FONT_ENCODING_UNICODE; font->max_unicode = 0; + font->id = strdup(id); - font->glyphs = rfx_calloc(face->num_glyphs*sizeof(gfxglyph_t)); - glyph2unicode = rfx_calloc(face->num_glyphs*sizeof(int)); - glyph2glyph = rfx_calloc(face->num_glyphs*sizeof(int)); + font->glyphs = (gfxglyph_t*)rfx_calloc(face->num_glyphs*sizeof(gfxglyph_t)); + glyph2unicode = (int*)rfx_calloc(face->num_glyphs*sizeof(int)); + glyph2glyph = (int*)rfx_calloc(face->num_glyphs*sizeof(int)); if(FT_HAS_GLYPH_NAMES(face)) { //font->glyphnames = rfx_calloc(face->num_glyphs*sizeof(char*)); @@ -190,9 +197,22 @@ gfxfont_t* gfxfont_load(char*filename, double quality) fontname = FT_Get_Postscript_Name(face); +#ifdef DEBUG + for(t=0;tnum_charmaps;t++) { + printf("possible encoding: %c%c%c%c (%d of %d)\n", + (face->charmaps[t]->encoding >> 24)&255, + (face->charmaps[t]->encoding >> 16)&255, + (face->charmaps[t]->encoding >> 8)&255, + (face->charmaps[t]->encoding >> 0)&255, + t+1, face->num_charmaps + ); + } +#endif + while(1) { charcode = FT_Get_First_Char(face, &gindex); + while(gindex != 0) { if(gindex >= 0 && gindexnum_glyphs) { @@ -206,13 +226,31 @@ gfxfont_t* gfxfont_load(char*filename, double quality) charcode = FT_Get_Next_Char(face, charcode, &gindex); } +#ifdef DEBUG + if(face->charmap) { + printf("ENCODING: %c%c%c%c (%d of %d) max_unicode=%d\n", + (face->charmap->encoding >> 24)&255, + (face->charmap->encoding >> 16)&255, + (face->charmap->encoding >> 8)&255, + (face->charmap->encoding >> 0)&255, + charmap, face->num_charmaps, font->max_unicode + ); + } else { + printf("ENCODING: NONE (%d of %d) max_unicode=%d\n", + charmap, face->num_charmaps, font->max_unicode + ); + } +#endif + /* if we didn't find a single encoding character, try the font's charmaps instead. That usually means that the encoding is no longer unicode. TODO: find a way to convert the encoding to unicode */ - if(font->max_unicode == 0 && charmap < face->num_charmaps-1 && - face->charmaps[charmap+1]->encoding != 0x41444243 /* custom */) + if(font->max_unicode == 0 && charmap < face->num_charmaps-1 + && face->charmaps[charmap+1]->encoding != 0x41444243 /* adbc, custom */ + && face->charmaps[charmap+1]->encoding != 0x61726d6e /* armn */ + ) { charmap++; FT_Set_Charmap(face, face->charmaps[charmap]); @@ -220,14 +258,13 @@ gfxfont_t* gfxfont_load(char*filename, double quality) } else break; } - /* TODO: if isunicode is 1, we now need to permutate the character order so that each character is at it's encoding position */ if(full_unicode) font->max_unicode = 65535; - font->unicode2glyph = rfx_calloc(font->max_unicode*sizeof(int)); + font->unicode2glyph = (int*)rfx_calloc(font->max_unicode*sizeof(int)); for(t=0;tmax_unicode;t++) { int g = FT_Get_Char_Index(face, t); @@ -235,6 +272,9 @@ gfxfont_t* gfxfont_load(char*filename, double quality) g = -1; font->unicode2glyph[t] = g; if(g>=0) { +#ifdef DEBUG + printf("u%d ->%d\n", t, g); +#endif max_unicode = t+1; if(!glyph2unicode[g]) { glyph2unicode[g] = t; @@ -259,12 +299,9 @@ gfxfont_t* gfxfont_load(char*filename, double quality) 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; @@ -282,19 +319,24 @@ gfxfont_t* gfxfont_load(char*filename, double quality) hasname = 1; } } - if(has_had_errors && (isunicode && !glyph2unicode[t]) && !hasname) { + +#if 0 // some cantonese pdfs fail to work if this is activated + + if(has_had_errors && (isunicode && !glyph2unicode[t]) && !hasname && t>=256) { /* 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; } +#endif + 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); + fprintf(stderr, "Warning: glyph %d/%d (unicode %d, name %s) has return code %d\n", t, (int)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); + fprintf(stderr, "Warning: glyph %d/%d (unicode %d) has return code %d\n", t, (int)face->num_glyphs, glyph2unicode[t], error); omit = 2; #if 0 @@ -317,7 +359,7 @@ gfxfont_t* gfxfont_load(char*filename, double quality) 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); + fprintf(stderr, "Couldn't get glyph %d/%d, error:%d\n", t, (int)face->num_glyphs, error); omit = 3; } } @@ -338,7 +380,7 @@ gfxfont_t* gfxfont_load(char*filename, double quality) FT_Done_Glyph(glyph); omit = 4; } else { - font->glyphs[font->num_glyphs].advance = (glyph->advance.x*20)/65536; + font->glyphs[font->num_glyphs].advance = glyph->advance.x/65536; font->glyphs[font->num_glyphs].line = (gfxline_t*)draw.result(&draw); } l = font->glyphs[font->num_glyphs].line; @@ -361,7 +403,7 @@ gfxfont_t* gfxfont_load(char*filename, double quality) */ font->glyphs[font->num_glyphs].unicode = 0; if(font->glyphs[font->num_glyphs].name) { - free(font->glyphs[font->num_glyphs].name); + free((void*)font->glyphs[font->num_glyphs].name); font->glyphs[font->num_glyphs].name = 0; } FT_Done_Glyph(glyph); @@ -398,7 +440,7 @@ gfxfont_t* gfxfont_load(char*filename, double quality) so that the encoding equals the char position, and remove the unicode table */ int t; - gfxglyph_t*newglyphs = rfx_calloc(font->max_unicode*sizeof(gfxglyph_t)); + gfxglyph_t*newglyphs = (gfxglyph_t*)rfx_calloc(font->max_unicode*sizeof(gfxglyph_t)); for(t=0;tunicode2glyph[t]; @@ -447,9 +489,10 @@ gfxfont_t* gfxfont_load(char*filename, double quality) } #else -gfxfont_t* gfxfont_load(char*filename) +gfxfont_t* gfxfont_load(char*id, char*filename, unsigned int flags, double quality) { fprintf(stderr, "No freetype support compiled in! Not able to load %s\n", filename); + return 0; } #endif @@ -467,6 +510,117 @@ void gfxfont_free(gfxfont_t*font) if(font->unicode2glyph) { free(font->unicode2glyph);font->unicode2glyph = 0; } + if(font->id) { + free((void*)font->id);font->id=0; + } + if(font->kerning) { + free(font->kerning);font->kerning=0; + } + free(font); } +ttf_t* gfxfont_to_ttf(gfxfont_t*font) +{ + ttf_t*ttf = ttf_new(); + int num_glyphs = font->num_glyphs; + int offset = 0; + int t; + char has_nondef_glyph = + font->num_glyphs && font->glyphs[0].unicode==-1 && + (!font->glyphs[0].line || !font->glyphs[0].line->next); + + if(!has_nondef_glyph) { + /* insert a new .nondef glyph at the start of the font */ + offset++; + num_glyphs++; + } + ttf->num_glyphs = num_glyphs; + ttf->glyphs = rfx_calloc(num_glyphs*sizeof(ttfglyph_t)); + double scale = 1.0; + int max_unicode = font->max_unicode; + for(t=0;tnum_glyphs;t++) { + gfxglyph_t*src = &font->glyphs[t]; + ttfglyph_t*dest = &ttf->glyphs[t+offset]; + gfxline_t*line = src->line; + int count = 0; + while(line) { + count++; + if(line->type == gfx_splineTo) + count++; + line=line->next; + } + dest->num_points = count; + dest->points = rfx_calloc(count*sizeof(ttfpoint_t)); + count = 0; + line = src->line; + while(line) { + if(line->type == gfx_splineTo) { + dest->points[count].x = line->sx*scale; + dest->points[count].y = line->sy*scale; + count++; + } + dest->points[count].x = line->x*scale; + dest->points[count].y = line->y*scale; + dest->points[count].flags |= GLYPH_ON_CURVE; + if(line->type == gfx_moveTo) { + dest->points[count].flags |= GLYPH_CONTOUR_START; + if(count) + dest->points[count-1].flags |= GLYPH_CONTOUR_END; + } + count++; + line=line->next; + } + if(count) + dest->points[count-1].flags |= GLYPH_CONTOUR_END; + + /* compute bounding box */ + int s; + if(count) { + dest->xmin = dest->xmax = dest->points[0].x; + dest->ymin = dest->ymax = dest->points[0].y; + for(s=1;spoints[s].x < dest->xmin) + dest->xmin = dest->points[s].x; + if(dest->points[s].y < dest->ymin) + dest->ymin = dest->points[s].y; + if(dest->points[s].x > dest->xmax) + dest->xmax = dest->points[s].x; + if(dest->points[s].y > dest->ymax) + dest->ymax = dest->points[s].y; + } + } + + dest->advance = src->advance*scale; + if(src->unicode > max_unicode) + max_unicode = src->unicode; + } + ttf->unicode_size = max_unicode+1; + ttf->unicode = rfx_calloc(sizeof(unicode_t)*ttf->unicode_size); + for(t=0;tnum_glyphs;t++) { + gfxglyph_t*src = &font->glyphs[t]; + int u = font->glyphs[t].unicode; + if(u>=0) + ttf->unicode[u] = t+offset; + } + int u; + for(u=0;umax_unicode;u++) { + int g = font->unicode2glyph[u]; + if(g>=0) { + ttf->unicode[u] = g+offset; + } + } + ttf->ascent = font->ascent; + ttf->descent = font->descent; + ttf->lineGap = font->ascent + font->descent; + + ttf_create_truetype_tables(ttf); + return ttf; +} + +void gfxfont_save(gfxfont_t*font, const char*filename) +{ + ttf_t*ttf = gfxfont_to_ttf(font); + ttf_save(ttf, filename); +} +