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