3 Functions for loading external fonts.
5 Extension module for the rfxswf library.
6 Part of the swftools package.
8 Copyright (c) 2003, 2004, 2005 Matthias Kramm
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.
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.
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 */
24 #include "../config.h"
25 #include "gfxdevice.h"
29 static int loadfont_scale = 64;
30 static int full_unicode = 1;
34 #ifdef HAVE_FT2BUILD_H
36 #include FT_FREETYPE_H
39 #include FT_SFNT_NAMES_H
40 #include FT_TRUETYPE_IDS_H
43 #include <freetype/freetype.h>
44 #include <freetype/ftglyph.h>
45 #include <freetype/ftsizes.h>
46 #include <freetype/ftsnames.h>
47 #include <freetype/ttnameid.h>
48 #include <freetype/ftoutln.h>
51 /* Setting subpixels to 64 also means that the "point size" of the
52 font outlines will be 64. So the font, when rendered at original
53 size (i.e., the swf fontsize is 1024) will have the same size as
54 if it was rendered at 64pt */
57 #define FT_SUBPIXELS 64
59 typedef struct _gfxdrawinfo_t {
64 static int ft_move_to(const FT_Vector* _to, void* user)
66 gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
67 gfxdrawer_t* draw = info->draw;
68 double x = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
69 double y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
70 draw->moveTo(draw, x,y);
73 static int ft_line_to(const FT_Vector* _to, void* user)
75 gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
76 gfxdrawer_t* draw = info->draw;
77 double x = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
78 double y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
79 draw->lineTo(draw, x,y);
82 static int ft_cubic_to(const FT_Vector* _c1, const FT_Vector* _c2, const FT_Vector* _to, void* user)
84 gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
85 gfxdrawer_t* draw = info->draw;
86 double tox = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
87 double toy = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
88 double c1x = _c1->x*FT_SCALE/(float)FT_SUBPIXELS;
89 double c1y = -_c1->y*FT_SCALE/(float)FT_SUBPIXELS;
90 double c2x = _c2->x*FT_SCALE/(float)FT_SUBPIXELS;
91 double c2y = -_c2->y*FT_SCALE/(float)FT_SUBPIXELS;
92 gfxdraw_cubicTo(draw, c1x, c1y, c2x, c2y, tox, toy, info->quality);
95 static int ft_conic_to(const FT_Vector* _c, const FT_Vector* _to, void* user)
97 gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
98 gfxdrawer_t* draw = info->draw;
99 double tox = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
100 double toy = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
101 double cx = _c->x*FT_SCALE/(float)FT_SUBPIXELS;
102 double cy = -_c->y*FT_SCALE/(float)FT_SUBPIXELS;
103 gfxdraw_conicTo(draw, cx,cy, tox,toy, info->quality);
106 static FT_Outline_Funcs outline_functions =
115 static FT_Library ftlibrary = 0;
117 static gfxglyph_t cloneGlyph(gfxglyph_t*src)
120 memset(&dest, 0, sizeof(dest));
122 dest.name = strdup(src->name);
123 dest.advance = src->advance;
124 dest.unicode = src->unicode;
125 dest.line = gfxline_clone(src->line);
129 static void glyph_clear(gfxglyph_t*g)
133 free((void*)g->name); g->name = 0;
135 gfxline_free(g->line);g->line = 0;
138 static int errorno = 0;
142 gfxfont_t* gfxfont_load(char*id, char*filename, unsigned int flags, double quality)
146 const char* fontname = 0;
152 int*glyph2unicode = 0;
156 int has_had_errors = 0;
160 if(FT_Init_FreeType(&ftlibrary)) {
161 fprintf(stderr, "Couldn't init freetype library!\n");
165 error = FT_New_Face(ftlibrary, filename, 0, &face);
166 FT_Set_Pixel_Sizes (face, 16*loadfont_scale, 16*loadfont_scale);
168 printf("gfxfont_load(%s, %s, %f)\n", id, filename, quality);
172 fprintf(stderr, "Couldn't load file %s- not a TTF file? (error=%02x)\n", filename, error);
175 if(face->num_glyphs <= 0) {
176 fprintf(stderr, "File %s contains %d glyphs\n", face->num_glyphs);
180 font = (gfxfont_t*)rfx_calloc(sizeof(gfxfont_t));
181 //font->style = ((face->style_flags&FT_STYLE_FLAG_ITALIC)?FONT_STYLE_ITALIC:0) |((face->style_flags&FT_STYLE_FLAG_BOLD)?FONT_STYLE_BOLD:0);
182 //font->ascent = abs(face->ascender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMin;
183 //font->descent = abs(face->descender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMax;
184 //font->leading = font->layout->ascent + font->layout->descent;
185 //font->encoding = FONT_ENCODING_UNICODE;
186 font->max_unicode = 0;
187 font->id = strdup(id);
189 font->glyphs = (gfxglyph_t*)rfx_calloc(face->num_glyphs*sizeof(gfxglyph_t));
190 glyph2unicode = (int*)rfx_calloc(face->num_glyphs*sizeof(int));
191 glyph2glyph = (int*)rfx_calloc(face->num_glyphs*sizeof(int));
193 if(FT_HAS_GLYPH_NAMES(face)) {
194 //font->glyphnames = rfx_calloc(face->num_glyphs*sizeof(char*));
197 fontname = FT_Get_Postscript_Name(face);
200 for(t=0;t<face->num_charmaps;t++) {
201 printf("possible encoding: %c%c%c%c (%d of %d)\n",
202 (face->charmaps[t]->encoding >> 24)&255,
203 (face->charmaps[t]->encoding >> 16)&255,
204 (face->charmaps[t]->encoding >> 8)&255,
205 (face->charmaps[t]->encoding >> 0)&255,
206 t+1, face->num_charmaps
213 charcode = FT_Get_First_Char(face, &gindex);
217 if(gindex >= 0 && gindex<face->num_glyphs) {
218 if(!glyph2unicode[gindex]) {
219 glyph2unicode[gindex] = charcode;
220 if(charcode + 1 > font->max_unicode) {
221 font->max_unicode = charcode + 1;
225 charcode = FT_Get_Next_Char(face, charcode, &gindex);
230 printf("ENCODING: %c%c%c%c (%d of %d) max_unicode=%d\n",
231 (face->charmap->encoding >> 24)&255,
232 (face->charmap->encoding >> 16)&255,
233 (face->charmap->encoding >> 8)&255,
234 (face->charmap->encoding >> 0)&255,
235 charmap, face->num_charmaps, font->max_unicode
238 printf("ENCODING: NONE (%d of %d) max_unicode=%d\n",
239 charmap, face->num_charmaps, font->max_unicode
244 /* if we didn't find a single encoding character, try
245 the font's charmaps instead. That usually means that
246 the encoding is no longer unicode.
247 TODO: find a way to convert the encoding to unicode
249 if(font->max_unicode == 0 && charmap < face->num_charmaps-1
250 && face->charmaps[charmap+1]->encoding != 0x41444243 /* adbc, custom */
251 && face->charmaps[charmap+1]->encoding != 0x61726d6e /* armn */
255 FT_Set_Charmap(face, face->charmaps[charmap]);
260 /* TODO: if isunicode is 1, we now need to permutate the character
261 order so that each character is at it's encoding position */
264 font->max_unicode = 65535;
266 font->unicode2glyph = (int*)rfx_calloc(font->max_unicode*sizeof(int));
268 for(t=0;t<font->max_unicode;t++) {
269 int g = FT_Get_Char_Index(face, t);
270 if(!g || g>=face->num_glyphs)
272 font->unicode2glyph[t] = g;
275 printf("u%d ->%d\n", t, g);
278 if(!glyph2unicode[g]) {
279 glyph2unicode[g] = t;
283 font->max_unicode = max_unicode;
285 font->num_glyphs = 0;
288 for(t=0; t < face->num_glyphs; t++) {
289 if(FT_HAS_GLYPH_NAMES(face)) {
291 error = FT_Get_Glyph_Name(face, t, name, 127);
292 if(!error && name[0] && !strstr(name, "notdef")) {
299 for(t=0; t < face->num_glyphs; t++) {
308 font->glyphs[font->num_glyphs].advance = 0;
309 font->glyphs[font->num_glyphs].line = 0;
310 font->glyphs[font->num_glyphs].unicode = glyph2unicode[t];
311 font->glyphs[font->num_glyphs].name = 0;
313 if(FT_HAS_GLYPH_NAMES(face) && (num_names >= face->num_glyphs/10 || num_names > 2)) {
315 error = FT_Get_Glyph_Name(face, t, name, 127);
316 if(!error && name[0] && !strstr(name, "notdef")) {
317 font->glyphs[font->num_glyphs].name = strdup(name);
322 #if 0 // some cantonese pdfs fail to work if this is activated
324 if(has_had_errors && (isunicode && !glyph2unicode[t]) && !hasname && t>=256) {
325 /* some freetype versions crash or corrupt memory if we try to load
326 characters (without unicode index or name) above 256 for some fonts.
327 So skip those characters once the first error occured */
333 error = FT_Load_Glyph(face, t, FT_LOAD_NO_BITMAP);
336 fprintf(stderr, "Warning: glyph %d/%d (unicode %d, name %s) has return code %d\n", t, face->num_glyphs, glyph2unicode[t], name, error);
338 fprintf(stderr, "Warning: glyph %d/%d (unicode %d) has return code %d\n", t, face->num_glyphs, glyph2unicode[t], error);
342 if(!has_had_errors) {
344 if(fontname && *fontname) {
345 fprintf(stderr, "font has been copied to %s.ttf\n", fontname);
346 sprintf(buf, "cp %s %s.ttf", filename, fontname);
348 fprintf(stderr, "font has been copied to badfont%d.ttf\n", errorno);
349 sprintf(buf, "cp %s badfont%d.ttf", filename, errorno);
359 error = FT_Get_Glyph(face->glyph, &glyph);
361 fprintf(stderr, "Couldn't get glyph %d/%d, error:%d\n", t, face->num_glyphs, error);
369 gfxdrawer_target_gfxline(&draw);
371 info.quality = quality;
373 //error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info);
374 error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info);
377 fprintf(stderr, "Couldn't decompose glyph %d\n", t);
378 gfxline_free((gfxline_t*)draw.result(&draw));
379 FT_Done_Glyph(glyph);
382 font->glyphs[font->num_glyphs].advance = glyph->advance.x/65536;
383 font->glyphs[font->num_glyphs].line = (gfxline_t*)draw.result(&draw);
385 l = font->glyphs[font->num_glyphs].line;
387 if(l->type != gfx_moveTo) {
393 gfxline_free(font->glyphs[font->num_glyphs].line);
394 font->glyphs[font->num_glyphs].line = 0;
395 font->glyphs[font->num_glyphs].advance = 0;
397 /* Some PDFs created e.g. by InDesign tend to create
398 fonts with reduced (empty) characters, which still
399 have unicode indices attached to them.
400 Remove that information, in order to not confuse
401 any converter applications.
403 font->glyphs[font->num_glyphs].unicode = 0;
404 if(font->glyphs[font->num_glyphs].name) {
405 free((void*)font->glyphs[font->num_glyphs].name);
406 font->glyphs[font->num_glyphs].name = 0;
408 FT_Done_Glyph(glyph);
414 FT_Done_Glyph(glyph);
415 font->glyphs[font->num_glyphs].unicode = glyph2unicode[t];
418 glyph2glyph[t] = font->num_glyphs;
422 /* notice: if skip_unused is true, font->glyph2unicode, font->glyphnames and font->layout->bounds will
423 have more memory allocated than just font->num_glyphs, but only the first font->numchars
426 for(t=0;t<font->max_unicode;t++) {
427 if(font->unicode2glyph[t]>=0) {
428 font->unicode2glyph[t] = glyph2glyph[font->unicode2glyph[t]];
431 rfx_free(glyph2glyph);
432 rfx_free(glyph2unicode);
435 FT_Done_FreeType(ftlibrary);ftlibrary=0;
437 if(!isunicode && font->num_glyphs>0 && font->max_unicode) {
438 /* if the encoding isn't unicode, remap the font
439 so that the encoding equals the char position, and
440 remove the unicode table */
442 gfxglyph_t*newglyphs = (gfxglyph_t*)rfx_calloc(font->max_unicode*sizeof(gfxglyph_t));
444 for(t=0;t<max_unicode;t++) {
445 int c = font->unicode2glyph[t];
446 if(c>=font->num_glyphs || c<0)
448 newglyphs[t] = cloneGlyph(&font->glyphs[c]);
449 newglyphs[t].unicode = -1;
451 for(t=0;t<font->num_glyphs;t++) {
452 glyph_clear(&font->glyphs[t]);
455 font->glyphs = newglyphs;
456 font->num_glyphs = font->max_unicode;
458 free(font->unicode2glyph);font->unicode2glyph = 0;
459 font->max_unicode = 0;
462 if(font->unicode2glyph) {
465 /* check whether the Unicode indices look o.k.
466 If they don't, disable the unicode lookup by setting
467 the unicode map to -1 everywhere */
468 for(t=0;t<font->num_glyphs;t++) {
469 int c = font->glyphs[t].unicode;
470 gfxline_t* line = font->glyphs[t].line;
471 if(c && c < 32 && (line && line->next && line->next->next)) {
472 // the character maps into the unicode control character range
473 // between 0001-001f. Yet it is not empty. Treat the one
474 // mapping as broken, and look how many of those we find.
479 free(font->unicode2glyph);font->unicode2glyph = 0;
480 font->max_unicode = 0;
481 for(t=0;t<font->num_glyphs;t++) {
482 font->glyphs[t].unicode = -1;
491 gfxfont_t* gfxfont_load(char*filename)
493 fprintf(stderr, "No freetype support compiled in! Not able to load %s\n", filename);
498 void gfxfont_free(gfxfont_t*font)
501 for(t=0;t<font->num_glyphs;t++) {
502 glyph_clear(&font->glyphs[t]);
505 free(font->glyphs);font->glyphs = 0;
507 font->num_glyphs = 0;
508 if(font->unicode2glyph) {
509 free(font->unicode2glyph);font->unicode2glyph = 0;