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