X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fgfxfont.c;h=549e50d58931d3272f6d1c50bfaa9c703a5947a5;hp=5004e18359b02a90f3201107b885a0586fe9ab8e;hb=879d0eec420fe0fd5ddcd56c8fe62b82a6744edd;hpb=b27d77f8a6343e60e2d3ae2c22a8096a6357a927 diff --git a/lib/gfxfont.c b/lib/gfxfont.c index 5004e18..549e50d 100644 --- a/lib/gfxfont.c +++ b/lib/gfxfont.c @@ -21,11 +21,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include +#include +#include #include "../config.h" #include "gfxdevice.h" #include "gfxtools.h" #include "gfxfont.h" #include "ttf.h" +#include "mem.h" +#include "log.h" static int loadfont_scale = 64; static int full_unicode = 1; @@ -140,7 +145,7 @@ static int errorno = 0; //#define DEBUG 1 -gfxfont_t* gfxfont_load(char*id, char*filename, unsigned int flags, double quality) +gfxfont_t* gfxfont_load(const char*id, const char*filename, unsigned int flags, double quality) { FT_Face face; FT_Error error; @@ -489,7 +494,7 @@ gfxfont_t* gfxfont_load(char*id, char*filename, unsigned int flags, double quali } #else -gfxfont_t* gfxfont_load(char*id, char*filename, unsigned int flags, double quality) +gfxfont_t* gfxfont_load(const char*id, const char*filename, unsigned int flags, double quality) { fprintf(stderr, "No freetype support compiled in! Not able to load %s\n", filename); return 0; @@ -520,7 +525,92 @@ void gfxfont_free(gfxfont_t*font) free(font); } -ttf_t* gfxfont_to_ttf(gfxfont_t*font) +static inline int invalid_unicode(int u) +{ + return (u<32 || (u>=0xe000 && u<0xf900)); +} +void gfxfont_fix_unicode(gfxfont_t*font) +{ + int t; + + /* find the current maximum unicode2glyph */ + int max = 0; + for(t=0;tnum_glyphs;t++) { + int u = font->glyphs[t].unicode; + if(u > max) + max = u; + } + char*used = rfx_calloc(max+1); + + /* now, remap all duplicates (and invalid characters) and + calculate the new maximum */ + int remap_pos=0; + max = 0; + for(t=0;tnum_glyphs;t++) { + int u = font->glyphs[t].unicode; + if(u>=0) { + if(used[u] || invalid_unicode(u)) { + u = font->glyphs[t].unicode = 0xe000 + remap_pos++; + } else { + used[u] = 1; + } + } + if(u > max) + max = u; + } + free(used); + if(font->unicode2glyph) { + free(font->unicode2glyph); + } + font->unicode2glyph = 0; + font->max_unicode = 0; +} + +void gfxfont_add_unicode2glyph(gfxfont_t*font) +{ + int t; + int max = 0; + for(t=0;tnum_glyphs;t++) { + int u = font->glyphs[t].unicode; + if(u > max) + max = u; + } + if(!font->unicode2glyph) { + /* (re)generate unicode2glyph-to-glyph mapping table by reverse mapping + the glyph unicode2glyph's indexes into the mapping table. For collisions, + we prefer the smaller unicode2glyph value.*/ + font->max_unicode = max+1; + font->unicode2glyph = malloc(sizeof(font->unicode2glyph[0])*(font->max_unicode)); + memset(font->unicode2glyph, -1, sizeof(font->unicode2glyph[0])*(font->max_unicode)); + + for(t=0;tnum_glyphs;t++) { + int u = font->glyphs[t].unicode; + if(u>=0) { + assert(font->unicode2glyph[u]<0); // we took care of duplicates, right? + assert(umax_unicode); + font->unicode2glyph[u] = t; + } + } + } else { + /* add the new glyph indexes (most probably, that's only the remapped values + at 0xe000) to the unicode2glyph table. Notice: Unlike glyph2unicode, we don't + care about collisions in the unicode2glyph table */ + int new_max_unicode = max+1; + if(font->max_unicode < new_max_unicode) { + font->unicode2glyph = rfx_realloc(font->unicode2glyph, sizeof(font->unicode2glyph[0])*(font->max_unicode)); + memset(font->unicode2glyph+font->max_unicode, -1, sizeof(font->unicode2glyph[0])*(new_max_unicode - font->max_unicode)); + } + for(t=0;tnum_glyphs;t++) { + int u = font->glyphs[t].unicode; + if(u>=0 && font->unicode2glyph[u]<0) { + font->unicode2glyph[u] = t; + } + } + font->max_unicode = new_max_unicode; + } +} + +ttf_t* gfxfont_to_ttf(gfxfont_t*font, char eot) { ttf_t*ttf = ttf_new(); int num_glyphs = font->num_glyphs; @@ -539,6 +629,7 @@ ttf_t* gfxfont_to_ttf(gfxfont_t*font) ttf->glyphs = rfx_calloc(num_glyphs*sizeof(ttfglyph_t)); double scale = 1.0; int max_unicode = font->max_unicode; + int remap_pos=0; for(t=0;tnum_glyphs;t++) { gfxglyph_t*src = &font->glyphs[t]; ttfglyph_t*dest = &ttf->glyphs[t+offset]; @@ -591,36 +682,75 @@ ttf_t* gfxfont_to_ttf(gfxfont_t*font) } } + if(eot) { + dest->bearing = dest->xmin; + /* for windows font rendering, make sure coordinates are always + to the right of the origin (and use bearing to shift them "back".) + Don't do this for non-windows platforms though because e.g. OS X + ignores bearing. */ + int xshift=0; + if(dest->xmin < 0) { + xshift = -dest->xmin; + for(s=0;spoints[s].x += xshift; + } + dest->xmin += xshift; + dest->xmax += xshift; + } + } dest->advance = src->advance*scale; - if(src->unicode > max_unicode) - max_unicode = src->unicode; + + //dest->xmin=0; //TODO: might be necessary for some font engines? + + dest->advance = src->advance*scale; + + int u = font->glyphs[t].unicode; + if(u > max_unicode) + max_unicode = u; } ttf->unicode_size = max_unicode+1; ttf->unicode = rfx_calloc(sizeof(unicode_t)*ttf->unicode_size); - int remap_pos=0; - for(t=0;tnum_glyphs;t++) { - gfxglyph_t*src = &font->glyphs[t]; - int u = font->glyphs[t].unicode; - if(u<32 || (u>=0xe000 && u<0xf900)) { - u = 0xe000 + remap_pos++; + + if(!font->unicode2glyph) { + for(t=0;tnum_glyphs;t++) { + gfxglyph_t*src = &font->glyphs[t]; + int u = font->glyphs[t].unicode; + if(u<=0) + continue; + if(u<32) { + msg(" gfxfont_to_ttf: glyph %d has an invalid unicode (%d)", t, u); + continue; + } else if(ttf->unicode[u]) { + msg(" gfxfont_to_ttf: glyph %d has a duplicate unicode (%d)", t, u); + continue; + } + if(uunicode_size) + ttf->unicode[u] = t+offset; } - if(u>=0) - ttf->unicode[u] = t+offset; - } - int u; - for(u=0;umax_unicode;u++) { - int g = font->unicode2glyph[u]; - if(u<32 || (u>=0xe000 && u<0xf900)) - continue; - if(g>=0 && !ttf->unicode[u]) { - ttf->unicode[u] = g+offset; + } else { + int u; + for(u=1;umax_unicode;u++) { + int g = font->unicode2glyph[u]; + if(g>=0 && u<32) { + msg(" gfxfont_to_ttf: Font contains an invalid unicode (%d)", u); + continue; + } + if(g>=0 && gnum_glyphs && !ttf->unicode[u]) { + ttf->unicode[u] = g+offset; + } } } + ttf->ascent = font->ascent; - ttf->descent = font->descent; - ttf->lineGap = font->ascent + font->descent; + ttf->descent = -font->descent; + ttf->lineGap = 0; - ttf->name = strdup(font->id); + ttf->full_name = strdup(font->id); + ttf->family_name = strdup(font->id); + ttf->subfamily_name = strdup(font->id); + ttf->postscript_name = strdup(font->id); + ttf->version_string = strdup("Version 1.0"); + ttf->font_uid = strdup(font->id); ttf_create_truetype_tables(ttf); return ttf; @@ -628,7 +758,15 @@ ttf_t* gfxfont_to_ttf(gfxfont_t*font) void gfxfont_save(gfxfont_t*font, const char*filename) { - ttf_t*ttf = gfxfont_to_ttf(font); + ttf_t*ttf = gfxfont_to_ttf(font, 0); ttf_save(ttf, filename); + ttf_destroy(ttf); +} + +void gfxfont_save_eot(gfxfont_t*font, const char*filename) +{ + ttf_t*ttf = gfxfont_to_ttf(font, 1); + ttf_save_eot(ttf, filename); + ttf_destroy(ttf); }