only create a unicode2glyph table if explicitly requested
[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(const char*id, const 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     if(font->unicode2glyph) {
561         free(font->unicode2glyph);
562     }
563     font->unicode2glyph = 0;
564     font->max_unicode = 0;
565 }
566
567 void gfxfont_add_unicode2glyph(gfxfont_t*font)
568
569     int t;
570     int max = 0;
571     for(t=0;t<font->num_glyphs;t++) {
572         int u = font->glyphs[t].unicode;
573         if(u > max)
574             max = u;
575     }
576     if(!font->unicode2glyph) {
577         /* (re)generate unicode2glyph-to-glyph mapping table by reverse mapping
578            the glyph unicode2glyph's indexes into the mapping table. For collisions,
579            we prefer the smaller unicode2glyph value.*/
580         font->max_unicode = max+1;
581         font->unicode2glyph = malloc(sizeof(font->unicode2glyph[0])*(font->max_unicode));
582         memset(font->unicode2glyph, -1, sizeof(font->unicode2glyph[0])*(font->max_unicode));
583         
584         for(t=0;t<font->num_glyphs;t++) {
585             int u = font->glyphs[t].unicode;
586             if(u>=0) {
587                 assert(font->unicode2glyph[u]<0); // we took care of duplicates, right?
588                 assert(u<font->max_unicode);
589                 font->unicode2glyph[u] = t;
590             }
591         }
592     } else {
593         /* add the new glyph indexes (most probably, that's only the remapped values
594            at 0xe000) to the unicode2glyph table. Notice: Unlike glyph2unicode, we don't
595            care about collisions in the unicode2glyph table */
596         int new_max_unicode = max+1;
597         if(font->max_unicode < new_max_unicode) {
598             font->unicode2glyph = rfx_realloc(font->unicode2glyph, sizeof(font->unicode2glyph[0])*(font->max_unicode));
599             memset(font->unicode2glyph+font->max_unicode, -1, sizeof(font->unicode2glyph[0])*(new_max_unicode - font->max_unicode));
600         }
601         for(t=0;t<font->num_glyphs;t++) {
602             int u = font->glyphs[t].unicode;
603             if(u>=0 && font->unicode2glyph[u]<0) {
604                 font->unicode2glyph[u] = t;
605             }
606         }
607         font->max_unicode = new_max_unicode;
608     }
609 }
610
611 ttf_t* gfxfont_to_ttf(gfxfont_t*font, char eot)
612 {
613     ttf_t*ttf = ttf_new();
614     int num_glyphs = font->num_glyphs;
615     int offset = 0;
616     int t;
617     char has_nondef_glyph = 
618         font->num_glyphs && font->glyphs[0].unicode==-1 && 
619         (!font->glyphs[0].line || !font->glyphs[0].line->next);
620
621     if(!has_nondef_glyph) {
622         /* insert a new .nondef glyph at the start of the font */
623         offset++;
624         num_glyphs++;
625     }
626     ttf->num_glyphs = num_glyphs;
627     ttf->glyphs = rfx_calloc(num_glyphs*sizeof(ttfglyph_t));
628     double scale = 1.0;
629     int max_unicode = font->max_unicode;
630     int remap_pos=0;
631     for(t=0;t<font->num_glyphs;t++) {
632         gfxglyph_t*src = &font->glyphs[t];
633         ttfglyph_t*dest = &ttf->glyphs[t+offset];
634         gfxline_t*line = src->line;
635         int count = 0;
636         while(line) {
637             count++;
638             if(line->type == gfx_splineTo) 
639                 count++;
640             line=line->next;
641         }
642         dest->num_points = count;
643         dest->points = rfx_calloc(count*sizeof(ttfpoint_t));
644         count = 0;
645         line = src->line;
646         while(line) {
647             if(line->type == gfx_splineTo) {
648                 dest->points[count].x = line->sx*scale;
649                 dest->points[count].y = line->sy*scale;
650                 count++;
651             }
652             dest->points[count].x = line->x*scale;
653             dest->points[count].y = line->y*scale;
654             dest->points[count].flags |= GLYPH_ON_CURVE;
655             if(line->type == gfx_moveTo) {
656                 dest->points[count].flags |= GLYPH_CONTOUR_START;
657                 if(count)
658                     dest->points[count-1].flags |= GLYPH_CONTOUR_END;
659             }
660             count++;
661             line=line->next;
662         }
663         if(count)
664             dest->points[count-1].flags |= GLYPH_CONTOUR_END;
665
666         /* compute bounding box */
667         int s;
668         if(count) {
669             dest->xmin = dest->xmax = dest->points[0].x;
670             dest->ymin = dest->ymax = dest->points[0].y;
671             for(s=1;s<count;s++) {
672                 if(dest->points[s].x < dest->xmin) 
673                     dest->xmin = dest->points[s].x;
674                 if(dest->points[s].y < dest->ymin) 
675                     dest->ymin = dest->points[s].y;
676                 if(dest->points[s].x > dest->xmax) 
677                     dest->xmax = dest->points[s].x;
678                 if(dest->points[s].y > dest->ymax) 
679                     dest->ymax = dest->points[s].y;
680             }
681         }
682
683         if(eot) {
684             dest->bearing = dest->xmin;
685             /* for windows font rendering, make sure coordinates are always 
686                to the right of the origin (and use bearing to shift them "back".)
687                Don't do this for non-windows platforms though because e.g. OS X 
688                ignores bearing. */
689             int xshift=0;
690             if(dest->xmin < 0) {
691                 xshift = -dest->xmin;
692                 for(s=0;s<count;s++) {
693                     dest->points[s].x += xshift;
694                 }
695                 dest->xmin += xshift;
696                 dest->xmax += xshift;
697             }
698         }
699         dest->advance = src->advance*scale;
700
701         //dest->xmin=0; //TODO: might be necessary for some font engines?
702
703         dest->advance = src->advance*scale;
704
705         int u = font->glyphs[t].unicode;
706         if(u > max_unicode)
707             max_unicode = u;
708     }
709     ttf->unicode_size = max_unicode+1;
710     ttf->unicode = rfx_calloc(sizeof(unicode_t)*ttf->unicode_size);
711     
712     if(!font->unicode2glyph) {
713         for(t=0;t<font->num_glyphs;t++) {
714             gfxglyph_t*src = &font->glyphs[t];
715             int u = font->glyphs[t].unicode;
716             if(u<=0)
717                 continue;
718             if(u<32) {
719                 msg("<warning> gfxfont_to_ttf: glyph %d has an invalid unicode (%d)", t, u);
720                 continue;
721             } else if(ttf->unicode[u]) {
722                 msg("<warning> gfxfont_to_ttf: glyph %d has a duplicate unicode (%d)", t, u);
723                 continue;
724             }
725             if(u<ttf->unicode_size)
726                 ttf->unicode[u] = t+offset;
727         }
728     } else {
729         int u;
730         for(u=1;u<font->max_unicode;u++) {
731             int g = font->unicode2glyph[u];
732             if(g>=0 && u<32) {
733                 msg("<warning> gfxfont_to_ttf: Font contains an invalid unicode (%d)", u);
734                 continue;
735             }
736             if(g>=0 && g<font->num_glyphs && !ttf->unicode[u]) {
737                 ttf->unicode[u] = g+offset;
738             }
739         }
740     }
741         
742     ttf->ascent = font->ascent;
743     ttf->descent = -font->descent;
744     ttf->lineGap = 0;
745
746     ttf->full_name = strdup(font->id);
747     ttf->family_name = strdup(font->id);
748     ttf->subfamily_name = strdup(font->id);
749     ttf->postscript_name = strdup(font->id);
750     ttf->version_string = strdup("Version 1.0");
751     ttf->font_uid = strdup(font->id);
752
753     ttf_create_truetype_tables(ttf);
754     return ttf;
755 }
756
757 void gfxfont_save(gfxfont_t*font, const char*filename)
758 {
759     ttf_t*ttf = gfxfont_to_ttf(font, 0);
760     ttf_save(ttf, filename);
761     ttf_destroy(ttf);
762 }
763
764 void gfxfont_save_eot(gfxfont_t*font, const char*filename)
765 {
766     ttf_t*ttf = gfxfont_to_ttf(font, 1);
767     ttf_save_eot(ttf, filename);
768     ttf_destroy(ttf);
769 }
770