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"
28 static int loadfont_scale = 64;
29 static int full_unicode = 1;
33 #ifdef HAVE_FT2BUILD_H
35 #include FT_FREETYPE_H
38 #include FT_SFNT_NAMES_H
39 #include FT_TRUETYPE_IDS_H
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>
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 */
56 #define FT_SUBPIXELS 64
58 typedef struct _gfxdrawinfo_t {
63 static int ft_move_to(FT_Vector* _to, void* user)
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);
72 static int ft_line_to(FT_Vector* _to, void* user)
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);
81 static int ft_cubic_to(FT_Vector* _c1, FT_Vector* _c2, FT_Vector* _to, void* user)
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);
94 static int ft_conic_to(FT_Vector* _c, FT_Vector* _to, void* user)
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);
105 static FT_Outline_Funcs outline_functions =
114 static FT_Library ftlibrary = 0;
116 static gfxglyph_t cloneGlyph(gfxglyph_t*src)
119 memset(&dest, 0, sizeof(dest));
121 dest.name = strdup(src->name);
122 dest.advance = src->advance;
123 dest.unicode = src->unicode;
124 dest.line = gfxline_clone(src->line);
128 static void glyph_clear(gfxglyph_t*g)
132 free(g->name); g->name = 0;
134 gfxline_free(g->line);g->line = 0;
137 static int errorno = 0;
139 gfxfont_t* gfxfont_load(char*id, char*filename, double quality)
143 const char* fontname = 0;
149 int*glyph2unicode = 0;
154 int has_had_errors = 0;
158 if(FT_Init_FreeType(&ftlibrary)) {
159 fprintf(stderr, "Couldn't init freetype library!\n");
163 error = FT_New_Face(ftlibrary, filename, 0, &face);
164 FT_Set_Pixel_Sizes (face, 16*loadfont_scale, 16*loadfont_scale);
167 fprintf(stderr, "Couldn't load file %s- not a TTF file? (error=%02x)\n", filename, error);
170 if(face->num_glyphs <= 0) {
171 fprintf(stderr, "File %s contains %d glyphs\n", face->num_glyphs);
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 font->id = strdup(id);
184 font->glyphs = rfx_calloc(face->num_glyphs*sizeof(gfxglyph_t));
185 glyph2unicode = rfx_calloc(face->num_glyphs*sizeof(int));
186 glyph2glyph = rfx_calloc(face->num_glyphs*sizeof(int));
188 if(FT_HAS_GLYPH_NAMES(face)) {
189 //font->glyphnames = rfx_calloc(face->num_glyphs*sizeof(char*));
192 fontname = FT_Get_Postscript_Name(face);
196 charcode = FT_Get_First_Char(face, &gindex);
199 if(gindex >= 0 && gindex<face->num_glyphs) {
200 if(!glyph2unicode[gindex]) {
201 glyph2unicode[gindex] = charcode;
202 if(charcode + 1 > font->max_unicode) {
203 font->max_unicode = charcode + 1;
207 charcode = FT_Get_Next_Char(face, charcode, &gindex);
210 /* if we didn't find a single encoding character, try
211 the font's charmaps instead. That usually means that
212 the encoding is no longer unicode.
213 TODO: find a way to convert the encoding to unicode
215 if(font->max_unicode == 0 && charmap < face->num_charmaps-1 &&
216 face->charmaps[charmap+1]->encoding != 0x41444243 /* custom */)
219 FT_Set_Charmap(face, face->charmaps[charmap]);
225 /* TODO: if isunicode is 1, we now need to permutate the character
226 order so that each character is at it's encoding position */
229 font->max_unicode = 65535;
231 font->unicode2glyph = rfx_calloc(font->max_unicode*sizeof(int));
233 for(t=0;t<font->max_unicode;t++) {
234 int g = FT_Get_Char_Index(face, t);
235 if(!g || g>=face->num_glyphs)
237 font->unicode2glyph[t] = g;
240 if(!glyph2unicode[g]) {
241 glyph2unicode[g] = t;
245 font->max_unicode = max_unicode;
247 font->num_glyphs = 0;
250 for(t=0; t < face->num_glyphs; t++) {
251 if(FT_HAS_GLYPH_NAMES(face)) {
253 error = FT_Get_Glyph_Name(face, t, name, 127);
254 if(!error && name[0] && !strstr(name, "notdef")) {
261 for(t=0; t < face->num_glyphs; t++) {
273 font->glyphs[font->num_glyphs].advance = 0;
274 font->glyphs[font->num_glyphs].line = 0;
275 font->glyphs[font->num_glyphs].unicode = glyph2unicode[t];
276 font->glyphs[font->num_glyphs].name = 0;
278 if(FT_HAS_GLYPH_NAMES(face) && (num_names >= face->num_glyphs/10 || num_names > 2)) {
280 error = FT_Get_Glyph_Name(face, t, name, 127);
281 if(!error && name[0] && !strstr(name, "notdef")) {
282 font->glyphs[font->num_glyphs].name = strdup(name);
287 #if 0 // some cantonese pdfs fail to work if this is activated
289 if(has_had_errors && (isunicode && !glyph2unicode[t]) && !hasname && t>=256) {
290 /* some freetype versions crash or corrupt memory if we try to load
291 characters (without unicode index or name) above 256 for some fonts.
292 So skip those characters once the first error occured */
298 error = FT_Load_Glyph(face, t, FT_LOAD_NO_BITMAP);
301 fprintf(stderr, "Warning: glyph %d/%d (unicode %d, name %s) has return code %d\n", t, face->num_glyphs, glyph2unicode[t], name, error);
303 fprintf(stderr, "Warning: glyph %d/%d (unicode %d) has return code %d\n", t, face->num_glyphs, glyph2unicode[t], error);
307 if(!has_had_errors) {
309 if(fontname && *fontname) {
310 fprintf(stderr, "font has been copied to %s.ttf\n", fontname);
311 sprintf(buf, "cp %s %s.ttf", filename, fontname);
313 fprintf(stderr, "font has been copied to badfont%d.ttf\n", errorno);
314 sprintf(buf, "cp %s badfont%d.ttf", filename, errorno);
324 error = FT_Get_Glyph(face->glyph, &glyph);
326 fprintf(stderr, "Couldn't get glyph %d/%d, error:%d\n", t, face->num_glyphs, error);
334 gfxdrawer_target_gfxline(&draw);
336 info.quality = quality;
338 //error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info);
339 error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info);
342 fprintf(stderr, "Couldn't decompose glyph %d\n", t);
343 gfxline_free((gfxline_t*)draw.result(&draw));
344 FT_Done_Glyph(glyph);
347 font->glyphs[font->num_glyphs].advance = (glyph->advance.x*20)/65536;
348 font->glyphs[font->num_glyphs].line = (gfxline_t*)draw.result(&draw);
350 l = font->glyphs[font->num_glyphs].line;
352 if(l->type != gfx_moveTo) {
358 gfxline_free(font->glyphs[font->num_glyphs].line);
359 font->glyphs[font->num_glyphs].line = 0;
360 font->glyphs[font->num_glyphs].advance = 0;
362 /* Some PDFs created e.g. by InDesign tend to create
363 fonts with reduced (empty) characters, which still
364 have unicode indices attached to them.
365 Remove that information, in order to not confuse
366 any converter applications.
368 font->glyphs[font->num_glyphs].unicode = 0;
369 if(font->glyphs[font->num_glyphs].name) {
370 free(font->glyphs[font->num_glyphs].name);
371 font->glyphs[font->num_glyphs].name = 0;
373 FT_Done_Glyph(glyph);
379 FT_Done_Glyph(glyph);
380 font->glyphs[font->num_glyphs].unicode = glyph2unicode[t];
383 glyph2glyph[t] = font->num_glyphs;
387 /* notice: if skip_unused is true, font->glyph2unicode, font->glyphnames and font->layout->bounds will
388 have more memory allocated than just font->num_glyphs, but only the first font->numchars
391 for(t=0;t<font->max_unicode;t++) {
392 if(font->unicode2glyph[t]>=0) {
393 font->unicode2glyph[t] = glyph2glyph[font->unicode2glyph[t]];
396 rfx_free(glyph2glyph);
397 rfx_free(glyph2unicode);
400 FT_Done_FreeType(ftlibrary);ftlibrary=0;
402 if(!isunicode && font->num_glyphs>0 && font->max_unicode) {
403 /* if the encoding isn't unicode, remap the font
404 so that the encoding equals the char position, and
405 remove the unicode table */
407 gfxglyph_t*newglyphs = rfx_calloc(font->max_unicode*sizeof(gfxglyph_t));
409 for(t=0;t<max_unicode;t++) {
410 int c = font->unicode2glyph[t];
411 if(c>=font->num_glyphs || c<0)
413 newglyphs[t] = cloneGlyph(&font->glyphs[c]);
414 newglyphs[t].unicode = -1;
416 for(t=0;t<font->num_glyphs;t++) {
417 glyph_clear(&font->glyphs[t]);
420 font->glyphs = newglyphs;
421 font->num_glyphs = font->max_unicode;
423 free(font->unicode2glyph);font->unicode2glyph = 0;
424 font->max_unicode = 0;
427 if(font->unicode2glyph) {
430 /* check whether the Unicode indices look o.k.
431 If they don't, disable the unicode lookup by setting
432 the unicode map to -1 everywhere */
433 for(t=0;t<font->num_glyphs;t++) {
434 int c = font->glyphs[t].unicode;
435 gfxline_t* line = font->glyphs[t].line;
436 if(c && c < 32 && (line && line->next && line->next->next)) {
437 // the character maps into the unicode control character range
438 // between 0001-001f. Yet it is not empty. Treat the one
439 // mapping as broken, and look how many of those we find.
444 free(font->unicode2glyph);font->unicode2glyph = 0;
445 font->max_unicode = 0;
446 for(t=0;t<font->num_glyphs;t++) {
447 font->glyphs[t].unicode = -1;
456 gfxfont_t* gfxfont_load(char*filename)
458 fprintf(stderr, "No freetype support compiled in! Not able to load %s\n", filename);
463 void gfxfont_free(gfxfont_t*font)
466 for(t=0;t<font->num_glyphs;t++) {
467 glyph_clear(&font->glyphs[t]);
470 free(font->glyphs);font->glyphs = 0;
472 font->num_glyphs = 0;
473 if(font->unicode2glyph) {
474 free(font->unicode2glyph);font->unicode2glyph = 0;