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 */
25 #include "../config.h"
26 #include "gfxdevice.h"
33 static int loadfont_scale = 64;
34 static int full_unicode = 1;
38 #ifdef HAVE_FT2BUILD_H
40 #include FT_FREETYPE_H
43 #include FT_SFNT_NAMES_H
44 #include FT_TRUETYPE_IDS_H
47 #include <freetype/freetype.h>
48 #include <freetype/ftglyph.h>
49 #include <freetype/ftsizes.h>
50 #include <freetype/ftsnames.h>
51 #include <freetype/ttnameid.h>
52 #include <freetype/ftoutln.h>
55 /* Setting subpixels to 64 also means that the "point size" of the
56 font outlines will be 64. So the font, when rendered at original
57 size (i.e., the swf fontsize is 1024) will have the same size as
58 if it was rendered at 64pt */
61 #define FT_SUBPIXELS 64
63 typedef struct _gfxdrawinfo_t {
68 static int ft_move_to(const FT_Vector* _to, void* user)
70 gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
71 gfxdrawer_t* draw = info->draw;
72 double x = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
73 double y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
74 draw->moveTo(draw, x,y);
77 static int ft_line_to(const FT_Vector* _to, void* user)
79 gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
80 gfxdrawer_t* draw = info->draw;
81 double x = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
82 double y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
83 draw->lineTo(draw, x,y);
86 static int ft_cubic_to(const FT_Vector* _c1, const FT_Vector* _c2, const FT_Vector* _to, void* user)
88 gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
89 gfxdrawer_t* draw = info->draw;
90 double tox = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
91 double toy = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
92 double c1x = _c1->x*FT_SCALE/(float)FT_SUBPIXELS;
93 double c1y = -_c1->y*FT_SCALE/(float)FT_SUBPIXELS;
94 double c2x = _c2->x*FT_SCALE/(float)FT_SUBPIXELS;
95 double c2y = -_c2->y*FT_SCALE/(float)FT_SUBPIXELS;
96 gfxdraw_cubicTo(draw, c1x, c1y, c2x, c2y, tox, toy, info->quality);
99 static int ft_conic_to(const FT_Vector* _c, const FT_Vector* _to, void* user)
101 gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
102 gfxdrawer_t* draw = info->draw;
103 double tox = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
104 double toy = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
105 double cx = _c->x*FT_SCALE/(float)FT_SUBPIXELS;
106 double cy = -_c->y*FT_SCALE/(float)FT_SUBPIXELS;
107 gfxdraw_conicTo(draw, cx,cy, tox,toy, info->quality);
110 static FT_Outline_Funcs outline_functions =
119 static FT_Library ftlibrary = 0;
121 static gfxglyph_t cloneGlyph(gfxglyph_t*src)
124 memset(&dest, 0, sizeof(dest));
126 dest.name = strdup(src->name);
127 dest.advance = src->advance;
128 dest.unicode = src->unicode;
129 dest.line = gfxline_clone(src->line);
133 static void glyph_clear(gfxglyph_t*g)
137 free((void*)g->name); g->name = 0;
139 gfxline_free(g->line);g->line = 0;
142 static int errorno = 0;
146 gfxfont_t* gfxfont_load(const char*id, const char*filename, unsigned int flags, double quality)
150 const char* fontname = 0;
156 int*glyph2unicode = 0;
160 int has_had_errors = 0;
164 if(FT_Init_FreeType(&ftlibrary)) {
165 fprintf(stderr, "Couldn't init freetype library!\n");
169 error = FT_New_Face(ftlibrary, filename, 0, &face);
170 FT_Set_Pixel_Sizes (face, 16*loadfont_scale, 16*loadfont_scale);
172 printf("gfxfont_load(%s, %s, %f)\n", id, filename, quality);
176 fprintf(stderr, "Couldn't load file %s- not a TTF file? (error=%02x)\n", filename, error);
179 if(face->num_glyphs <= 0) {
180 fprintf(stderr, "File %s contains %d glyphs\n", filename, (int)face->num_glyphs);
184 font = (gfxfont_t*)rfx_calloc(sizeof(gfxfont_t));
185 //font->style = ((face->style_flags&FT_STYLE_FLAG_ITALIC)?FONT_STYLE_ITALIC:0) |((face->style_flags&FT_STYLE_FLAG_BOLD)?FONT_STYLE_BOLD:0);
186 //font->ascent = abs(face->ascender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMin;
187 //font->descent = abs(face->descender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMax;
188 //font->leading = font->layout->ascent + font->layout->descent;
189 //font->encoding = FONT_ENCODING_UNICODE;
190 font->max_unicode = 0;
191 font->id = strdup(id);
193 font->glyphs = (gfxglyph_t*)rfx_calloc(face->num_glyphs*sizeof(gfxglyph_t));
194 glyph2unicode = (int*)rfx_calloc(face->num_glyphs*sizeof(int));
195 glyph2glyph = (int*)rfx_calloc(face->num_glyphs*sizeof(int));
197 if(FT_HAS_GLYPH_NAMES(face)) {
198 //font->glyphnames = rfx_calloc(face->num_glyphs*sizeof(char*));
201 fontname = FT_Get_Postscript_Name(face);
204 for(t=0;t<face->num_charmaps;t++) {
205 printf("possible encoding: %c%c%c%c (%d of %d)\n",
206 (face->charmaps[t]->encoding >> 24)&255,
207 (face->charmaps[t]->encoding >> 16)&255,
208 (face->charmaps[t]->encoding >> 8)&255,
209 (face->charmaps[t]->encoding >> 0)&255,
210 t+1, face->num_charmaps
217 charcode = FT_Get_First_Char(face, &gindex);
221 if(gindex >= 0 && gindex<face->num_glyphs) {
222 if(!glyph2unicode[gindex]) {
223 glyph2unicode[gindex] = charcode;
224 if(charcode + 1 > font->max_unicode) {
225 font->max_unicode = charcode + 1;
229 charcode = FT_Get_Next_Char(face, charcode, &gindex);
234 printf("ENCODING: %c%c%c%c (%d of %d) max_unicode=%d\n",
235 (face->charmap->encoding >> 24)&255,
236 (face->charmap->encoding >> 16)&255,
237 (face->charmap->encoding >> 8)&255,
238 (face->charmap->encoding >> 0)&255,
239 charmap, face->num_charmaps, font->max_unicode
242 printf("ENCODING: NONE (%d of %d) max_unicode=%d\n",
243 charmap, face->num_charmaps, font->max_unicode
248 /* if we didn't find a single encoding character, try
249 the font's charmaps instead. That usually means that
250 the encoding is no longer unicode.
251 TODO: find a way to convert the encoding to unicode
253 if(font->max_unicode == 0 && charmap < face->num_charmaps-1
254 && face->charmaps[charmap+1]->encoding != 0x41444243 /* adbc, custom */
255 && face->charmaps[charmap+1]->encoding != 0x61726d6e /* armn */
259 FT_Set_Charmap(face, face->charmaps[charmap]);
264 /* TODO: if isunicode is 1, we now need to permutate the character
265 order so that each character is at it's encoding position */
268 font->max_unicode = 65535;
270 font->unicode2glyph = (int*)rfx_calloc(font->max_unicode*sizeof(int));
272 for(t=0;t<font->max_unicode;t++) {
273 int g = FT_Get_Char_Index(face, t);
274 if(!g || g>=face->num_glyphs)
276 font->unicode2glyph[t] = g;
279 printf("u%d ->%d\n", t, g);
282 if(!glyph2unicode[g]) {
283 glyph2unicode[g] = t;
287 font->max_unicode = max_unicode;
289 font->num_glyphs = 0;
292 for(t=0; t < face->num_glyphs; t++) {
293 if(FT_HAS_GLYPH_NAMES(face)) {
295 error = FT_Get_Glyph_Name(face, t, name, 127);
296 if(!error && name[0] && !strstr(name, "notdef")) {
303 for(t=0; t < face->num_glyphs; t++) {
312 font->glyphs[font->num_glyphs].advance = 0;
313 font->glyphs[font->num_glyphs].line = 0;
314 font->glyphs[font->num_glyphs].unicode = glyph2unicode[t];
315 font->glyphs[font->num_glyphs].name = 0;
317 if(FT_HAS_GLYPH_NAMES(face) && (num_names >= face->num_glyphs/10 || num_names > 2)) {
319 error = FT_Get_Glyph_Name(face, t, name, 127);
320 if(!error && name[0] && !strstr(name, "notdef")) {
321 font->glyphs[font->num_glyphs].name = strdup(name);
326 #if 0 // some cantonese pdfs fail to work if this is activated
328 if(has_had_errors && (isunicode && !glyph2unicode[t]) && !hasname && t>=256) {
329 /* some freetype versions crash or corrupt memory if we try to load
330 characters (without unicode index or name) above 256 for some fonts.
331 So skip those characters once the first error occured */
337 error = FT_Load_Glyph(face, t, FT_LOAD_NO_BITMAP);
340 fprintf(stderr, "Warning: glyph %d/%d (unicode %d, name %s) has return code %d\n", t, (int)face->num_glyphs, glyph2unicode[t], name, error);
342 fprintf(stderr, "Warning: glyph %d/%d (unicode %d) has return code %d\n", t, (int)face->num_glyphs, glyph2unicode[t], error);
346 if(!has_had_errors) {
348 if(fontname && *fontname) {
349 fprintf(stderr, "font has been copied to %s.ttf\n", fontname);
350 sprintf(buf, "cp %s %s.ttf", filename, fontname);
352 fprintf(stderr, "font has been copied to badfont%d.ttf\n", errorno);
353 sprintf(buf, "cp %s badfont%d.ttf", filename, errorno);
363 error = FT_Get_Glyph(face->glyph, &glyph);
365 fprintf(stderr, "Couldn't get glyph %d/%d, error:%d\n", t, (int)face->num_glyphs, error);
373 gfxdrawer_target_gfxline(&draw);
375 info.quality = quality;
377 //error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info);
378 error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info);
381 fprintf(stderr, "Couldn't decompose glyph %d\n", t);
382 gfxline_free((gfxline_t*)draw.result(&draw));
383 FT_Done_Glyph(glyph);
386 font->glyphs[font->num_glyphs].advance = glyph->advance.x/65536;
387 font->glyphs[font->num_glyphs].line = (gfxline_t*)draw.result(&draw);
389 l = font->glyphs[font->num_glyphs].line;
391 if(l->type != gfx_moveTo) {
397 gfxline_free(font->glyphs[font->num_glyphs].line);
398 font->glyphs[font->num_glyphs].line = 0;
399 font->glyphs[font->num_glyphs].advance = 0;
401 /* Some PDFs created e.g. by InDesign tend to create
402 fonts with reduced (empty) characters, which still
403 have unicode indices attached to them.
404 Remove that information, in order to not confuse
405 any converter applications.
407 font->glyphs[font->num_glyphs].unicode = 0;
408 if(font->glyphs[font->num_glyphs].name) {
409 free((void*)font->glyphs[font->num_glyphs].name);
410 font->glyphs[font->num_glyphs].name = 0;
412 FT_Done_Glyph(glyph);
418 FT_Done_Glyph(glyph);
419 font->glyphs[font->num_glyphs].unicode = glyph2unicode[t];
422 glyph2glyph[t] = font->num_glyphs;
426 /* notice: if skip_unused is true, font->glyph2unicode, font->glyphnames and font->layout->bounds will
427 have more memory allocated than just font->num_glyphs, but only the first font->numchars
430 for(t=0;t<font->max_unicode;t++) {
431 if(font->unicode2glyph[t]>=0) {
432 font->unicode2glyph[t] = glyph2glyph[font->unicode2glyph[t]];
435 rfx_free(glyph2glyph);
436 rfx_free(glyph2unicode);
439 FT_Done_FreeType(ftlibrary);ftlibrary=0;
441 if(!isunicode && font->num_glyphs>0 && font->max_unicode) {
442 /* if the encoding isn't unicode, remap the font
443 so that the encoding equals the char position, and
444 remove the unicode table */
446 gfxglyph_t*newglyphs = (gfxglyph_t*)rfx_calloc(font->max_unicode*sizeof(gfxglyph_t));
448 for(t=0;t<max_unicode;t++) {
449 int c = font->unicode2glyph[t];
450 if(c>=font->num_glyphs || c<0)
452 newglyphs[t] = cloneGlyph(&font->glyphs[c]);
453 newglyphs[t].unicode = -1;
455 for(t=0;t<font->num_glyphs;t++) {
456 glyph_clear(&font->glyphs[t]);
459 font->glyphs = newglyphs;
460 font->num_glyphs = font->max_unicode;
462 free(font->unicode2glyph);font->unicode2glyph = 0;
463 font->max_unicode = 0;
466 if(font->unicode2glyph) {
469 /* check whether the Unicode indices look o.k.
470 If they don't, disable the unicode lookup by setting
471 the unicode map to -1 everywhere */
472 for(t=0;t<font->num_glyphs;t++) {
473 int c = font->glyphs[t].unicode;
474 gfxline_t* line = font->glyphs[t].line;
475 if(c && c < 32 && (line && line->next && line->next->next)) {
476 // the character maps into the unicode control character range
477 // between 0001-001f. Yet it is not empty. Treat the one
478 // mapping as broken, and look how many of those we find.
483 free(font->unicode2glyph);font->unicode2glyph = 0;
484 font->max_unicode = 0;
485 for(t=0;t<font->num_glyphs;t++) {
486 font->glyphs[t].unicode = -1;
495 gfxfont_t* gfxfont_load(char*id, char*filename, unsigned int flags, double quality)
497 fprintf(stderr, "No freetype support compiled in! Not able to load %s\n", filename);
503 void gfxfont_free(gfxfont_t*font)
506 for(t=0;t<font->num_glyphs;t++) {
507 glyph_clear(&font->glyphs[t]);
510 free(font->glyphs);font->glyphs = 0;
512 font->num_glyphs = 0;
513 if(font->unicode2glyph) {
514 free(font->unicode2glyph);font->unicode2glyph = 0;
517 free((void*)font->id);font->id=0;
520 free(font->kerning);font->kerning=0;
526 static inline int invalid_unicode(int u)
528 return (u<32 || (u>=0xe000 && u<0xf900));
530 void gfxfont_fix_unicode(gfxfont_t*font)
534 /* find the current maximum unicode2glyph */
536 for(t=0;t<font->num_glyphs;t++) {
537 int u = font->glyphs[t].unicode;
541 char*used = rfx_calloc(max+1);
543 /* now, remap all duplicates (and invalid characters) and
544 calculate the new maximum */
547 for(t=0;t<font->num_glyphs;t++) {
548 int u = font->glyphs[t].unicode;
550 if(used[u] || invalid_unicode(u)) {
551 u = font->glyphs[t].unicode = 0xe000 + remap_pos++;
560 if(font->unicode2glyph) {
561 free(font->unicode2glyph);
563 font->unicode2glyph = 0;
564 font->max_unicode = 0;
567 void gfxfont_add_unicode2glyph(gfxfont_t*font)
571 for(t=0;t<font->num_glyphs;t++) {
572 int u = font->glyphs[t].unicode;
576 if(!font->unicode2glyph) {
577 /* (re)generate unicode2glyph-to-glyph mapping table by reverse mapping
578 the glyph unicode2glyph's indexes into the mapping table. For collisions,
579 we prefer the smaller unicode2glyph value.*/
580 font->max_unicode = max+1;
581 font->unicode2glyph = malloc(sizeof(font->unicode2glyph[0])*(font->max_unicode));
582 memset(font->unicode2glyph, -1, sizeof(font->unicode2glyph[0])*(font->max_unicode));
584 for(t=0;t<font->num_glyphs;t++) {
585 int u = font->glyphs[t].unicode;
587 assert(font->unicode2glyph[u]<0); // we took care of duplicates, right?
588 assert(u<font->max_unicode);
589 font->unicode2glyph[u] = t;
593 /* add the new glyph indexes (most probably, that's only the remapped values
594 at 0xe000) to the unicode2glyph table. Notice: Unlike glyph2unicode, we don't
595 care about collisions in the unicode2glyph table */
596 int new_max_unicode = max+1;
597 if(font->max_unicode < new_max_unicode) {
598 font->unicode2glyph = rfx_realloc(font->unicode2glyph, sizeof(font->unicode2glyph[0])*(font->max_unicode));
599 memset(font->unicode2glyph+font->max_unicode, -1, sizeof(font->unicode2glyph[0])*(new_max_unicode - font->max_unicode));
601 for(t=0;t<font->num_glyphs;t++) {
602 int u = font->glyphs[t].unicode;
603 if(u>=0 && font->unicode2glyph[u]<0) {
604 font->unicode2glyph[u] = t;
607 font->max_unicode = new_max_unicode;
611 ttf_t* gfxfont_to_ttf(gfxfont_t*font, char eot)
613 ttf_t*ttf = ttf_new();
614 int num_glyphs = font->num_glyphs;
617 char has_nondef_glyph =
618 font->num_glyphs && font->glyphs[0].unicode==-1 &&
619 (!font->glyphs[0].line || !font->glyphs[0].line->next);
621 if(!has_nondef_glyph) {
622 /* insert a new .nondef glyph at the start of the font */
626 ttf->num_glyphs = num_glyphs;
627 ttf->glyphs = rfx_calloc(num_glyphs*sizeof(ttfglyph_t));
629 int max_unicode = font->max_unicode;
631 for(t=0;t<font->num_glyphs;t++) {
632 gfxglyph_t*src = &font->glyphs[t];
633 ttfglyph_t*dest = &ttf->glyphs[t+offset];
634 gfxline_t*line = src->line;
638 if(line->type == gfx_splineTo)
642 dest->num_points = count;
643 dest->points = rfx_calloc(count*sizeof(ttfpoint_t));
647 if(line->type == gfx_splineTo) {
648 dest->points[count].x = line->sx*scale;
649 dest->points[count].y = line->sy*scale;
652 dest->points[count].x = line->x*scale;
653 dest->points[count].y = line->y*scale;
654 dest->points[count].flags |= GLYPH_ON_CURVE;
655 if(line->type == gfx_moveTo) {
656 dest->points[count].flags |= GLYPH_CONTOUR_START;
658 dest->points[count-1].flags |= GLYPH_CONTOUR_END;
664 dest->points[count-1].flags |= GLYPH_CONTOUR_END;
666 /* compute bounding box */
669 dest->xmin = dest->xmax = dest->points[0].x;
670 dest->ymin = dest->ymax = dest->points[0].y;
671 for(s=1;s<count;s++) {
672 if(dest->points[s].x < dest->xmin)
673 dest->xmin = dest->points[s].x;
674 if(dest->points[s].y < dest->ymin)
675 dest->ymin = dest->points[s].y;
676 if(dest->points[s].x > dest->xmax)
677 dest->xmax = dest->points[s].x;
678 if(dest->points[s].y > dest->ymax)
679 dest->ymax = dest->points[s].y;
684 dest->bearing = dest->xmin;
685 /* for windows font rendering, make sure coordinates are always
686 to the right of the origin (and use bearing to shift them "back".)
687 Don't do this for non-windows platforms though because e.g. OS X
691 xshift = -dest->xmin;
692 for(s=0;s<count;s++) {
693 dest->points[s].x += xshift;
695 dest->xmin += xshift;
696 dest->xmax += xshift;
699 dest->advance = src->advance*scale;
701 //dest->xmin=0; //TODO: might be necessary for some font engines?
703 dest->advance = src->advance*scale;
705 int u = font->glyphs[t].unicode;
709 ttf->unicode_size = max_unicode+1;
710 ttf->unicode = rfx_calloc(sizeof(unicode_t)*ttf->unicode_size);
712 if(!font->unicode2glyph) {
713 for(t=0;t<font->num_glyphs;t++) {
714 gfxglyph_t*src = &font->glyphs[t];
715 int u = font->glyphs[t].unicode;
719 msg("<warning> gfxfont_to_ttf: glyph %d has an invalid unicode (%d)", t, u);
721 } else if(ttf->unicode[u]) {
722 msg("<warning> gfxfont_to_ttf: glyph %d has a duplicate unicode (%d)", t, u);
725 if(u<ttf->unicode_size)
726 ttf->unicode[u] = t+offset;
730 for(u=1;u<font->max_unicode;u++) {
731 int g = font->unicode2glyph[u];
733 msg("<warning> gfxfont_to_ttf: Font contains an invalid unicode (%d)", u);
736 if(g>=0 && g<font->num_glyphs && !ttf->unicode[u]) {
737 ttf->unicode[u] = g+offset;
742 ttf->ascent = font->ascent;
743 ttf->descent = -font->descent;
746 ttf->full_name = strdup(font->id);
747 ttf->family_name = strdup(font->id);
748 ttf->subfamily_name = strdup(font->id);
749 ttf->postscript_name = strdup(font->id);
750 ttf->version_string = strdup("Version 1.0");
751 ttf->font_uid = strdup(font->id);
753 ttf_create_truetype_tables(ttf);
757 void gfxfont_save(gfxfont_t*font, const char*filename)
759 ttf_t*ttf = gfxfont_to_ttf(font, 0);
760 ttf_save(ttf, filename);
764 void gfxfont_save_eot(gfxfont_t*font, const char*filename)
766 ttf_t*ttf = gfxfont_to_ttf(font, 1);
767 ttf_save_eot(ttf, filename);