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"
30 static int loadfont_scale = 64;
31 static int full_unicode = 1;
35 #ifdef HAVE_FT2BUILD_H
37 #include FT_FREETYPE_H
40 #include FT_SFNT_NAMES_H
41 #include FT_TRUETYPE_IDS_H
44 #include <freetype/freetype.h>
45 #include <freetype/ftglyph.h>
46 #include <freetype/ftsizes.h>
47 #include <freetype/ftsnames.h>
48 #include <freetype/ttnameid.h>
49 #include <freetype/ftoutln.h>
52 /* Setting subpixels to 64 also means that the "point size" of the
53 font outlines will be 64. So the font, when rendered at original
54 size (i.e., the swf fontsize is 1024) will have the same size as
55 if it was rendered at 64pt */
58 #define FT_SUBPIXELS 64
60 typedef struct _gfxdrawinfo_t {
65 static int ft_move_to(const FT_Vector* _to, void* user)
67 gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
68 gfxdrawer_t* draw = info->draw;
69 double x = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
70 double y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
71 draw->moveTo(draw, x,y);
74 static int ft_line_to(const FT_Vector* _to, void* user)
76 gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
77 gfxdrawer_t* draw = info->draw;
78 double x = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
79 double y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
80 draw->lineTo(draw, x,y);
83 static int ft_cubic_to(const FT_Vector* _c1, const FT_Vector* _c2, const FT_Vector* _to, void* user)
85 gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
86 gfxdrawer_t* draw = info->draw;
87 double tox = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
88 double toy = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
89 double c1x = _c1->x*FT_SCALE/(float)FT_SUBPIXELS;
90 double c1y = -_c1->y*FT_SCALE/(float)FT_SUBPIXELS;
91 double c2x = _c2->x*FT_SCALE/(float)FT_SUBPIXELS;
92 double c2y = -_c2->y*FT_SCALE/(float)FT_SUBPIXELS;
93 gfxdraw_cubicTo(draw, c1x, c1y, c2x, c2y, tox, toy, info->quality);
96 static int ft_conic_to(const FT_Vector* _c, const FT_Vector* _to, void* user)
98 gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
99 gfxdrawer_t* draw = info->draw;
100 double tox = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
101 double toy = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
102 double cx = _c->x*FT_SCALE/(float)FT_SUBPIXELS;
103 double cy = -_c->y*FT_SCALE/(float)FT_SUBPIXELS;
104 gfxdraw_conicTo(draw, cx,cy, tox,toy, info->quality);
107 static FT_Outline_Funcs outline_functions =
116 static FT_Library ftlibrary = 0;
118 static gfxglyph_t cloneGlyph(gfxglyph_t*src)
121 memset(&dest, 0, sizeof(dest));
123 dest.name = strdup(src->name);
124 dest.advance = src->advance;
125 dest.unicode = src->unicode;
126 dest.line = gfxline_clone(src->line);
130 static void glyph_clear(gfxglyph_t*g)
134 free((void*)g->name); g->name = 0;
136 gfxline_free(g->line);g->line = 0;
139 static int errorno = 0;
143 gfxfont_t* gfxfont_load(char*id, char*filename, unsigned int flags, double quality)
147 const char* fontname = 0;
153 int*glyph2unicode = 0;
157 int has_had_errors = 0;
161 if(FT_Init_FreeType(&ftlibrary)) {
162 fprintf(stderr, "Couldn't init freetype library!\n");
166 error = FT_New_Face(ftlibrary, filename, 0, &face);
167 FT_Set_Pixel_Sizes (face, 16*loadfont_scale, 16*loadfont_scale);
169 printf("gfxfont_load(%s, %s, %f)\n", id, filename, quality);
173 fprintf(stderr, "Couldn't load file %s- not a TTF file? (error=%02x)\n", filename, error);
176 if(face->num_glyphs <= 0) {
177 fprintf(stderr, "File %s contains %d glyphs\n", filename, (int)face->num_glyphs);
181 font = (gfxfont_t*)rfx_calloc(sizeof(gfxfont_t));
182 //font->style = ((face->style_flags&FT_STYLE_FLAG_ITALIC)?FONT_STYLE_ITALIC:0) |((face->style_flags&FT_STYLE_FLAG_BOLD)?FONT_STYLE_BOLD:0);
183 //font->ascent = abs(face->ascender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMin;
184 //font->descent = abs(face->descender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMax;
185 //font->leading = font->layout->ascent + font->layout->descent;
186 //font->encoding = FONT_ENCODING_UNICODE;
187 font->max_unicode = 0;
188 font->id = strdup(id);
190 font->glyphs = (gfxglyph_t*)rfx_calloc(face->num_glyphs*sizeof(gfxglyph_t));
191 glyph2unicode = (int*)rfx_calloc(face->num_glyphs*sizeof(int));
192 glyph2glyph = (int*)rfx_calloc(face->num_glyphs*sizeof(int));
194 if(FT_HAS_GLYPH_NAMES(face)) {
195 //font->glyphnames = rfx_calloc(face->num_glyphs*sizeof(char*));
198 fontname = FT_Get_Postscript_Name(face);
201 for(t=0;t<face->num_charmaps;t++) {
202 printf("possible encoding: %c%c%c%c (%d of %d)\n",
203 (face->charmaps[t]->encoding >> 24)&255,
204 (face->charmaps[t]->encoding >> 16)&255,
205 (face->charmaps[t]->encoding >> 8)&255,
206 (face->charmaps[t]->encoding >> 0)&255,
207 t+1, face->num_charmaps
214 charcode = FT_Get_First_Char(face, &gindex);
218 if(gindex >= 0 && gindex<face->num_glyphs) {
219 if(!glyph2unicode[gindex]) {
220 glyph2unicode[gindex] = charcode;
221 if(charcode + 1 > font->max_unicode) {
222 font->max_unicode = charcode + 1;
226 charcode = FT_Get_Next_Char(face, charcode, &gindex);
231 printf("ENCODING: %c%c%c%c (%d of %d) max_unicode=%d\n",
232 (face->charmap->encoding >> 24)&255,
233 (face->charmap->encoding >> 16)&255,
234 (face->charmap->encoding >> 8)&255,
235 (face->charmap->encoding >> 0)&255,
236 charmap, face->num_charmaps, font->max_unicode
239 printf("ENCODING: NONE (%d of %d) max_unicode=%d\n",
240 charmap, face->num_charmaps, font->max_unicode
245 /* if we didn't find a single encoding character, try
246 the font's charmaps instead. That usually means that
247 the encoding is no longer unicode.
248 TODO: find a way to convert the encoding to unicode
250 if(font->max_unicode == 0 && charmap < face->num_charmaps-1
251 && face->charmaps[charmap+1]->encoding != 0x41444243 /* adbc, custom */
252 && face->charmaps[charmap+1]->encoding != 0x61726d6e /* armn */
256 FT_Set_Charmap(face, face->charmaps[charmap]);
261 /* TODO: if isunicode is 1, we now need to permutate the character
262 order so that each character is at it's encoding position */
265 font->max_unicode = 65535;
267 font->unicode2glyph = (int*)rfx_calloc(font->max_unicode*sizeof(int));
269 for(t=0;t<font->max_unicode;t++) {
270 int g = FT_Get_Char_Index(face, t);
271 if(!g || g>=face->num_glyphs)
273 font->unicode2glyph[t] = g;
276 printf("u%d ->%d\n", t, g);
279 if(!glyph2unicode[g]) {
280 glyph2unicode[g] = t;
284 font->max_unicode = max_unicode;
286 font->num_glyphs = 0;
289 for(t=0; t < face->num_glyphs; t++) {
290 if(FT_HAS_GLYPH_NAMES(face)) {
292 error = FT_Get_Glyph_Name(face, t, name, 127);
293 if(!error && name[0] && !strstr(name, "notdef")) {
300 for(t=0; t < face->num_glyphs; t++) {
309 font->glyphs[font->num_glyphs].advance = 0;
310 font->glyphs[font->num_glyphs].line = 0;
311 font->glyphs[font->num_glyphs].unicode = glyph2unicode[t];
312 font->glyphs[font->num_glyphs].name = 0;
314 if(FT_HAS_GLYPH_NAMES(face) && (num_names >= face->num_glyphs/10 || num_names > 2)) {
316 error = FT_Get_Glyph_Name(face, t, name, 127);
317 if(!error && name[0] && !strstr(name, "notdef")) {
318 font->glyphs[font->num_glyphs].name = strdup(name);
323 #if 0 // some cantonese pdfs fail to work if this is activated
325 if(has_had_errors && (isunicode && !glyph2unicode[t]) && !hasname && t>=256) {
326 /* some freetype versions crash or corrupt memory if we try to load
327 characters (without unicode index or name) above 256 for some fonts.
328 So skip those characters once the first error occured */
334 error = FT_Load_Glyph(face, t, FT_LOAD_NO_BITMAP);
337 fprintf(stderr, "Warning: glyph %d/%d (unicode %d, name %s) has return code %d\n", t, (int)face->num_glyphs, glyph2unicode[t], name, error);
339 fprintf(stderr, "Warning: glyph %d/%d (unicode %d) has return code %d\n", t, (int)face->num_glyphs, glyph2unicode[t], error);
343 if(!has_had_errors) {
345 if(fontname && *fontname) {
346 fprintf(stderr, "font has been copied to %s.ttf\n", fontname);
347 sprintf(buf, "cp %s %s.ttf", filename, fontname);
349 fprintf(stderr, "font has been copied to badfont%d.ttf\n", errorno);
350 sprintf(buf, "cp %s badfont%d.ttf", filename, errorno);
360 error = FT_Get_Glyph(face->glyph, &glyph);
362 fprintf(stderr, "Couldn't get glyph %d/%d, error:%d\n", t, (int)face->num_glyphs, error);
370 gfxdrawer_target_gfxline(&draw);
372 info.quality = quality;
374 //error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info);
375 error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info);
378 fprintf(stderr, "Couldn't decompose glyph %d\n", t);
379 gfxline_free((gfxline_t*)draw.result(&draw));
380 FT_Done_Glyph(glyph);
383 font->glyphs[font->num_glyphs].advance = glyph->advance.x/65536;
384 font->glyphs[font->num_glyphs].line = (gfxline_t*)draw.result(&draw);
386 l = font->glyphs[font->num_glyphs].line;
388 if(l->type != gfx_moveTo) {
394 gfxline_free(font->glyphs[font->num_glyphs].line);
395 font->glyphs[font->num_glyphs].line = 0;
396 font->glyphs[font->num_glyphs].advance = 0;
398 /* Some PDFs created e.g. by InDesign tend to create
399 fonts with reduced (empty) characters, which still
400 have unicode indices attached to them.
401 Remove that information, in order to not confuse
402 any converter applications.
404 font->glyphs[font->num_glyphs].unicode = 0;
405 if(font->glyphs[font->num_glyphs].name) {
406 free((void*)font->glyphs[font->num_glyphs].name);
407 font->glyphs[font->num_glyphs].name = 0;
409 FT_Done_Glyph(glyph);
415 FT_Done_Glyph(glyph);
416 font->glyphs[font->num_glyphs].unicode = glyph2unicode[t];
419 glyph2glyph[t] = font->num_glyphs;
423 /* notice: if skip_unused is true, font->glyph2unicode, font->glyphnames and font->layout->bounds will
424 have more memory allocated than just font->num_glyphs, but only the first font->numchars
427 for(t=0;t<font->max_unicode;t++) {
428 if(font->unicode2glyph[t]>=0) {
429 font->unicode2glyph[t] = glyph2glyph[font->unicode2glyph[t]];
432 rfx_free(glyph2glyph);
433 rfx_free(glyph2unicode);
436 FT_Done_FreeType(ftlibrary);ftlibrary=0;
438 if(!isunicode && font->num_glyphs>0 && font->max_unicode) {
439 /* if the encoding isn't unicode, remap the font
440 so that the encoding equals the char position, and
441 remove the unicode table */
443 gfxglyph_t*newglyphs = (gfxglyph_t*)rfx_calloc(font->max_unicode*sizeof(gfxglyph_t));
445 for(t=0;t<max_unicode;t++) {
446 int c = font->unicode2glyph[t];
447 if(c>=font->num_glyphs || c<0)
449 newglyphs[t] = cloneGlyph(&font->glyphs[c]);
450 newglyphs[t].unicode = -1;
452 for(t=0;t<font->num_glyphs;t++) {
453 glyph_clear(&font->glyphs[t]);
456 font->glyphs = newglyphs;
457 font->num_glyphs = font->max_unicode;
459 free(font->unicode2glyph);font->unicode2glyph = 0;
460 font->max_unicode = 0;
463 if(font->unicode2glyph) {
466 /* check whether the Unicode indices look o.k.
467 If they don't, disable the unicode lookup by setting
468 the unicode map to -1 everywhere */
469 for(t=0;t<font->num_glyphs;t++) {
470 int c = font->glyphs[t].unicode;
471 gfxline_t* line = font->glyphs[t].line;
472 if(c && c < 32 && (line && line->next && line->next->next)) {
473 // the character maps into the unicode control character range
474 // between 0001-001f. Yet it is not empty. Treat the one
475 // mapping as broken, and look how many of those we find.
480 free(font->unicode2glyph);font->unicode2glyph = 0;
481 font->max_unicode = 0;
482 for(t=0;t<font->num_glyphs;t++) {
483 font->glyphs[t].unicode = -1;
492 gfxfont_t* gfxfont_load(char*id, char*filename, unsigned int flags, double quality)
494 fprintf(stderr, "No freetype support compiled in! Not able to load %s\n", filename);
500 void gfxfont_free(gfxfont_t*font)
503 for(t=0;t<font->num_glyphs;t++) {
504 glyph_clear(&font->glyphs[t]);
507 free(font->glyphs);font->glyphs = 0;
509 font->num_glyphs = 0;
510 if(font->unicode2glyph) {
511 free(font->unicode2glyph);font->unicode2glyph = 0;
514 free((void*)font->id);font->id=0;
517 free(font->kerning);font->kerning=0;
523 ttf_t* gfxfont_to_ttf(gfxfont_t*font)
525 ttf_t*ttf = ttf_new();
526 int num_glyphs = font->num_glyphs;
529 char has_nondef_glyph =
530 font->num_glyphs && font->glyphs[0].unicode==-1 &&
531 (!font->glyphs[0].line || !font->glyphs[0].line->next);
533 if(!has_nondef_glyph) {
534 /* insert a new .nondef glyph at the start of the font */
538 ttf->num_glyphs = num_glyphs;
539 ttf->glyphs = rfx_calloc(num_glyphs*sizeof(ttfglyph_t));
541 int max_unicode = font->max_unicode;
543 for(t=0;t<font->num_glyphs;t++) {
544 gfxglyph_t*src = &font->glyphs[t];
545 ttfglyph_t*dest = &ttf->glyphs[t+offset];
546 gfxline_t*line = src->line;
550 if(line->type == gfx_splineTo)
554 dest->num_points = count;
555 dest->points = rfx_calloc(count*sizeof(ttfpoint_t));
559 if(line->type == gfx_splineTo) {
560 dest->points[count].x = line->sx*scale;
561 dest->points[count].y = line->sy*scale;
564 dest->points[count].x = line->x*scale;
565 dest->points[count].y = line->y*scale;
566 dest->points[count].flags |= GLYPH_ON_CURVE;
567 if(line->type == gfx_moveTo) {
568 dest->points[count].flags |= GLYPH_CONTOUR_START;
570 dest->points[count-1].flags |= GLYPH_CONTOUR_END;
576 dest->points[count-1].flags |= GLYPH_CONTOUR_END;
578 /* compute bounding box */
581 dest->xmin = dest->xmax = dest->points[0].x;
582 dest->ymin = dest->ymax = dest->points[0].y;
583 for(s=1;s<count;s++) {
584 if(dest->points[s].x < dest->xmin)
585 dest->xmin = dest->points[s].x;
586 if(dest->points[s].y < dest->ymin)
587 dest->ymin = dest->points[s].y;
588 if(dest->points[s].x > dest->xmax)
589 dest->xmax = dest->points[s].x;
590 if(dest->points[s].y > dest->ymax)
591 dest->ymax = dest->points[s].y;
595 dest->advance = src->advance*scale;
597 int u = font->glyphs[t].unicode;
598 if(u<32 || (u>=0xe000 && u<0xf900)) {
599 u = 0xe000 + remap_pos++;
604 ttf->unicode_size = max_unicode+1;
605 ttf->unicode = rfx_calloc(sizeof(unicode_t)*ttf->unicode_size);
607 for(t=0;t<font->num_glyphs;t++) {
608 gfxglyph_t*src = &font->glyphs[t];
609 int u = font->glyphs[t].unicode;
610 if(u<32 || (u>=0xe000 && u<0xf900)) {
611 u = 0xe000 + remap_pos++;
613 if(u>=0 && u<ttf->unicode_size)
614 ttf->unicode[u] = t+offset;
617 for(u=0;u<font->max_unicode;u++) {
618 int g = font->unicode2glyph[u];
619 if(u<32 || (u>=0xe000 && u<0xf900))
621 if(g>=0 && !ttf->unicode[u]) {
622 ttf->unicode[u] = g+offset;
625 ttf->ascent = font->ascent;
626 ttf->descent = font->descent;
627 ttf->lineGap = font->ascent + font->descent;
629 ttf->name = strdup(font->id);
631 ttf_create_truetype_tables(ttf);
635 void gfxfont_save(gfxfont_t*font, const char*filename)
637 ttf_t*ttf = gfxfont_to_ttf(font);
638 ttf_save(ttf, filename);