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*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?\n", filename);
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;
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));
187 if(FT_HAS_GLYPH_NAMES(face)) {
188 //font->glyphnames = rfx_calloc(face->num_glyphs*sizeof(char*));
191 fontname = FT_Get_Postscript_Name(face);
195 charcode = FT_Get_First_Char(face, &gindex);
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;
206 charcode = FT_Get_Next_Char(face, charcode, &gindex);
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
214 if(font->max_unicode == 0 && charmap < face->num_charmaps - 1) {
216 FT_Set_Charmap(face, face->charmaps[charmap]);
222 /* TODO: if isunicode is 1, we now need to permutate the character
223 order so that each character is at it's encoding position */
226 font->max_unicode = 65535;
228 font->unicode2glyph = rfx_calloc(font->max_unicode*sizeof(int));
230 for(t=0;t<font->max_unicode;t++) {
231 int g = FT_Get_Char_Index(face, t);
232 if(!g || g>=face->num_glyphs)
234 font->unicode2glyph[t] = g;
237 if(!glyph2unicode[g]) {
238 glyph2unicode[g] = t;
242 font->max_unicode = max_unicode;
244 font->num_glyphs = 0;
247 for(t=0; t < face->num_glyphs; t++) {
248 if(FT_HAS_GLYPH_NAMES(face)) {
250 error = FT_Get_Glyph_Name(face, t, name, 127);
251 if(!error && name[0] && !strstr(name, "notdef")) {
258 for(t=0; t < face->num_glyphs; t++) {
270 font->glyphs[font->num_glyphs].advance = 0;
271 font->glyphs[font->num_glyphs].line = 0;
272 font->glyphs[font->num_glyphs].unicode = glyph2unicode[t];
273 font->glyphs[font->num_glyphs].name = 0;
275 if(FT_HAS_GLYPH_NAMES(face) && (num_names >= face->num_glyphs/10 || num_names > 2)) {
277 error = FT_Get_Glyph_Name(face, t, name, 127);
278 if(!error && name[0] && !strstr(name, "notdef")) {
279 font->glyphs[font->num_glyphs].name = strdup(name);
283 if(has_had_errors && (isunicode && !glyph2unicode[t]) && !hasname) {
284 /* some freetype versions crash or corrupt memory if we try to load
285 characters (without unicode index or name) above 256 for some fonts.
286 So skip those characters once the first error occured */
290 error = FT_Load_Glyph(face, t, FT_LOAD_NO_BITMAP);
293 fprintf(stderr, "Warning: glyph %d/%d (unicode %d, name %s) has return code %d\n", t, face->num_glyphs, glyph2unicode[t], name, error);
295 fprintf(stderr, "Warning: glyph %d/%d (unicode %d) has return code %d\n", t, face->num_glyphs, glyph2unicode[t], error);
299 if(!has_had_errors) {
301 if(fontname && *fontname) {
302 fprintf(stderr, "font has been copied to %s.ttf\n", fontname);
303 sprintf(buf, "cp %s %s.ttf", filename, fontname);
305 fprintf(stderr, "font has been copied to badfont%d.ttf\n", errorno);
306 sprintf(buf, "cp %s badfont%d.ttf", filename, errorno);
316 error = FT_Get_Glyph(face->glyph, &glyph);
318 fprintf(stderr, "Couldn't get glyph %d/%d, error:%d\n", t, face->num_glyphs, error);
326 gfxdrawer_target_gfxline(&draw);
328 info.quality = quality;
330 //error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info);
331 error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info);
334 fprintf(stderr, "Couldn't decompose glyph %d\n", t);
335 gfxline_free((gfxline_t*)draw.result(&draw));
336 FT_Done_Glyph(glyph);
339 font->glyphs[font->num_glyphs].advance = glyph->advance.x*20/65536;
340 font->glyphs[font->num_glyphs].line = (gfxline_t*)draw.result(&draw);
342 l = font->glyphs[font->num_glyphs].line;
344 if(l->type != gfx_moveTo) {
350 gfxline_free(font->glyphs[font->num_glyphs].line);
351 font->glyphs[font->num_glyphs].line = 0;
352 font->glyphs[font->num_glyphs].advance = 0;
354 /* Some PDFs created e.g. by InDesign tend to create
355 fonts with reduced (empty) characters, which still
356 have unicode indices attached to them.
357 Remove that information, in order to not confuse
358 any converter applications.
360 font->glyphs[font->num_glyphs].unicode = 0;
361 if(font->glyphs[font->num_glyphs].name) {
362 free(font->glyphs[font->num_glyphs].name);
363 font->glyphs[font->num_glyphs].name = 0;
365 FT_Done_Glyph(glyph);
371 FT_Done_Glyph(glyph);
372 font->glyphs[font->num_glyphs].unicode = glyph2unicode[t];
375 glyph2glyph[t] = font->num_glyphs;
379 /* notice: if skip_unused is true, font->glyph2unicode, font->glyphnames and font->layout->bounds will
380 have more memory allocated than just font->num_glyphs, but only the first font->numchars
383 for(t=0;t<font->max_unicode;t++) {
384 if(font->unicode2glyph[t]>=0) {
385 font->unicode2glyph[t] = glyph2glyph[font->unicode2glyph[t]];
388 rfx_free(glyph2glyph);
389 rfx_free(glyph2unicode);
392 FT_Done_FreeType(ftlibrary);ftlibrary=0;
394 if(!isunicode && font->num_glyphs>0 && font->max_unicode) {
395 /* if the encoding isn't unicode, remap the font
396 so that the encoding equals the char position, and
397 remove the unicode table */
399 gfxglyph_t*newglyphs = rfx_calloc(font->max_unicode*sizeof(gfxglyph_t));
401 for(t=0;t<max_unicode;t++) {
402 int c = font->unicode2glyph[t];
403 if(c>=font->num_glyphs || c<0)
405 newglyphs[t] = cloneGlyph(&font->glyphs[c]);
406 newglyphs[t].unicode = -1;
408 for(t=0;t<font->num_glyphs;t++) {
409 glyph_clear(&font->glyphs[t]);
412 font->glyphs = newglyphs;
413 font->num_glyphs = font->max_unicode;
415 free(font->unicode2glyph);font->unicode2glyph = 0;
416 font->max_unicode = 0;
419 if(font->unicode2glyph) {
422 /* check whether the Unicode indices look o.k.
423 If they don't, disable the unicode lookup by setting
424 the unicode map to -1 everywhere */
425 for(t=0;t<font->num_glyphs;t++) {
426 int c = font->glyphs[t].unicode;
427 gfxline_t* line = font->glyphs[t].line;
428 if(c && c < 32 && (line && line->next && line->next->next)) {
429 // the character maps into the unicode control character range
430 // between 0001-001f. Yet it is not empty. Treat the one
431 // mapping as broken, and look how many of those we find.
436 free(font->unicode2glyph);font->unicode2glyph = 0;
437 font->max_unicode = 0;
438 for(t=0;t<font->num_glyphs;t++) {
439 font->glyphs[t].unicode = -1;
448 gfxfont_t* gfxfont_load(char*filename)
450 fprintf(stderr, "No freetype support compiled in! Not able to load %s\n", filename);
455 void gfxfont_free(gfxfont_t*font)
458 for(t=0;t<font->num_glyphs;t++) {
459 glyph_clear(&font->glyphs[t]);
462 free(font->glyphs);font->glyphs = 0;
464 font->num_glyphs = 0;
465 if(font->unicode2glyph) {
466 free(font->unicode2glyph);font->unicode2glyph = 0;