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 */
27 #include "../config.h"
28 #include "gfxdevice.h"
35 static int loadfont_scale = 64;
36 static int full_unicode = 1;
40 #ifdef HAVE_FT2BUILD_H
42 #include FT_FREETYPE_H
45 #include FT_SFNT_NAMES_H
46 #include FT_TRUETYPE_IDS_H
49 #include <freetype/freetype.h>
50 #include <freetype/ftglyph.h>
51 #include <freetype/ftsizes.h>
52 #include <freetype/ftsnames.h>
53 #include <freetype/ttnameid.h>
54 #include <freetype/ftoutln.h>
57 /* Setting subpixels to 64 also means that the "point size" of the
58 font outlines will be 64. So the font, when rendered at original
59 size (i.e., the swf fontsize is 1024) will have the same size as
60 if it was rendered at 64pt */
63 #define FT_SUBPIXELS 64
65 typedef struct _gfxdrawinfo_t {
70 static int ft_move_to(const FT_Vector* _to, void* user)
72 gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
73 gfxdrawer_t* draw = info->draw;
74 double x = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
75 double y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
76 draw->moveTo(draw, x,y);
79 static int ft_line_to(const FT_Vector* _to, void* user)
81 gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
82 gfxdrawer_t* draw = info->draw;
83 double x = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
84 double y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
85 draw->lineTo(draw, x,y);
88 static int ft_cubic_to(const FT_Vector* _c1, const FT_Vector* _c2, const FT_Vector* _to, void* user)
90 gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
91 gfxdrawer_t* draw = info->draw;
92 double tox = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
93 double toy = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
94 double c1x = _c1->x*FT_SCALE/(float)FT_SUBPIXELS;
95 double c1y = -_c1->y*FT_SCALE/(float)FT_SUBPIXELS;
96 double c2x = _c2->x*FT_SCALE/(float)FT_SUBPIXELS;
97 double c2y = -_c2->y*FT_SCALE/(float)FT_SUBPIXELS;
98 gfxdraw_cubicTo(draw, c1x, c1y, c2x, c2y, tox, toy, info->quality);
101 static int ft_conic_to(const FT_Vector* _c, const FT_Vector* _to, void* user)
103 gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
104 gfxdrawer_t* draw = info->draw;
105 double tox = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
106 double toy = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
107 double cx = _c->x*FT_SCALE/(float)FT_SUBPIXELS;
108 double cy = -_c->y*FT_SCALE/(float)FT_SUBPIXELS;
109 gfxdraw_conicTo(draw, cx,cy, tox,toy, info->quality);
112 static FT_Outline_Funcs outline_functions =
121 static FT_Library ftlibrary = 0;
123 static gfxglyph_t cloneGlyph(gfxglyph_t*src)
126 memset(&dest, 0, sizeof(dest));
128 dest.name = strdup(src->name);
129 dest.advance = src->advance;
130 dest.unicode = src->unicode;
131 dest.line = gfxline_clone(src->line);
135 static void glyph_clear(gfxglyph_t*g)
139 free((void*)g->name); g->name = 0;
141 gfxline_free(g->line);g->line = 0;
144 static int errorno = 0;
148 gfxfont_t* gfxfont_load(const char*id, const char*filename, unsigned int flags, double quality)
152 const char* fontname = 0;
158 int*glyph2unicode = 0;
162 int has_had_errors = 0;
166 if(FT_Init_FreeType(&ftlibrary)) {
167 fprintf(stderr, "Couldn't init freetype library!\n");
171 error = FT_New_Face(ftlibrary, filename, 0, &face);
172 FT_Set_Pixel_Sizes (face, 16*loadfont_scale, 16*loadfont_scale);
174 printf("gfxfont_load(%s, %s, %f)\n", id, filename, quality);
178 fprintf(stderr, "Couldn't load file %s- not a TTF file? (error=%02x)\n", filename, error);
181 if(face->num_glyphs <= 0) {
182 fprintf(stderr, "File %s contains %d glyphs\n", filename, (int)face->num_glyphs);
186 font = (gfxfont_t*)rfx_calloc(sizeof(gfxfont_t));
187 //font->style = ((face->style_flags&FT_STYLE_FLAG_ITALIC)?FONT_STYLE_ITALIC:0) |((face->style_flags&FT_STYLE_FLAG_BOLD)?FONT_STYLE_BOLD:0);
188 //font->ascent = abs(face->ascender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMin;
189 //font->descent = abs(face->descender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMax;
190 //font->leading = font->layout->ascent + font->layout->descent;
191 //font->encoding = FONT_ENCODING_UNICODE;
192 font->max_unicode = 0;
193 font->id = strdup(id);
195 font->glyphs = (gfxglyph_t*)rfx_calloc(face->num_glyphs*sizeof(gfxglyph_t));
196 glyph2unicode = (int*)rfx_calloc(face->num_glyphs*sizeof(int));
197 glyph2glyph = (int*)rfx_calloc(face->num_glyphs*sizeof(int));
199 if(FT_HAS_GLYPH_NAMES(face)) {
200 //font->glyphnames = rfx_calloc(face->num_glyphs*sizeof(char*));
203 fontname = FT_Get_Postscript_Name(face);
206 for(t=0;t<face->num_charmaps;t++) {
207 printf("possible encoding: %c%c%c%c (%d of %d)\n",
208 (face->charmaps[t]->encoding >> 24)&255,
209 (face->charmaps[t]->encoding >> 16)&255,
210 (face->charmaps[t]->encoding >> 8)&255,
211 (face->charmaps[t]->encoding >> 0)&255,
212 t+1, face->num_charmaps
219 charcode = FT_Get_First_Char(face, &gindex);
223 if(gindex >= 0 && gindex<face->num_glyphs) {
224 if(!glyph2unicode[gindex]) {
225 glyph2unicode[gindex] = charcode;
226 if(charcode + 1 > font->max_unicode) {
227 font->max_unicode = charcode + 1;
231 charcode = FT_Get_Next_Char(face, charcode, &gindex);
236 printf("ENCODING: %c%c%c%c (%d of %d) max_unicode=%d\n",
237 (face->charmap->encoding >> 24)&255,
238 (face->charmap->encoding >> 16)&255,
239 (face->charmap->encoding >> 8)&255,
240 (face->charmap->encoding >> 0)&255,
241 charmap, face->num_charmaps, font->max_unicode
244 printf("ENCODING: NONE (%d of %d) max_unicode=%d\n",
245 charmap, face->num_charmaps, font->max_unicode
250 /* if we didn't find a single encoding character, try
251 the font's charmaps instead. That usually means that
252 the encoding is no longer unicode.
253 TODO: find a way to convert the encoding to unicode
255 if(font->max_unicode == 0 && charmap < face->num_charmaps-1
256 && face->charmaps[charmap+1]->encoding != 0x41444243 /* adbc, custom */
257 && face->charmaps[charmap+1]->encoding != 0x61726d6e /* armn */
261 FT_Set_Charmap(face, face->charmaps[charmap]);
266 /* TODO: if isunicode is 1, we now need to permutate the character
267 order so that each character is at it's encoding position */
270 font->max_unicode = 65535;
272 font->unicode2glyph = (int*)rfx_calloc(font->max_unicode*sizeof(int));
274 for(t=0;t<font->max_unicode;t++) {
275 int g = FT_Get_Char_Index(face, t);
276 if(!g || g>=face->num_glyphs)
278 font->unicode2glyph[t] = g;
281 printf("u%d ->%d\n", t, g);
284 if(!glyph2unicode[g]) {
285 glyph2unicode[g] = t;
289 font->max_unicode = max_unicode;
291 font->num_glyphs = 0;
294 for(t=0; t < face->num_glyphs; t++) {
295 if(FT_HAS_GLYPH_NAMES(face)) {
297 error = FT_Get_Glyph_Name(face, t, name, 127);
298 if(!error && name[0] && !strstr(name, "notdef")) {
305 for(t=0; t < face->num_glyphs; t++) {
314 font->glyphs[font->num_glyphs].advance = 0;
315 font->glyphs[font->num_glyphs].line = 0;
316 font->glyphs[font->num_glyphs].unicode = glyph2unicode[t];
317 font->glyphs[font->num_glyphs].name = 0;
319 if(FT_HAS_GLYPH_NAMES(face) && (num_names >= face->num_glyphs/10 || num_names > 2)) {
321 error = FT_Get_Glyph_Name(face, t, name, 127);
322 if(!error && name[0] && !strstr(name, "notdef")) {
323 font->glyphs[font->num_glyphs].name = strdup(name);
328 #if 0 // some cantonese pdfs fail to work if this is activated
330 if(has_had_errors && (isunicode && !glyph2unicode[t]) && !hasname && t>=256) {
331 /* some freetype versions crash or corrupt memory if we try to load
332 characters (without unicode index or name) above 256 for some fonts.
333 So skip those characters once the first error occured */
339 error = FT_Load_Glyph(face, t, FT_LOAD_NO_BITMAP);
342 fprintf(stderr, "Warning: glyph %d/%d (unicode %d, name %s) has return code %d\n", t, (int)face->num_glyphs, glyph2unicode[t], name, error);
344 fprintf(stderr, "Warning: glyph %d/%d (unicode %d) has return code %d\n", t, (int)face->num_glyphs, glyph2unicode[t], error);
348 if(!has_had_errors) {
350 if(fontname && *fontname) {
351 fprintf(stderr, "font has been copied to %s.ttf\n", fontname);
352 sprintf(buf, "cp %s %s.ttf", filename, fontname);
354 fprintf(stderr, "font has been copied to badfont%d.ttf\n", errorno);
355 sprintf(buf, "cp %s badfont%d.ttf", filename, errorno);
365 error = FT_Get_Glyph(face->glyph, &glyph);
367 fprintf(stderr, "Couldn't get glyph %d/%d, error:%d\n", t, (int)face->num_glyphs, error);
375 gfxdrawer_target_gfxline(&draw);
377 info.quality = quality;
379 //error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info);
380 error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info);
383 fprintf(stderr, "Couldn't decompose glyph %d\n", t);
384 gfxline_free((gfxline_t*)draw.result(&draw));
385 FT_Done_Glyph(glyph);
388 font->glyphs[font->num_glyphs].advance = glyph->advance.x/65536;
389 font->glyphs[font->num_glyphs].line = (gfxline_t*)draw.result(&draw);
391 l = font->glyphs[font->num_glyphs].line;
393 if(l->type != gfx_moveTo) {
399 gfxline_free(font->glyphs[font->num_glyphs].line);
400 font->glyphs[font->num_glyphs].line = 0;
401 font->glyphs[font->num_glyphs].advance = 0;
403 /* Some PDFs created e.g. by InDesign tend to create
404 fonts with reduced (empty) characters, which still
405 have unicode indices attached to them.
406 Remove that information, in order to not confuse
407 any converter applications.
409 font->glyphs[font->num_glyphs].unicode = 0;
410 if(font->glyphs[font->num_glyphs].name) {
411 free((void*)font->glyphs[font->num_glyphs].name);
412 font->glyphs[font->num_glyphs].name = 0;
414 FT_Done_Glyph(glyph);
420 FT_Done_Glyph(glyph);
421 font->glyphs[font->num_glyphs].unicode = glyph2unicode[t];
424 glyph2glyph[t] = font->num_glyphs;
428 /* notice: if skip_unused is true, font->glyph2unicode, font->glyphnames and font->layout->bounds will
429 have more memory allocated than just font->num_glyphs, but only the first font->numchars
432 for(t=0;t<font->max_unicode;t++) {
433 if(font->unicode2glyph[t]>=0) {
434 font->unicode2glyph[t] = glyph2glyph[font->unicode2glyph[t]];
437 rfx_free(glyph2glyph);
438 rfx_free(glyph2unicode);
441 FT_Done_FreeType(ftlibrary);ftlibrary=0;
443 if(!isunicode && font->num_glyphs>0 && font->max_unicode) {
444 /* if the encoding isn't unicode, remap the font
445 so that the encoding equals the char position, and
446 remove the unicode table */
448 gfxglyph_t*newglyphs = (gfxglyph_t*)rfx_calloc(font->max_unicode*sizeof(gfxglyph_t));
450 for(t=0;t<max_unicode;t++) {
451 int c = font->unicode2glyph[t];
452 if(c>=font->num_glyphs || c<0)
454 newglyphs[t] = cloneGlyph(&font->glyphs[c]);
455 newglyphs[t].unicode = -1;
457 for(t=0;t<font->num_glyphs;t++) {
458 glyph_clear(&font->glyphs[t]);
461 font->glyphs = newglyphs;
462 font->num_glyphs = font->max_unicode;
464 free(font->unicode2glyph);font->unicode2glyph = 0;
465 font->max_unicode = 0;
468 if(font->unicode2glyph) {
471 /* check whether the Unicode indices look o.k.
472 If they don't, disable the unicode lookup by setting
473 the unicode map to -1 everywhere */
474 for(t=0;t<font->num_glyphs;t++) {
475 int c = font->glyphs[t].unicode;
476 gfxline_t* line = font->glyphs[t].line;
477 if(c && c < 32 && (line && line->next && line->next->next)) {
478 // the character maps into the unicode control character range
479 // between 0001-001f. Yet it is not empty. Treat the one
480 // mapping as broken, and look how many of those we find.
485 free(font->unicode2glyph);font->unicode2glyph = 0;
486 font->max_unicode = 0;
487 for(t=0;t<font->num_glyphs;t++) {
488 font->glyphs[t].unicode = -1;
497 gfxfont_t* gfxfont_load(const char*id, const char*filename, unsigned int flags, double quality)
499 fprintf(stderr, "No freetype support compiled in! Not able to load %s\n", filename);
505 void gfxfont_free(gfxfont_t*font)
508 for(t=0;t<font->num_glyphs;t++) {
509 glyph_clear(&font->glyphs[t]);
512 free(font->glyphs);font->glyphs = 0;
514 font->num_glyphs = 0;
515 if(font->unicode2glyph) {
516 free(font->unicode2glyph);font->unicode2glyph = 0;
519 free((void*)font->id);font->id=0;
522 free(font->kerning);font->kerning=0;
528 static inline int invalid_unicode(int u)
530 return (u<32 || (u>=0xe000 && u<0xf900));
532 void gfxfont_fix_unicode(gfxfont_t*font)
536 /* find the current maximum unicode2glyph */
538 for(t=0;t<font->num_glyphs;t++) {
539 int u = font->glyphs[t].unicode;
543 char*used = rfx_calloc(max+1);
545 /* now, remap all duplicates (and invalid characters) and
546 calculate the new maximum */
549 for(t=0;t<font->num_glyphs;t++) {
550 int u = font->glyphs[t].unicode;
552 if(used[u] || invalid_unicode(u)) {
553 u = font->glyphs[t].unicode = 0xe000 + remap_pos++;
562 if(font->unicode2glyph) {
563 free(font->unicode2glyph);
565 font->unicode2glyph = 0;
566 font->max_unicode = 0;
569 void gfxfont_add_unicode2glyph(gfxfont_t*font)
573 for(t=0;t<font->num_glyphs;t++) {
574 int u = font->glyphs[t].unicode;
578 if(!font->unicode2glyph) {
579 /* (re)generate unicode2glyph-to-glyph mapping table by reverse mapping
580 the glyph unicode2glyph's indexes into the mapping table. For collisions,
581 we prefer the smaller unicode2glyph value.*/
582 font->max_unicode = max+1;
583 font->unicode2glyph = malloc(sizeof(font->unicode2glyph[0])*(font->max_unicode));
584 memset(font->unicode2glyph, -1, sizeof(font->unicode2glyph[0])*(font->max_unicode));
586 for(t=0;t<font->num_glyphs;t++) {
587 int u = font->glyphs[t].unicode;
589 assert(font->unicode2glyph[u]<0); // we took care of duplicates, right?
590 assert(u<font->max_unicode);
591 font->unicode2glyph[u] = t;
595 /* add the new glyph indexes (most probably, that's only the remapped values
596 at 0xe000) to the unicode2glyph table. Notice: Unlike glyph2unicode, we don't
597 care about collisions in the unicode2glyph table */
598 int new_max_unicode = max+1;
599 if(font->max_unicode < new_max_unicode) {
600 font->unicode2glyph = rfx_realloc(font->unicode2glyph, sizeof(font->unicode2glyph[0])*(font->max_unicode));
601 memset(font->unicode2glyph+font->max_unicode, -1, sizeof(font->unicode2glyph[0])*(new_max_unicode - font->max_unicode));
603 for(t=0;t<font->num_glyphs;t++) {
604 int u = font->glyphs[t].unicode;
605 if(u>=0 && font->unicode2glyph[u]<0) {
606 font->unicode2glyph[u] = t;
609 font->max_unicode = new_max_unicode;
613 ttf_t* gfxfont_to_ttf(gfxfont_t*font, char eot)
615 ttf_t*ttf = ttf_new();
616 int num_glyphs = font->num_glyphs;
619 char has_nondef_glyph =
620 font->num_glyphs && font->glyphs[0].unicode==-1 &&
621 (!font->glyphs[0].line || !font->glyphs[0].line->next);
623 if(!has_nondef_glyph) {
624 /* insert a new .nondef glyph at the start of the font */
628 ttf->num_glyphs = num_glyphs;
629 ttf->glyphs = rfx_calloc(num_glyphs*sizeof(ttfglyph_t));
631 int max_unicode = font->max_unicode;
633 for(t=0;t<font->num_glyphs;t++) {
634 gfxglyph_t*src = &font->glyphs[t];
635 ttfglyph_t*dest = &ttf->glyphs[t+offset];
636 gfxline_t*line = src->line;
640 if(line->type == gfx_splineTo)
644 dest->num_points = count;
645 dest->points = rfx_calloc(count*sizeof(ttfpoint_t));
649 if(line->type == gfx_splineTo) {
650 dest->points[count].x = line->sx*scale;
651 dest->points[count].y = line->sy*scale;
654 dest->points[count].x = line->x*scale;
655 dest->points[count].y = line->y*scale;
656 dest->points[count].flags |= GLYPH_ON_CURVE;
657 if(line->type == gfx_moveTo) {
658 dest->points[count].flags |= GLYPH_CONTOUR_START;
660 dest->points[count-1].flags |= GLYPH_CONTOUR_END;
666 dest->points[count-1].flags |= GLYPH_CONTOUR_END;
668 /* compute bounding box */
671 dest->xmin = dest->xmax = dest->points[0].x;
672 dest->ymin = dest->ymax = dest->points[0].y;
673 for(s=1;s<count;s++) {
674 if(dest->points[s].x < dest->xmin)
675 dest->xmin = dest->points[s].x;
676 if(dest->points[s].y < dest->ymin)
677 dest->ymin = dest->points[s].y;
678 if(dest->points[s].x > dest->xmax)
679 dest->xmax = dest->points[s].x;
680 if(dest->points[s].y > dest->ymax)
681 dest->ymax = dest->points[s].y;
686 dest->bearing = dest->xmin;
687 /* for windows font rendering, make sure coordinates are always
688 to the right of the origin (and use bearing to shift them "back".)
689 Don't do this for non-windows platforms though because e.g. OS X
693 xshift = -dest->xmin;
694 for(s=0;s<count;s++) {
695 dest->points[s].x += xshift;
697 dest->xmin += xshift;
698 dest->xmax += xshift;
701 dest->advance = src->advance*scale;
703 //dest->xmin=0; //TODO: might be necessary for some font engines?
705 dest->advance = src->advance*scale;
707 int u = font->glyphs[t].unicode;
711 ttf->unicode_size = max_unicode+1;
712 ttf->unicode = rfx_calloc(sizeof(unicode_t)*ttf->unicode_size);
714 if(!font->unicode2glyph) {
715 for(t=0;t<font->num_glyphs;t++) {
716 gfxglyph_t*src = &font->glyphs[t];
717 int u = font->glyphs[t].unicode;
721 msg("<warning> gfxfont_to_ttf: glyph %d has an invalid unicode (%d)", t, u);
723 } else if(ttf->unicode[u]) {
724 msg("<warning> gfxfont_to_ttf: glyph %d has a duplicate unicode (%d)", t, u);
727 if(u<ttf->unicode_size)
728 ttf->unicode[u] = t+offset;
732 for(u=1;u<font->max_unicode;u++) {
733 int g = font->unicode2glyph[u];
735 msg("<warning> gfxfont_to_ttf: Font contains an invalid unicode (%d)", u);
738 if(g>=0 && g<font->num_glyphs && !ttf->unicode[u]) {
739 ttf->unicode[u] = g+offset;
744 ttf->ascent = font->ascent;
745 ttf->descent = -font->descent;
748 ttf->full_name = strdup(font->id);
749 ttf->family_name = strdup(font->id);
750 ttf->subfamily_name = strdup(font->id);
751 ttf->postscript_name = strdup(font->id);
752 ttf->version_string = strdup("Version 1.0");
753 ttf->font_uid = strdup(font->id);
755 ttf_create_truetype_tables(ttf);
759 void gfxfont_save(gfxfont_t*font, const char*filename)
761 ttf_t*ttf = gfxfont_to_ttf(font, 0);
762 ttf_save(ttf, filename);
766 void gfxfont_save_eot(gfxfont_t*font, const char*filename)
768 ttf_t*ttf = gfxfont_to_ttf(font, 1);
769 ttf_save_eot(ttf, filename);