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);
286 if(has_had_errors && (isunicode && !glyph2unicode[t]) && !hasname) {
287 /* some freetype versions crash or corrupt memory if we try to load
288 characters (without unicode index or name) above 256 for some fonts.
289 So skip those characters once the first error occured */
293 error = FT_Load_Glyph(face, t, FT_LOAD_NO_BITMAP);
296 fprintf(stderr, "Warning: glyph %d/%d (unicode %d, name %s) has return code %d\n", t, face->num_glyphs, glyph2unicode[t], name, error);
298 fprintf(stderr, "Warning: glyph %d/%d (unicode %d) has return code %d\n", t, face->num_glyphs, glyph2unicode[t], error);
302 if(!has_had_errors) {
304 if(fontname && *fontname) {
305 fprintf(stderr, "font has been copied to %s.ttf\n", fontname);
306 sprintf(buf, "cp %s %s.ttf", filename, fontname);
308 fprintf(stderr, "font has been copied to badfont%d.ttf\n", errorno);
309 sprintf(buf, "cp %s badfont%d.ttf", filename, errorno);
319 error = FT_Get_Glyph(face->glyph, &glyph);
321 fprintf(stderr, "Couldn't get glyph %d/%d, error:%d\n", t, face->num_glyphs, error);
329 gfxdrawer_target_gfxline(&draw);
331 info.quality = quality;
333 //error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info);
334 error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info);
337 fprintf(stderr, "Couldn't decompose glyph %d\n", t);
338 gfxline_free((gfxline_t*)draw.result(&draw));
339 FT_Done_Glyph(glyph);
342 font->glyphs[font->num_glyphs].advance = (glyph->advance.x*20)/65536;
343 font->glyphs[font->num_glyphs].line = (gfxline_t*)draw.result(&draw);
345 l = font->glyphs[font->num_glyphs].line;
347 if(l->type != gfx_moveTo) {
353 gfxline_free(font->glyphs[font->num_glyphs].line);
354 font->glyphs[font->num_glyphs].line = 0;
355 font->glyphs[font->num_glyphs].advance = 0;
357 /* Some PDFs created e.g. by InDesign tend to create
358 fonts with reduced (empty) characters, which still
359 have unicode indices attached to them.
360 Remove that information, in order to not confuse
361 any converter applications.
363 font->glyphs[font->num_glyphs].unicode = 0;
364 if(font->glyphs[font->num_glyphs].name) {
365 free(font->glyphs[font->num_glyphs].name);
366 font->glyphs[font->num_glyphs].name = 0;
368 FT_Done_Glyph(glyph);
374 FT_Done_Glyph(glyph);
375 font->glyphs[font->num_glyphs].unicode = glyph2unicode[t];
378 glyph2glyph[t] = font->num_glyphs;
382 /* notice: if skip_unused is true, font->glyph2unicode, font->glyphnames and font->layout->bounds will
383 have more memory allocated than just font->num_glyphs, but only the first font->numchars
386 for(t=0;t<font->max_unicode;t++) {
387 if(font->unicode2glyph[t]>=0) {
388 font->unicode2glyph[t] = glyph2glyph[font->unicode2glyph[t]];
391 rfx_free(glyph2glyph);
392 rfx_free(glyph2unicode);
395 FT_Done_FreeType(ftlibrary);ftlibrary=0;
397 if(!isunicode && font->num_glyphs>0 && font->max_unicode) {
398 /* if the encoding isn't unicode, remap the font
399 so that the encoding equals the char position, and
400 remove the unicode table */
402 gfxglyph_t*newglyphs = rfx_calloc(font->max_unicode*sizeof(gfxglyph_t));
404 for(t=0;t<max_unicode;t++) {
405 int c = font->unicode2glyph[t];
406 if(c>=font->num_glyphs || c<0)
408 newglyphs[t] = cloneGlyph(&font->glyphs[c]);
409 newglyphs[t].unicode = -1;
411 for(t=0;t<font->num_glyphs;t++) {
412 glyph_clear(&font->glyphs[t]);
415 font->glyphs = newglyphs;
416 font->num_glyphs = font->max_unicode;
418 free(font->unicode2glyph);font->unicode2glyph = 0;
419 font->max_unicode = 0;
422 if(font->unicode2glyph) {
425 /* check whether the Unicode indices look o.k.
426 If they don't, disable the unicode lookup by setting
427 the unicode map to -1 everywhere */
428 for(t=0;t<font->num_glyphs;t++) {
429 int c = font->glyphs[t].unicode;
430 gfxline_t* line = font->glyphs[t].line;
431 if(c && c < 32 && (line && line->next && line->next->next)) {
432 // the character maps into the unicode control character range
433 // between 0001-001f. Yet it is not empty. Treat the one
434 // mapping as broken, and look how many of those we find.
439 free(font->unicode2glyph);font->unicode2glyph = 0;
440 font->max_unicode = 0;
441 for(t=0;t<font->num_glyphs;t++) {
442 font->glyphs[t].unicode = -1;
451 gfxfont_t* gfxfont_load(char*filename)
453 fprintf(stderr, "No freetype support compiled in! Not able to load %s\n", filename);
458 void gfxfont_free(gfxfont_t*font)
461 for(t=0;t<font->num_glyphs;t++) {
462 glyph_clear(&font->glyphs[t]);
465 free(font->glyphs);font->glyphs = 0;
467 font->num_glyphs = 0;
468 if(font->unicode2glyph) {
469 free(font->unicode2glyph);font->unicode2glyph = 0;