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]);
217 //font->encoding = 0;//anything but unicode FIXME
223 /* TODO: if isunicode is 1, we now need to permutate the character
224 order so that each character is at it's encoding position */
227 font->max_unicode = 65535;
229 font->unicode2glyph = rfx_calloc(font->max_unicode*sizeof(int));
231 for(t=0;t<font->max_unicode;t++) {
232 int g = FT_Get_Char_Index(face, t);
233 if(!g || g>=face->num_glyphs)
235 font->unicode2glyph[t] = g;
238 if(!glyph2unicode[g]) {
239 glyph2unicode[g] = t;
243 font->max_unicode = max_unicode;
245 font->num_glyphs = 0;
248 for(t=0; t < face->num_glyphs; t++) {
249 if(FT_HAS_GLYPH_NAMES(face)) {
251 error = FT_Get_Glyph_Name(face, t, name, 127);
252 if(!error && name[0] && !strstr(name, "notdef")) {
259 for(t=0; t < face->num_glyphs; t++) {
271 font->glyphs[font->num_glyphs].advance = 0;
272 font->glyphs[font->num_glyphs].line = 0;
273 font->glyphs[font->num_glyphs].unicode = glyph2unicode[t];
274 font->glyphs[font->num_glyphs].name = 0;
276 if(FT_HAS_GLYPH_NAMES(face) && (num_names >= face->num_glyphs/10 || num_names > 2)) {
278 error = FT_Get_Glyph_Name(face, t, name, 127);
279 if(!error && name[0] && !strstr(name, "notdef")) {
280 font->glyphs[font->num_glyphs].name = strdup(name);
284 if(has_had_errors && (isunicode && !glyph2unicode[t]) && !hasname) {
285 /* some freetype versions crash or corrupt memory if we try to load
286 characters (without unicode index or name) above 256 for some fonts.
287 So skip those characters once the first error occured */
291 error = FT_Load_Glyph(face, t, FT_LOAD_NO_BITMAP);
294 fprintf(stderr, "Warning: glyph %d/%d (unicode %d, name %s) has return code %d\n", t, face->num_glyphs, glyph2unicode[t], name, error);
296 fprintf(stderr, "Warning: glyph %d/%d (unicode %d) has return code %d\n", t, face->num_glyphs, glyph2unicode[t], error);
300 if(!has_had_errors) {
302 if(fontname && *fontname) {
303 fprintf(stderr, "font has been copied to %s.ttf\n", fontname);
304 sprintf(buf, "cp %s %s.ttf", filename, fontname);
306 fprintf(stderr, "font has been copied to badfont%d.ttf\n", errorno);
307 sprintf(buf, "cp %s badfont%d.ttf", filename, errorno);
317 error = FT_Get_Glyph(face->glyph, &glyph);
319 fprintf(stderr, "Couldn't get glyph %d/%d, error:%d\n", t, face->num_glyphs, error);
327 gfxdrawer_target_gfxline(&draw);
329 info.quality = quality;
331 //error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info);
332 error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info);
335 fprintf(stderr, "Couldn't decompose glyph %d\n", t);
336 gfxline_free((gfxline_t*)draw.result(&draw));
337 FT_Done_Glyph(glyph);
340 font->glyphs[font->num_glyphs].advance = glyph->advance.x*20/65536;
341 font->glyphs[font->num_glyphs].line = (gfxline_t*)draw.result(&draw);
343 l = font->glyphs[font->num_glyphs].line;
345 if(l->type != gfx_moveTo) {
351 gfxline_free(font->glyphs[font->num_glyphs].line);
352 font->glyphs[font->num_glyphs].line = 0;
353 font->glyphs[font->num_glyphs].advance = 0;
355 /* Some PDFs created e.g. by InDesign tend to create
356 fonts with reduced (empty) characters, which still
357 have unicode indices attached to them.
358 Remove that information, in order to not confuse
359 any converter applications.
361 TODO: what about space characters? */
362 font->glyphs[font->num_glyphs].unicode = 0;
363 if(font->glyphs[font->num_glyphs].name) {
364 free(font->glyphs[font->num_glyphs].name);
365 font->glyphs[font->num_glyphs].name = 0;
367 FT_Done_Glyph(glyph);
373 FT_Done_Glyph(glyph);
374 font->glyphs[font->num_glyphs].unicode = glyph2unicode[t];
377 glyph2glyph[t] = font->num_glyphs;
381 /* notice: if skip_unused is true, font->glyph2unicode, font->glyphnames and font->layout->bounds will
382 have more memory allocated than just font->num_glyphs, but only the first font->numchars
385 for(t=0;t<font->max_unicode;t++) {
386 if(font->unicode2glyph[t]>=0) {
387 font->unicode2glyph[t] = glyph2glyph[font->unicode2glyph[t]];
390 rfx_free(glyph2glyph);
391 rfx_free(glyph2unicode);
394 FT_Done_FreeType(ftlibrary);ftlibrary=0;
396 if(!isunicode && font->num_glyphs>0) {
397 /* if the encoding isn't unicode, remap the font
398 so that the encoding equals the char position, and
399 remove the unicode table */
401 gfxglyph_t*newglyphs = rfx_calloc(font->max_unicode*sizeof(gfxglyph_t));
403 for(t=0;t<max_unicode;t++) {
404 int c = font->unicode2glyph[t];
405 if(c>=font->num_glyphs || c<0)
407 newglyphs[t] = cloneGlyph(&font->glyphs[c]);
408 newglyphs[t].unicode = -1;
410 for(t=0;t<font->num_glyphs;t++) {
411 glyph_clear(&font->glyphs[t]);
414 font->glyphs = newglyphs;
415 font->num_glyphs = font->max_unicode;
417 free(font->unicode2glyph);font->unicode2glyph = 0;
418 font->max_unicode = 0;
421 if(font->unicode2glyph) {
424 /* check whether the Unicode indices look o.k.
425 If they don't, disable the unicode lookup by setting
426 the unicode map to -1 everywhere */
427 for(t=0;t<font->num_glyphs;t++) {
428 int c = font->glyphs[t].unicode;
429 gfxline_t* line = font->glyphs[t].line;
430 if(c && c < 32 && (line && line->next && line->next->next)) {
431 // the character maps into the unicode control character range
432 // between 0001-001f. Yet it is not empty. Treat the one
433 // mapping as broken, and look how many of those we find.
438 free(font->unicode2glyph);font->unicode2glyph = 0;
439 font->max_unicode = 0;
440 for(t=0;t<font->num_glyphs;t++) {
441 font->glyphs[t].unicode = -1;
450 gfxfont_t* gfxfont_load(char*filename)
452 fprintf(stderr, "No freetype support compiled in! Not able to load %s\n", filename);
457 void gfxfont_free(gfxfont_t*font)
460 for(t=0;t<font->num_glyphs;t++) {
461 glyph_clear(&font->glyphs[t]);
464 free(font->glyphs);font->glyphs = 0;
466 font->num_glyphs = 0;
467 if(font->unicode2glyph) {
468 free(font->unicode2glyph);font->unicode2glyph = 0;