e99816c997517fee2f301f59015c5845e79507dc
[swftools.git] / lib / gfxfont.c
1 /* swffont.c
2
3    Functions for loading external fonts.
4
5    Extension module for the rfxswf library.
6    Part of the swftools package.
7
8    Copyright (c) 2003, 2004, 2005 Matthias Kramm
9  
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
23
24 #include <assert.h>
25 #include "../config.h"
26 #include "gfxdevice.h"
27 #include "gfxtools.h"
28 #include "gfxfont.h"
29 #include "ttf.h"
30 #include "mem.h"
31
32 static int loadfont_scale = 64;
33 static int full_unicode = 1;
34
35 #ifdef HAVE_FREETYPE
36
37 #ifdef HAVE_FT2BUILD_H
38 #include <ft2build.h>
39 #include FT_FREETYPE_H
40 #include FT_GLYPH_H
41 #include FT_SIZES_H
42 #include FT_SFNT_NAMES_H
43 #include FT_TRUETYPE_IDS_H
44 #include FT_OUTLINE_H
45 #else
46 #include <freetype/freetype.h>
47 #include <freetype/ftglyph.h>
48 #include <freetype/ftsizes.h>
49 #include <freetype/ftsnames.h>
50 #include <freetype/ttnameid.h>
51 #include <freetype/ftoutln.h>
52 #endif
53
54 /* Setting subpixels to 64 also means that the "point size" of the
55    font outlines will be 64. So the font, when rendered at original
56    size (i.e., the swf fontsize is 1024) will have the same size as
57    if it was rendered at 64pt */
58
59 #define FT_SCALE 1
60 #define FT_SUBPIXELS 64
61
62 typedef struct _gfxdrawinfo_t {
63     gfxdrawer_t* draw;
64     double quality;
65 } gfxdrawinfo_t;
66
67 static int ft_move_to(const FT_Vector* _to, void* user) 
68 {
69     gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
70     gfxdrawer_t* draw = info->draw;
71     double x = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
72     double y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
73     draw->moveTo(draw, x,y);
74     return 0;
75 }
76 static int ft_line_to(const FT_Vector* _to, void* user) 
77 {
78     gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
79     gfxdrawer_t* draw = info->draw;
80     double x = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
81     double y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
82     draw->lineTo(draw, x,y);
83     return 0;
84 }
85 static int ft_cubic_to(const FT_Vector* _c1, const FT_Vector* _c2, const FT_Vector* _to, void* user)
86 {
87     gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
88     gfxdrawer_t* draw = info->draw;
89     double tox = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
90     double toy = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
91     double c1x = _c1->x*FT_SCALE/(float)FT_SUBPIXELS;
92     double c1y = -_c1->y*FT_SCALE/(float)FT_SUBPIXELS;
93     double c2x = _c2->x*FT_SCALE/(float)FT_SUBPIXELS;
94     double c2y = -_c2->y*FT_SCALE/(float)FT_SUBPIXELS;
95     gfxdraw_cubicTo(draw, c1x, c1y, c2x, c2y, tox, toy, info->quality);
96     return 0;
97 }
98 static int ft_conic_to(const FT_Vector* _c, const FT_Vector* _to, void* user) 
99 {
100     gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
101     gfxdrawer_t* draw = info->draw;
102     double tox = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
103     double toy = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
104     double cx = _c->x*FT_SCALE/(float)FT_SUBPIXELS;
105     double cy = -_c->y*FT_SCALE/(float)FT_SUBPIXELS;
106     gfxdraw_conicTo(draw, cx,cy, tox,toy, info->quality);
107     return 0;
108 }
109 static FT_Outline_Funcs outline_functions =
110 {
111   ft_move_to,
112   ft_line_to,
113   ft_conic_to,
114   ft_cubic_to,
115   0,0
116 };
117
118 static FT_Library ftlibrary = 0;
119
120 static gfxglyph_t cloneGlyph(gfxglyph_t*src)
121 {
122     gfxglyph_t dest;
123     memset(&dest, 0, sizeof(dest));
124     if(src->name)
125         dest.name = strdup(src->name);
126     dest.advance = src->advance;
127     dest.unicode = src->unicode;
128     dest.line = gfxline_clone(src->line);
129     return dest;
130 }
131
132 static void glyph_clear(gfxglyph_t*g)
133 {
134     gfxline_t*line;
135     if(g->name) {
136         free((void*)g->name); g->name = 0;
137     }
138     gfxline_free(g->line);g->line = 0;
139 }
140
141 static int errorno = 0;
142
143 //#define DEBUG 1
144
145 gfxfont_t* gfxfont_load(char*id, char*filename, unsigned int flags, double quality)
146 {
147     FT_Face face;
148     FT_Error error;
149     const char* fontname = 0;
150     FT_ULong charcode;
151     FT_UInt gindex;
152     gfxfont_t* font;
153     int t;
154     int*glyph2glyph = 0;
155     int*glyph2unicode = 0;
156     int max_unicode = 0;
157     int charmap = -1;
158     int isunicode = 1;
159     int has_had_errors = 0;
160     int num_names = 0;
161
162     if(ftlibrary == 0) {
163         if(FT_Init_FreeType(&ftlibrary)) {
164             fprintf(stderr, "Couldn't init freetype library!\n");
165             exit(1);
166         }
167     }
168     error = FT_New_Face(ftlibrary, filename, 0, &face);
169     FT_Set_Pixel_Sizes (face, 16*loadfont_scale, 16*loadfont_scale);
170 #ifdef DEBUG
171     printf("gfxfont_load(%s, %s, %f)\n", id, filename, quality);
172 #endif
173
174     if(error) {
175         fprintf(stderr, "Couldn't load file %s- not a TTF file? (error=%02x)\n", filename, error);
176         return 0;
177     }
178     if(face->num_glyphs <= 0) {
179         fprintf(stderr, "File %s contains %d glyphs\n", filename, (int)face->num_glyphs);
180         return 0;
181     }
182
183     font = (gfxfont_t*)rfx_calloc(sizeof(gfxfont_t));
184     //font->style =  ((face->style_flags&FT_STYLE_FLAG_ITALIC)?FONT_STYLE_ITALIC:0) |((face->style_flags&FT_STYLE_FLAG_BOLD)?FONT_STYLE_BOLD:0);
185     //font->ascent = abs(face->ascender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMin;
186     //font->descent = abs(face->descender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMax;
187     //font->leading = font->layout->ascent + font->layout->descent;
188     //font->encoding = FONT_ENCODING_UNICODE;
189     font->max_unicode = 0;
190     font->id = strdup(id);
191     
192     font->glyphs = (gfxglyph_t*)rfx_calloc(face->num_glyphs*sizeof(gfxglyph_t));
193     glyph2unicode = (int*)rfx_calloc(face->num_glyphs*sizeof(int));
194     glyph2glyph = (int*)rfx_calloc(face->num_glyphs*sizeof(int));
195
196     if(FT_HAS_GLYPH_NAMES(face)) {
197         //font->glyphnames = rfx_calloc(face->num_glyphs*sizeof(char*));
198     }
199
200     fontname = FT_Get_Postscript_Name(face);
201
202 #ifdef DEBUG
203     for(t=0;t<face->num_charmaps;t++) {
204         printf("possible encoding: %c%c%c%c (%d of %d)\n", 
205                 (face->charmaps[t]->encoding >> 24)&255,
206                 (face->charmaps[t]->encoding >> 16)&255,
207                 (face->charmaps[t]->encoding >> 8)&255,
208                 (face->charmaps[t]->encoding >> 0)&255,
209                 t+1, face->num_charmaps
210                 );
211     }
212 #endif
213
214     while(1) 
215     {
216         charcode = FT_Get_First_Char(face, &gindex);
217
218         while(gindex != 0)
219         {
220             if(gindex >= 0 && gindex<face->num_glyphs) {
221                 if(!glyph2unicode[gindex]) {
222                     glyph2unicode[gindex] = charcode;
223                     if(charcode + 1 > font->max_unicode) {
224                         font->max_unicode = charcode + 1;
225                     }
226                 }
227             }
228             charcode = FT_Get_Next_Char(face, charcode, &gindex);
229         }
230
231 #ifdef DEBUG
232         if(face->charmap) {
233             printf("ENCODING: %c%c%c%c (%d of %d) max_unicode=%d\n", 
234                     (face->charmap->encoding >> 24)&255,
235                     (face->charmap->encoding >> 16)&255,
236                     (face->charmap->encoding >> 8)&255,
237                     (face->charmap->encoding >> 0)&255,
238                     charmap, face->num_charmaps, font->max_unicode
239                     );
240         } else {
241             printf("ENCODING: NONE (%d of %d) max_unicode=%d\n",
242                     charmap, face->num_charmaps, font->max_unicode
243                     );
244         }
245 #endif
246
247         /* if we didn't find a single encoding character, try
248            the font's charmaps instead. That usually means that
249            the encoding is no longer unicode. 
250            TODO: find a way to convert the encoding to unicode
251          */
252         if(font->max_unicode == 0 && charmap < face->num_charmaps-1
253                 && face->charmaps[charmap+1]->encoding != 0x41444243 /* adbc, custom */
254                 && face->charmaps[charmap+1]->encoding != 0x61726d6e    /* armn */
255                 )
256                 {
257             charmap++;
258             FT_Set_Charmap(face, face->charmaps[charmap]);
259             isunicode = 0;
260         } else
261             break;
262     }
263     /* TODO: if isunicode is 1, we now need to permutate the character
264              order so that each character is at it's encoding position */
265
266     if(full_unicode)
267         font->max_unicode = 65535;
268     
269     font->unicode2glyph = (int*)rfx_calloc(font->max_unicode*sizeof(int));
270     
271     for(t=0;t<font->max_unicode;t++) {
272         int g = FT_Get_Char_Index(face, t);
273         if(!g || g>=face->num_glyphs)
274             g = -1;
275         font->unicode2glyph[t] = g;
276         if(g>=0) {
277 #ifdef DEBUG
278             printf("u%d ->%d\n", t, g);
279 #endif
280             max_unicode = t+1;
281             if(!glyph2unicode[g]) {
282                 glyph2unicode[g] = t;
283             }
284         }
285     }
286     font->max_unicode = max_unicode;
287
288     font->num_glyphs = 0;
289
290
291     for(t=0; t < face->num_glyphs; t++) {
292         if(FT_HAS_GLYPH_NAMES(face)) {
293             char name[128];
294             error = FT_Get_Glyph_Name(face, t, name, 127);
295             if(!error && name[0] && !strstr(name, "notdef")) {
296                 num_names++;
297             }
298         }
299     }
300
301
302     for(t=0; t < face->num_glyphs; t++) {
303         FT_Glyph glyph;
304         char name[128];
305         gfxdrawer_t draw;
306         gfxdrawinfo_t info;
307         char hasname = 0;
308         int omit = 0;
309         name[0]=0;
310         
311         font->glyphs[font->num_glyphs].advance = 0;
312         font->glyphs[font->num_glyphs].line = 0;
313         font->glyphs[font->num_glyphs].unicode = glyph2unicode[t];
314         font->glyphs[font->num_glyphs].name = 0;
315
316         if(FT_HAS_GLYPH_NAMES(face) && (num_names >= face->num_glyphs/10 || num_names > 2)) {
317             name[0] = 0;
318             error = FT_Get_Glyph_Name(face, t, name, 127);
319             if(!error && name[0] && !strstr(name, "notdef")) {
320                 font->glyphs[font->num_glyphs].name = strdup(name);
321                 hasname = 1;
322             }
323         }
324
325 #if 0 // some cantonese pdfs fail to work if this is activated
326
327         if(has_had_errors && (isunicode && !glyph2unicode[t]) && !hasname && t>=256) {
328             /* some freetype versions crash or corrupt memory if we try to load
329                characters (without unicode index or name) above 256 for some fonts.
330                So skip those characters once the first error occured */
331             omit = 1;
332         }
333 #endif
334
335         if(!omit) {
336             error = FT_Load_Glyph(face, t, FT_LOAD_NO_BITMAP);
337             if(error) {
338                 if(hasname)
339                     fprintf(stderr, "Warning: glyph %d/%d (unicode %d, name %s) has return code %d\n", t, (int)face->num_glyphs, glyph2unicode[t], name, error);
340                 else
341                     fprintf(stderr, "Warning: glyph %d/%d (unicode %d) has return code %d\n", t, (int)face->num_glyphs, glyph2unicode[t], error);
342                 omit = 2;
343
344 #if 0
345                 if(!has_had_errors) {
346                     char buf[256];
347                     if(fontname && *fontname) {
348                         fprintf(stderr, "font has been copied to %s.ttf\n", fontname);
349                         sprintf(buf, "cp %s %s.ttf", filename, fontname);
350                     } else {
351                         fprintf(stderr, "font has been copied to badfont%d.ttf\n", errorno);
352                         sprintf(buf, "cp %s badfont%d.ttf", filename, errorno);
353                         errorno++;
354                     }
355                     system(buf);
356                 }
357 #endif
358                 has_had_errors = 1;
359             }
360         }
361         if(!omit) {
362             error = FT_Get_Glyph(face->glyph, &glyph);
363             if(error) {
364                 fprintf(stderr, "Couldn't get glyph %d/%d, error:%d\n", t, (int)face->num_glyphs, error);
365                 omit = 3;
366             }
367         }
368
369         if(!omit) {
370             gfxline_t*l;
371             int ok=0;
372             gfxdrawer_target_gfxline(&draw);
373             info.draw = &draw;
374             info.quality = quality;
375
376             //error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info);
377             error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info);
378             
379             if(error) {
380                 fprintf(stderr, "Couldn't decompose glyph %d\n", t);
381                 gfxline_free((gfxline_t*)draw.result(&draw));
382                 FT_Done_Glyph(glyph);
383                 omit = 4;
384             } else {
385                 font->glyphs[font->num_glyphs].advance = glyph->advance.x/65536;
386                 font->glyphs[font->num_glyphs].line = (gfxline_t*)draw.result(&draw);
387             }
388             l = font->glyphs[font->num_glyphs].line;
389             while(l) {
390                 if(l->type != gfx_moveTo) {
391                     ok = 1;
392                 }
393                 l = l->next;
394             }
395             if(!ok && !name) {
396                 gfxline_free(font->glyphs[font->num_glyphs].line);
397                 font->glyphs[font->num_glyphs].line = 0;
398                 font->glyphs[font->num_glyphs].advance = 0;
399
400                 /* Some PDFs created e.g. by InDesign tend to create
401                    fonts with reduced (empty) characters, which still
402                    have unicode indices attached to them.
403                    Remove that information, in order to not confuse
404                    any converter applications.
405                     */
406                 font->glyphs[font->num_glyphs].unicode = 0;
407                 if(font->glyphs[font->num_glyphs].name) {
408                     free((void*)font->glyphs[font->num_glyphs].name);
409                     font->glyphs[font->num_glyphs].name = 0;
410                 }
411                 FT_Done_Glyph(glyph);
412                 omit = 5;
413             }
414         }
415
416         if(!omit) {
417             FT_Done_Glyph(glyph);
418             font->glyphs[font->num_glyphs].unicode = glyph2unicode[t];
419         }
420
421         glyph2glyph[t] = font->num_glyphs;
422         font->num_glyphs++;
423     }
424
425     /* notice: if skip_unused is true, font->glyph2unicode, font->glyphnames and font->layout->bounds will 
426                have more memory allocated than just font->num_glyphs, but only the first font->numchars 
427                are used/valid */
428
429     for(t=0;t<font->max_unicode;t++) {
430         if(font->unicode2glyph[t]>=0) {
431             font->unicode2glyph[t] = glyph2glyph[font->unicode2glyph[t]];
432         }
433     }
434     rfx_free(glyph2glyph);
435     rfx_free(glyph2unicode);
436
437     FT_Done_Face(face);
438     FT_Done_FreeType(ftlibrary);ftlibrary=0;
439  
440     if(!isunicode && font->num_glyphs>0 && font->max_unicode) {
441         /* if the encoding isn't unicode, remap the font
442            so that the encoding equals the char position, and
443            remove the unicode table */
444         int t;
445         gfxglyph_t*newglyphs = (gfxglyph_t*)rfx_calloc(font->max_unicode*sizeof(gfxglyph_t));
446
447         for(t=0;t<max_unicode;t++) {
448             int c = font->unicode2glyph[t];
449             if(c>=font->num_glyphs || c<0)
450                 c = 0;
451             newglyphs[t] = cloneGlyph(&font->glyphs[c]);
452             newglyphs[t].unicode = -1;
453         }
454         for(t=0;t<font->num_glyphs;t++) {
455             glyph_clear(&font->glyphs[t]);
456         }
457         free(font->glyphs);
458         font->glyphs = newglyphs;
459         font->num_glyphs = font->max_unicode;
460
461         free(font->unicode2glyph);font->unicode2glyph = 0;
462         font->max_unicode = 0;
463     }
464
465     if(font->unicode2glyph) {
466         int t;
467         int bad = 0;
468         /* check whether the Unicode indices look o.k.
469            If they don't, disable the unicode lookup by setting
470            the unicode map to -1 everywhere */
471         for(t=0;t<font->num_glyphs;t++) {
472             int c = font->glyphs[t].unicode;
473             gfxline_t* line = font->glyphs[t].line;
474             if(c && c < 32 && (line && line->next && line->next->next)) {
475                 // the character maps into the unicode control character range
476                 // between 0001-001f. Yet it is not empty. Treat the one
477                 // mapping as broken, and look how many of those we find.
478                 bad ++;
479             }
480         }
481         if(bad>5) {
482             free(font->unicode2glyph);font->unicode2glyph = 0;
483             font->max_unicode = 0;
484             for(t=0;t<font->num_glyphs;t++) {
485                 font->glyphs[t].unicode = -1;
486             }
487         }
488     }
489
490     return font;
491 }
492 #else
493
494 gfxfont_t* gfxfont_load(char*id, char*filename, unsigned int flags, double quality)
495 {
496     fprintf(stderr, "No freetype support compiled in! Not able to load %s\n", filename);
497     return 0;
498 }
499
500 #endif
501
502 void gfxfont_free(gfxfont_t*font)
503 {
504     int t;
505     for(t=0;t<font->num_glyphs;t++) {
506         glyph_clear(&font->glyphs[t]);
507     }
508     if(font->glyphs) {
509         free(font->glyphs);font->glyphs = 0;
510     }
511     font->num_glyphs = 0;
512     if(font->unicode2glyph) {
513         free(font->unicode2glyph);font->unicode2glyph = 0;
514     }
515     if(font->id) {
516         free((void*)font->id);font->id=0;
517     }
518     if(font->kerning) {
519         free(font->kerning);font->kerning=0;
520     }
521
522     free(font);
523 }
524
525 static inline int invalid_unicode(int u)
526 {
527     return (u<32 || (u>=0xe000 && u<0xf900));
528 }
529 void gfxfont_fix_unicode(gfxfont_t*font)
530 {
531     int t;
532
533     /* find the current maximum unicode2glyph */
534     int max = 0;
535     for(t=0;t<font->num_glyphs;t++) {
536         int u = font->glyphs[t].unicode;
537         if(u > max)
538             max = u;
539     }
540     char*used = rfx_calloc(max+1);
541
542     /* now, remap all duplicates (and invalid characters) and
543        calculate the new maximum */
544     int remap_pos=0;
545     max = 0;
546     for(t=0;t<font->num_glyphs;t++) {
547         int u = font->glyphs[t].unicode;
548         if(u>=0) {
549             if(used[u] || invalid_unicode(u)) {
550                 u = font->glyphs[t].unicode = 0xe000 + remap_pos++;
551             } else {
552                 used[u] = 1;
553             }
554         }
555         if(u > max)
556             max = u;
557     }
558     free(used);
559     
560     if(!font->unicode2glyph) {
561         /* (re)generate unicode2glyph-to-glyph mapping table by reverse mapping
562            the glyph unicode2glyph's indexes into the mapping table. For collisions,
563            we prefer the smaller unicode2glyph value.*/
564         font->max_unicode = max+1;
565         font->unicode2glyph = malloc(sizeof(font->unicode2glyph[0])*(font->max_unicode));
566         memset(font->unicode2glyph, -1, sizeof(font->unicode2glyph[0])*(font->max_unicode));
567         
568         for(t=0;t<font->num_glyphs;t++) {
569             int u = font->glyphs[t].unicode;
570             if(u>=0) {
571                 assert(font->unicode2glyph[u]<0); // we took care of duplicates, right?
572                 font->unicode2glyph[u] = t;
573             }
574         }
575     } else {
576         /* add the new glyph indexes (most probably, that's only the remapped values
577            at 0xe000) to the unicode2glyph table. Notice: Unlike glyph2unicode, we don't
578            care about collisions in the unicode2glyph table */
579         int new_max_unicode = max+1;
580         if(font->max_unicode < new_max_unicode) {
581             font->unicode2glyph = rfx_realloc(font->unicode2glyph, sizeof(font->unicode2glyph[0])*(font->max_unicode));
582             memset(font->unicode2glyph+font->max_unicode, -1, sizeof(font->unicode2glyph[0])*(new_max_unicode - font->max_unicode));
583         }
584         for(t=0;t<font->num_glyphs;t++) {
585             int u = font->glyphs[t].unicode;
586             if(u>=0 && font->unicode2glyph[u]<0) {
587                 font->unicode2glyph[u] = t;
588             }
589         }
590         font->max_unicode = new_max_unicode;
591     }
592 }
593
594 ttf_t* gfxfont_to_ttf(gfxfont_t*font)
595 {
596     ttf_t*ttf = ttf_new();
597     int num_glyphs = font->num_glyphs;
598     int offset = 0;
599     int t;
600     char has_nondef_glyph = 
601         font->num_glyphs && font->glyphs[0].unicode==-1 && 
602         (!font->glyphs[0].line || !font->glyphs[0].line->next);
603
604     if(!has_nondef_glyph) {
605         /* insert a new .nondef glyph at the start of the font */
606         offset++;
607         num_glyphs++;
608     }
609     ttf->num_glyphs = num_glyphs;
610     ttf->glyphs = rfx_calloc(num_glyphs*sizeof(ttfglyph_t));
611     double scale = 1.0;
612     int max_unicode = font->max_unicode;
613     int remap_pos=0;
614     for(t=0;t<font->num_glyphs;t++) {
615         gfxglyph_t*src = &font->glyphs[t];
616         ttfglyph_t*dest = &ttf->glyphs[t+offset];
617         gfxline_t*line = src->line;
618         int count = 0;
619         while(line) {
620             count++;
621             if(line->type == gfx_splineTo) 
622                 count++;
623             line=line->next;
624         }
625         dest->num_points = count;
626         dest->points = rfx_calloc(count*sizeof(ttfpoint_t));
627         count = 0;
628         line = src->line;
629         while(line) {
630             if(line->type == gfx_splineTo) {
631                 dest->points[count].x = line->sx*scale;
632                 dest->points[count].y = line->sy*scale;
633                 count++;
634             }
635             dest->points[count].x = line->x*scale;
636             dest->points[count].y = line->y*scale;
637             dest->points[count].flags |= GLYPH_ON_CURVE;
638             if(line->type == gfx_moveTo) {
639                 dest->points[count].flags |= GLYPH_CONTOUR_START;
640                 if(count)
641                     dest->points[count-1].flags |= GLYPH_CONTOUR_END;
642             }
643             count++;
644             line=line->next;
645         }
646         if(count)
647             dest->points[count-1].flags |= GLYPH_CONTOUR_END;
648
649         /* compute bounding box */
650         int s;
651         if(count) {
652             dest->xmin = dest->xmax = dest->points[0].x;
653             dest->ymin = dest->ymax = dest->points[0].y;
654             for(s=1;s<count;s++) {
655                 if(dest->points[s].x < dest->xmin) 
656                     dest->xmin = dest->points[s].x;
657                 if(dest->points[s].y < dest->ymin) 
658                     dest->ymin = dest->points[s].y;
659                 if(dest->points[s].x > dest->xmax) 
660                     dest->xmax = dest->points[s].x;
661                 if(dest->points[s].y > dest->ymax) 
662                     dest->ymax = dest->points[s].y;
663             }
664         }
665
666         dest->advance = src->advance*scale;
667
668         int u = font->glyphs[t].unicode;
669         if(invalid_unicode(u)) {
670             u = 0xe000 + remap_pos++;
671         }
672         if(u > max_unicode)
673             max_unicode = u;
674     }
675     ttf->unicode_size = max_unicode+1;
676     ttf->unicode = rfx_calloc(sizeof(unicode_t)*ttf->unicode_size);
677     remap_pos=0;
678     for(t=0;t<font->num_glyphs;t++) {
679         gfxglyph_t*src = &font->glyphs[t];
680         int u = font->glyphs[t].unicode;
681         if(invalid_unicode(u)) {
682             u = 0xe000 + remap_pos++;
683         }
684         if(u>=0 && u<ttf->unicode_size)
685             ttf->unicode[u] = t+offset;
686     }
687     int u;
688     if(font->unicode2glyph) {
689         for(u=0;u<ttf->unicode_size;u++) {
690             int g = font->unicode2glyph[u];
691             if(invalid_unicode(u))
692                 continue;
693             if(g>=0 && g<font->num_glyphs && !ttf->unicode[u]) {
694                 ttf->unicode[u] = g+offset;
695             }
696         }
697     }
698         
699     ttf->ascent = font->ascent;
700     ttf->descent = font->descent;
701     ttf->lineGap = 0;
702
703     ttf->full_name = strdup(font->id);
704     ttf->family_name = strdup(font->id);
705     ttf->subfamily_name = strdup(font->id);
706     ttf->postscript_name = strdup(font->id);
707     ttf->version_string = strdup("Version 1.0");
708     ttf->font_uid = strdup(font->id);
709
710     ttf_create_truetype_tables(ttf);
711     return ttf;
712 }
713
714 void gfxfont_save(gfxfont_t*font, const char*filename)
715 {
716     ttf_t*ttf = gfxfont_to_ttf(font);
717     ttf_save(ttf, filename);
718     ttf_destroy(ttf);
719 }
720
721 void gfxfont_save_eot(gfxfont_t*font, const char*filename)
722 {
723     ttf_t*ttf = gfxfont_to_ttf(font);
724     ttf_save_eot(ttf, filename);
725     ttf_destroy(ttf);
726 }
727