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