don't switch to custom chartables
[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 "../config.h"
25 #include "gfxdevice.h"
26 #include "gfxtools.h"
27
28 static int loadfont_scale = 64;
29 static int full_unicode = 1;
30
31 #ifdef HAVE_FREETYPE
32
33 #ifdef HAVE_FT2BUILD_H
34 #include <ft2build.h>
35 #include FT_FREETYPE_H
36 #include FT_GLYPH_H
37 #include FT_SIZES_H
38 #include FT_SFNT_NAMES_H
39 #include FT_TRUETYPE_IDS_H
40 #include FT_OUTLINE_H
41 #else
42 #include <freetype/freetype.h>
43 #include <freetype/ftglyph.h>
44 #include <freetype/ftsizes.h>
45 #include <freetype/ftsnames.h>
46 #include <freetype/ttnameid.h>
47 #include <freetype/ftoutln.h>
48 #endif
49
50 /* Setting subpixels to 64 also means that the "point size" of the
51    font outlines will be 64. So the font, when rendered at original
52    size (i.e., the swf fontsize is 1024) will have the same size as
53    if it was rendered at 64pt */
54
55 #define FT_SCALE 1
56 #define FT_SUBPIXELS 64
57
58 typedef struct _gfxdrawinfo_t {
59     gfxdrawer_t* draw;
60     double quality;
61 } gfxdrawinfo_t;
62
63 static int ft_move_to(FT_Vector* _to, void* user) 
64 {
65     gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
66     gfxdrawer_t* draw = info->draw;
67     double x = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
68     double y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
69     draw->moveTo(draw, x,y);
70     return 0;
71 }
72 static int ft_line_to(FT_Vector* _to, void* user) 
73 {
74     gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
75     gfxdrawer_t* draw = info->draw;
76     double x = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
77     double y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
78     draw->lineTo(draw, x,y);
79     return 0;
80 }
81 static int ft_cubic_to(FT_Vector* _c1, FT_Vector* _c2, FT_Vector* _to, void* user)
82 {
83     gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
84     gfxdrawer_t* draw = info->draw;
85     double tox = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
86     double toy = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
87     double c1x = _c1->x*FT_SCALE/(float)FT_SUBPIXELS;
88     double c1y = -_c1->y*FT_SCALE/(float)FT_SUBPIXELS;
89     double c2x = _c2->x*FT_SCALE/(float)FT_SUBPIXELS;
90     double c2y = -_c2->y*FT_SCALE/(float)FT_SUBPIXELS;
91     gfxdraw_cubicTo(draw, c1x, c1y, c2x, c2y, tox, toy, info->quality);
92     return 0;
93 }
94 static int ft_conic_to(FT_Vector* _c, FT_Vector* _to, void* user) 
95 {
96     gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
97     gfxdrawer_t* draw = info->draw;
98     double tox = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
99     double toy = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
100     double cx = _c->x*FT_SCALE/(float)FT_SUBPIXELS;
101     double cy = -_c->y*FT_SCALE/(float)FT_SUBPIXELS;
102     gfxdraw_conicTo(draw, cx,cy, tox,toy, info->quality);
103     return 0;
104 }
105 static FT_Outline_Funcs outline_functions =
106 {
107   ft_move_to,
108   ft_line_to,
109   ft_conic_to,
110   ft_cubic_to,
111   0,0
112 };
113
114 static FT_Library ftlibrary = 0;
115
116 static gfxglyph_t cloneGlyph(gfxglyph_t*src)
117 {
118     gfxglyph_t dest;
119     memset(&dest, 0, sizeof(dest));
120     if(src->name)
121         dest.name = strdup(src->name);
122     dest.advance = src->advance;
123     dest.unicode = src->unicode;
124     dest.line = gfxline_clone(src->line);
125     return dest;
126 }
127
128 static void glyph_clear(gfxglyph_t*g)
129 {
130     gfxline_t*line;
131     if(g->name) {
132         free(g->name); g->name = 0;
133     }
134     gfxline_free(g->line);g->line = 0;
135 }
136
137 static int errorno = 0;
138
139 gfxfont_t* gfxfont_load(char*filename, double quality)
140 {
141     FT_Face face;
142     FT_Error error;
143     const char* fontname = 0;
144     FT_ULong charcode;
145     FT_UInt gindex;
146     gfxfont_t* font;
147     int t;
148     int*glyph2glyph = 0;
149     int*glyph2unicode = 0;
150     FT_Size size;
151     int max_unicode = 0;
152     int charmap = -1;
153     int isunicode = 1;
154     int has_had_errors = 0;
155     int num_names = 0;
156
157     if(ftlibrary == 0) {
158         if(FT_Init_FreeType(&ftlibrary)) {
159             fprintf(stderr, "Couldn't init freetype library!\n");
160             exit(1);
161         }
162     }
163     error = FT_New_Face(ftlibrary, filename, 0, &face);
164     FT_Set_Pixel_Sizes (face, 16*loadfont_scale, 16*loadfont_scale);
165
166     if(error) {
167         fprintf(stderr, "Couldn't load file %s- not a TTF file?\n", filename);
168         return 0;
169     }
170     if(face->num_glyphs <= 0) {
171         fprintf(stderr, "File %s contains %d glyphs\n", face->num_glyphs);
172         return 0;
173     }
174
175     font = rfx_calloc(sizeof(gfxfont_t));
176     //font->style =  ((face->style_flags&FT_STYLE_FLAG_ITALIC)?FONT_STYLE_ITALIC:0) |((face->style_flags&FT_STYLE_FLAG_BOLD)?FONT_STYLE_BOLD:0);
177     //font->ascent = abs(face->ascender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMin;
178     //font->descent = abs(face->descender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMax;
179     //font->leading = font->layout->ascent + font->layout->descent;
180     //font->encoding = FONT_ENCODING_UNICODE;
181     font->max_unicode = 0;
182     
183     font->glyphs = rfx_calloc(face->num_glyphs*sizeof(gfxglyph_t));
184     glyph2unicode = rfx_calloc(face->num_glyphs*sizeof(int));
185     glyph2glyph = rfx_calloc(face->num_glyphs*sizeof(int));
186
187     if(FT_HAS_GLYPH_NAMES(face)) {
188         //font->glyphnames = rfx_calloc(face->num_glyphs*sizeof(char*));
189     }
190
191     fontname = FT_Get_Postscript_Name(face);
192
193     while(1) 
194     {
195         charcode = FT_Get_First_Char(face, &gindex);
196         while(gindex != 0)
197         {
198             if(gindex >= 0 && gindex<face->num_glyphs) {
199                 if(!glyph2unicode[gindex]) {
200                     glyph2unicode[gindex] = charcode;
201                     if(charcode + 1 > font->max_unicode) {
202                         font->max_unicode = charcode + 1;
203                     }
204                 }
205             }
206             charcode = FT_Get_Next_Char(face, charcode, &gindex);
207         }
208
209         /* if we didn't find a single encoding character, try
210            the font's charmaps instead. That usually means that
211            the encoding is no longer unicode. 
212            TODO: find a way to convert the encoding to unicode
213          */
214         if(font->max_unicode == 0 && charmap < face->num_charmaps-1 && 
215                 face->charmaps[charmap+1]->encoding != 0x41444243 /* custom */)
216                 {
217             charmap++;
218             FT_Set_Charmap(face, face->charmaps[charmap]);
219             isunicode = 0;
220         } else
221             break;
222     }
223
224     /* TODO: if isunicode is 1, we now need to permutate the character
225              order so that each character is at it's encoding position */
226
227     if(full_unicode)
228         font->max_unicode = 65535;
229     
230     font->unicode2glyph = rfx_calloc(font->max_unicode*sizeof(int));
231     
232     for(t=0;t<font->max_unicode;t++) {
233         int g = FT_Get_Char_Index(face, t);
234         if(!g || g>=face->num_glyphs)
235             g = -1;
236         font->unicode2glyph[t] = g;
237         if(g>=0) {
238             max_unicode = t+1;
239             if(!glyph2unicode[g]) {
240                 glyph2unicode[g] = t;
241             }
242         }
243     }
244     font->max_unicode = max_unicode;
245
246     font->num_glyphs = 0;
247
248
249     for(t=0; t < face->num_glyphs; t++) {
250         if(FT_HAS_GLYPH_NAMES(face)) {
251             char name[128];
252             error = FT_Get_Glyph_Name(face, t, name, 127);
253             if(!error && name[0] && !strstr(name, "notdef")) {
254                 num_names++;
255             }
256         }
257     }
258
259
260     for(t=0; t < face->num_glyphs; t++) {
261         FT_Glyph glyph;
262         FT_BBox bbox;
263         FT_Matrix matrix;
264         char name[128];
265         gfxdrawer_t draw;
266         gfxdrawinfo_t info;
267         int ret;
268         char hasname = 0;
269         int omit = 0;
270         name[0]=0;
271         
272         font->glyphs[font->num_glyphs].advance = 0;
273         font->glyphs[font->num_glyphs].line = 0;
274         font->glyphs[font->num_glyphs].unicode = glyph2unicode[t];
275         font->glyphs[font->num_glyphs].name = 0;
276
277         if(FT_HAS_GLYPH_NAMES(face) && (num_names >= face->num_glyphs/10 || num_names > 2)) {
278             name[0] = 0;
279             error = FT_Get_Glyph_Name(face, t, name, 127);
280             if(!error && name[0] && !strstr(name, "notdef")) {
281                 font->glyphs[font->num_glyphs].name = strdup(name);
282                 hasname = 1;
283             }
284         }
285         if(has_had_errors && (isunicode && !glyph2unicode[t]) && !hasname) {
286             /* some freetype versions crash or corrupt memory if we try to load
287                characters (without unicode index or name) above 256 for some fonts.
288                So skip those characters once the first error occured */
289             omit = 1;
290         }
291         if(!omit) {
292             error = FT_Load_Glyph(face, t, FT_LOAD_NO_BITMAP);
293             if(error) {
294                 if(hasname)
295                     fprintf(stderr, "Warning: glyph %d/%d (unicode %d, name %s) has return code %d\n", t, face->num_glyphs, glyph2unicode[t], name, error);
296                 else
297                     fprintf(stderr, "Warning: glyph %d/%d (unicode %d) has return code %d\n", t, face->num_glyphs, glyph2unicode[t], error);
298                 omit = 2;
299
300 #if 0
301                 if(!has_had_errors) {
302                     char buf[256];
303                     if(fontname && *fontname) {
304                         fprintf(stderr, "font has been copied to %s.ttf\n", fontname);
305                         sprintf(buf, "cp %s %s.ttf", filename, fontname);
306                     } else {
307                         fprintf(stderr, "font has been copied to badfont%d.ttf\n", errorno);
308                         sprintf(buf, "cp %s badfont%d.ttf", filename, errorno);
309                         errorno++;
310                     }
311                     system(buf);
312                 }
313 #endif
314                 has_had_errors = 1;
315             }
316         }
317         if(!omit) {
318             error = FT_Get_Glyph(face->glyph, &glyph);
319             if(error) {
320                 fprintf(stderr, "Couldn't get glyph %d/%d, error:%d\n", t, face->num_glyphs, error);
321                 omit = 3;
322             }
323         }
324
325         if(!omit) {
326             gfxline_t*l;
327             int ok=0;
328             gfxdrawer_target_gfxline(&draw);
329             info.draw = &draw;
330             info.quality = quality;
331
332             //error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info);
333             error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info);
334             
335             if(error) {
336                 fprintf(stderr, "Couldn't decompose glyph %d\n", t);
337                 gfxline_free((gfxline_t*)draw.result(&draw));
338                 FT_Done_Glyph(glyph);
339                 omit = 4;
340             } else {
341                 font->glyphs[font->num_glyphs].advance = (glyph->advance.x*20)/65536;
342                 font->glyphs[font->num_glyphs].line = (gfxline_t*)draw.result(&draw);
343             }
344             l = font->glyphs[font->num_glyphs].line;
345             while(l) {
346                 if(l->type != gfx_moveTo) {
347                     ok = 1;
348                 }
349                 l = l->next;
350             }
351             if(!ok && !name) {
352                 gfxline_free(font->glyphs[font->num_glyphs].line);
353                 font->glyphs[font->num_glyphs].line = 0;
354                 font->glyphs[font->num_glyphs].advance = 0;
355
356                 /* Some PDFs created e.g. by InDesign tend to create
357                    fonts with reduced (empty) characters, which still
358                    have unicode indices attached to them.
359                    Remove that information, in order to not confuse
360                    any converter applications.
361                     */
362                 font->glyphs[font->num_glyphs].unicode = 0;
363                 if(font->glyphs[font->num_glyphs].name) {
364                     free(font->glyphs[font->num_glyphs].name);
365                     font->glyphs[font->num_glyphs].name = 0;
366                 }
367                 FT_Done_Glyph(glyph);
368                 omit = 5;
369             }
370         }
371
372         if(!omit) {
373             FT_Done_Glyph(glyph);
374             font->glyphs[font->num_glyphs].unicode = glyph2unicode[t];
375         }
376
377         glyph2glyph[t] = font->num_glyphs;
378         font->num_glyphs++;
379     }
380
381     /* notice: if skip_unused is true, font->glyph2unicode, font->glyphnames and font->layout->bounds will 
382                have more memory allocated than just font->num_glyphs, but only the first font->numchars 
383                are used/valid */
384
385     for(t=0;t<font->max_unicode;t++) {
386         if(font->unicode2glyph[t]>=0) {
387             font->unicode2glyph[t] = glyph2glyph[font->unicode2glyph[t]];
388         }
389     }
390     rfx_free(glyph2glyph);
391     rfx_free(glyph2unicode);
392
393     FT_Done_Face(face);
394     FT_Done_FreeType(ftlibrary);ftlibrary=0;
395  
396     if(!isunicode && font->num_glyphs>0 && font->max_unicode) {
397         /* if the encoding isn't unicode, remap the font
398            so that the encoding equals the char position, and
399            remove the unicode table */
400         int t;
401         gfxglyph_t*newglyphs = rfx_calloc(font->max_unicode*sizeof(gfxglyph_t));
402
403         for(t=0;t<max_unicode;t++) {
404             int c = font->unicode2glyph[t];
405             if(c>=font->num_glyphs || c<0)
406                 c = 0;
407             newglyphs[t] = cloneGlyph(&font->glyphs[c]);
408             newglyphs[t].unicode = -1;
409         }
410         for(t=0;t<font->num_glyphs;t++) {
411             glyph_clear(&font->glyphs[t]);
412         }
413         free(font->glyphs);
414         font->glyphs = newglyphs;
415         font->num_glyphs = font->max_unicode;
416
417         free(font->unicode2glyph);font->unicode2glyph = 0;
418         font->max_unicode = 0;
419     }
420
421     if(font->unicode2glyph) {
422         int t;
423         int bad = 0;
424         /* check whether the Unicode indices look o.k.
425            If they don't, disable the unicode lookup by setting
426            the unicode map to -1 everywhere */
427         for(t=0;t<font->num_glyphs;t++) {
428             int c = font->glyphs[t].unicode;
429             gfxline_t* line = font->glyphs[t].line;
430             if(c && c < 32 && (line && line->next && line->next->next)) {
431                 // the character maps into the unicode control character range
432                 // between 0001-001f. Yet it is not empty. Treat the one
433                 // mapping as broken, and look how many of those we find.
434                 bad ++;
435             }
436         }
437         if(bad>5) {
438             free(font->unicode2glyph);font->unicode2glyph = 0;
439             font->max_unicode = 0;
440             for(t=0;t<font->num_glyphs;t++) {
441                 font->glyphs[t].unicode = -1;
442             }
443         }
444     }
445
446     return font;
447 }
448 #else
449
450 gfxfont_t* gfxfont_load(char*filename)
451 {
452     fprintf(stderr, "No freetype support compiled in! Not able to load %s\n", filename);
453 }
454
455 #endif
456
457 void gfxfont_free(gfxfont_t*font)
458 {
459     int t;
460     for(t=0;t<font->num_glyphs;t++) {
461         glyph_clear(&font->glyphs[t]);
462     }
463     if(font->glyphs) {
464         free(font->glyphs);font->glyphs = 0;
465     }
466     font->num_glyphs = 0;
467     if(font->unicode2glyph) {
468         free(font->unicode2glyph);font->unicode2glyph = 0;
469     }
470     free(font);
471 }
472