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"
32 static int loadfont_scale = 64;
33 static int full_unicode = 1;
37 #ifdef HAVE_FT2BUILD_H
39 #include FT_FREETYPE_H
42 #include FT_SFNT_NAMES_H
43 #include FT_TRUETYPE_IDS_H
46 #include <freetype/freetype.h>
47 #include <freetype/ftglyph.h>
48 #include <freetype/ftsizes.h>
49 #include <freetype/ftsnames.h>
50 #include <freetype/ttnameid.h>
51 #include <freetype/ftoutln.h>
54 /* Setting subpixels to 64 also means that the "point size" of the
55 font outlines will be 64. So the font, when rendered at original
56 size (i.e., the swf fontsize is 1024) will have the same size as
57 if it was rendered at 64pt */
60 #define FT_SUBPIXELS 64
62 typedef struct _gfxdrawinfo_t {
67 static int ft_move_to(const FT_Vector* _to, void* user)
69 gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
70 gfxdrawer_t* draw = info->draw;
71 double x = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
72 double y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
73 draw->moveTo(draw, x,y);
76 static int ft_line_to(const FT_Vector* _to, void* user)
78 gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
79 gfxdrawer_t* draw = info->draw;
80 double x = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
81 double y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
82 draw->lineTo(draw, x,y);
85 static int ft_cubic_to(const FT_Vector* _c1, const FT_Vector* _c2, const FT_Vector* _to, void* user)
87 gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
88 gfxdrawer_t* draw = info->draw;
89 double tox = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
90 double toy = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
91 double c1x = _c1->x*FT_SCALE/(float)FT_SUBPIXELS;
92 double c1y = -_c1->y*FT_SCALE/(float)FT_SUBPIXELS;
93 double c2x = _c2->x*FT_SCALE/(float)FT_SUBPIXELS;
94 double c2y = -_c2->y*FT_SCALE/(float)FT_SUBPIXELS;
95 gfxdraw_cubicTo(draw, c1x, c1y, c2x, c2y, tox, toy, info->quality);
98 static int ft_conic_to(const FT_Vector* _c, const FT_Vector* _to, void* user)
100 gfxdrawinfo_t* info = (gfxdrawinfo_t*)user;
101 gfxdrawer_t* draw = info->draw;
102 double tox = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
103 double toy = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
104 double cx = _c->x*FT_SCALE/(float)FT_SUBPIXELS;
105 double cy = -_c->y*FT_SCALE/(float)FT_SUBPIXELS;
106 gfxdraw_conicTo(draw, cx,cy, tox,toy, info->quality);
109 static FT_Outline_Funcs outline_functions =
118 static FT_Library ftlibrary = 0;
120 static gfxglyph_t cloneGlyph(gfxglyph_t*src)
123 memset(&dest, 0, sizeof(dest));
125 dest.name = strdup(src->name);
126 dest.advance = src->advance;
127 dest.unicode = src->unicode;
128 dest.line = gfxline_clone(src->line);
132 static void glyph_clear(gfxglyph_t*g)
136 free((void*)g->name); g->name = 0;
138 gfxline_free(g->line);g->line = 0;
141 static int errorno = 0;
145 gfxfont_t* gfxfont_load(char*id, char*filename, unsigned int flags, double quality)
149 const char* fontname = 0;
155 int*glyph2unicode = 0;
159 int has_had_errors = 0;
163 if(FT_Init_FreeType(&ftlibrary)) {
164 fprintf(stderr, "Couldn't init freetype library!\n");
168 error = FT_New_Face(ftlibrary, filename, 0, &face);
169 FT_Set_Pixel_Sizes (face, 16*loadfont_scale, 16*loadfont_scale);
171 printf("gfxfont_load(%s, %s, %f)\n", id, filename, quality);
175 fprintf(stderr, "Couldn't load file %s- not a TTF file? (error=%02x)\n", filename, error);
178 if(face->num_glyphs <= 0) {
179 fprintf(stderr, "File %s contains %d glyphs\n", filename, (int)face->num_glyphs);
183 font = (gfxfont_t*)rfx_calloc(sizeof(gfxfont_t));
184 //font->style = ((face->style_flags&FT_STYLE_FLAG_ITALIC)?FONT_STYLE_ITALIC:0) |((face->style_flags&FT_STYLE_FLAG_BOLD)?FONT_STYLE_BOLD:0);
185 //font->ascent = abs(face->ascender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMin;
186 //font->descent = abs(face->descender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMax;
187 //font->leading = font->layout->ascent + font->layout->descent;
188 //font->encoding = FONT_ENCODING_UNICODE;
189 font->max_unicode = 0;
190 font->id = strdup(id);
192 font->glyphs = (gfxglyph_t*)rfx_calloc(face->num_glyphs*sizeof(gfxglyph_t));
193 glyph2unicode = (int*)rfx_calloc(face->num_glyphs*sizeof(int));
194 glyph2glyph = (int*)rfx_calloc(face->num_glyphs*sizeof(int));
196 if(FT_HAS_GLYPH_NAMES(face)) {
197 //font->glyphnames = rfx_calloc(face->num_glyphs*sizeof(char*));
200 fontname = FT_Get_Postscript_Name(face);
203 for(t=0;t<face->num_charmaps;t++) {
204 printf("possible encoding: %c%c%c%c (%d of %d)\n",
205 (face->charmaps[t]->encoding >> 24)&255,
206 (face->charmaps[t]->encoding >> 16)&255,
207 (face->charmaps[t]->encoding >> 8)&255,
208 (face->charmaps[t]->encoding >> 0)&255,
209 t+1, face->num_charmaps
216 charcode = FT_Get_First_Char(face, &gindex);
220 if(gindex >= 0 && gindex<face->num_glyphs) {
221 if(!glyph2unicode[gindex]) {
222 glyph2unicode[gindex] = charcode;
223 if(charcode + 1 > font->max_unicode) {
224 font->max_unicode = charcode + 1;
228 charcode = FT_Get_Next_Char(face, charcode, &gindex);
233 printf("ENCODING: %c%c%c%c (%d of %d) max_unicode=%d\n",
234 (face->charmap->encoding >> 24)&255,
235 (face->charmap->encoding >> 16)&255,
236 (face->charmap->encoding >> 8)&255,
237 (face->charmap->encoding >> 0)&255,
238 charmap, face->num_charmaps, font->max_unicode
241 printf("ENCODING: NONE (%d of %d) max_unicode=%d\n",
242 charmap, face->num_charmaps, font->max_unicode
247 /* if we didn't find a single encoding character, try
248 the font's charmaps instead. That usually means that
249 the encoding is no longer unicode.
250 TODO: find a way to convert the encoding to unicode
252 if(font->max_unicode == 0 && charmap < face->num_charmaps-1
253 && face->charmaps[charmap+1]->encoding != 0x41444243 /* adbc, custom */
254 && face->charmaps[charmap+1]->encoding != 0x61726d6e /* armn */
258 FT_Set_Charmap(face, face->charmaps[charmap]);
263 /* TODO: if isunicode is 1, we now need to permutate the character
264 order so that each character is at it's encoding position */
267 font->max_unicode = 65535;
269 font->unicode2glyph = (int*)rfx_calloc(font->max_unicode*sizeof(int));
271 for(t=0;t<font->max_unicode;t++) {
272 int g = FT_Get_Char_Index(face, t);
273 if(!g || g>=face->num_glyphs)
275 font->unicode2glyph[t] = g;
278 printf("u%d ->%d\n", t, g);
281 if(!glyph2unicode[g]) {
282 glyph2unicode[g] = t;
286 font->max_unicode = max_unicode;
288 font->num_glyphs = 0;
291 for(t=0; t < face->num_glyphs; t++) {
292 if(FT_HAS_GLYPH_NAMES(face)) {
294 error = FT_Get_Glyph_Name(face, t, name, 127);
295 if(!error && name[0] && !strstr(name, "notdef")) {
302 for(t=0; t < face->num_glyphs; t++) {
311 font->glyphs[font->num_glyphs].advance = 0;
312 font->glyphs[font->num_glyphs].line = 0;
313 font->glyphs[font->num_glyphs].unicode = glyph2unicode[t];
314 font->glyphs[font->num_glyphs].name = 0;
316 if(FT_HAS_GLYPH_NAMES(face) && (num_names >= face->num_glyphs/10 || num_names > 2)) {
318 error = FT_Get_Glyph_Name(face, t, name, 127);
319 if(!error && name[0] && !strstr(name, "notdef")) {
320 font->glyphs[font->num_glyphs].name = strdup(name);
325 #if 0 // some cantonese pdfs fail to work if this is activated
327 if(has_had_errors && (isunicode && !glyph2unicode[t]) && !hasname && t>=256) {
328 /* some freetype versions crash or corrupt memory if we try to load
329 characters (without unicode index or name) above 256 for some fonts.
330 So skip those characters once the first error occured */
336 error = FT_Load_Glyph(face, t, FT_LOAD_NO_BITMAP);
339 fprintf(stderr, "Warning: glyph %d/%d (unicode %d, name %s) has return code %d\n", t, (int)face->num_glyphs, glyph2unicode[t], name, error);
341 fprintf(stderr, "Warning: glyph %d/%d (unicode %d) has return code %d\n", t, (int)face->num_glyphs, glyph2unicode[t], error);
345 if(!has_had_errors) {
347 if(fontname && *fontname) {
348 fprintf(stderr, "font has been copied to %s.ttf\n", fontname);
349 sprintf(buf, "cp %s %s.ttf", filename, fontname);
351 fprintf(stderr, "font has been copied to badfont%d.ttf\n", errorno);
352 sprintf(buf, "cp %s badfont%d.ttf", filename, errorno);
362 error = FT_Get_Glyph(face->glyph, &glyph);
364 fprintf(stderr, "Couldn't get glyph %d/%d, error:%d\n", t, (int)face->num_glyphs, error);
372 gfxdrawer_target_gfxline(&draw);
374 info.quality = quality;
376 //error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info);
377 error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &info);
380 fprintf(stderr, "Couldn't decompose glyph %d\n", t);
381 gfxline_free((gfxline_t*)draw.result(&draw));
382 FT_Done_Glyph(glyph);
385 font->glyphs[font->num_glyphs].advance = glyph->advance.x/65536;
386 font->glyphs[font->num_glyphs].line = (gfxline_t*)draw.result(&draw);
388 l = font->glyphs[font->num_glyphs].line;
390 if(l->type != gfx_moveTo) {
396 gfxline_free(font->glyphs[font->num_glyphs].line);
397 font->glyphs[font->num_glyphs].line = 0;
398 font->glyphs[font->num_glyphs].advance = 0;
400 /* Some PDFs created e.g. by InDesign tend to create
401 fonts with reduced (empty) characters, which still
402 have unicode indices attached to them.
403 Remove that information, in order to not confuse
404 any converter applications.
406 font->glyphs[font->num_glyphs].unicode = 0;
407 if(font->glyphs[font->num_glyphs].name) {
408 free((void*)font->glyphs[font->num_glyphs].name);
409 font->glyphs[font->num_glyphs].name = 0;
411 FT_Done_Glyph(glyph);
417 FT_Done_Glyph(glyph);
418 font->glyphs[font->num_glyphs].unicode = glyph2unicode[t];
421 glyph2glyph[t] = font->num_glyphs;
425 /* notice: if skip_unused is true, font->glyph2unicode, font->glyphnames and font->layout->bounds will
426 have more memory allocated than just font->num_glyphs, but only the first font->numchars
429 for(t=0;t<font->max_unicode;t++) {
430 if(font->unicode2glyph[t]>=0) {
431 font->unicode2glyph[t] = glyph2glyph[font->unicode2glyph[t]];
434 rfx_free(glyph2glyph);
435 rfx_free(glyph2unicode);
438 FT_Done_FreeType(ftlibrary);ftlibrary=0;
440 if(!isunicode && font->num_glyphs>0 && font->max_unicode) {
441 /* if the encoding isn't unicode, remap the font
442 so that the encoding equals the char position, and
443 remove the unicode table */
445 gfxglyph_t*newglyphs = (gfxglyph_t*)rfx_calloc(font->max_unicode*sizeof(gfxglyph_t));
447 for(t=0;t<max_unicode;t++) {
448 int c = font->unicode2glyph[t];
449 if(c>=font->num_glyphs || c<0)
451 newglyphs[t] = cloneGlyph(&font->glyphs[c]);
452 newglyphs[t].unicode = -1;
454 for(t=0;t<font->num_glyphs;t++) {
455 glyph_clear(&font->glyphs[t]);
458 font->glyphs = newglyphs;
459 font->num_glyphs = font->max_unicode;
461 free(font->unicode2glyph);font->unicode2glyph = 0;
462 font->max_unicode = 0;
465 if(font->unicode2glyph) {
468 /* check whether the Unicode indices look o.k.
469 If they don't, disable the unicode lookup by setting
470 the unicode map to -1 everywhere */
471 for(t=0;t<font->num_glyphs;t++) {
472 int c = font->glyphs[t].unicode;
473 gfxline_t* line = font->glyphs[t].line;
474 if(c && c < 32 && (line && line->next && line->next->next)) {
475 // the character maps into the unicode control character range
476 // between 0001-001f. Yet it is not empty. Treat the one
477 // mapping as broken, and look how many of those we find.
482 free(font->unicode2glyph);font->unicode2glyph = 0;
483 font->max_unicode = 0;
484 for(t=0;t<font->num_glyphs;t++) {
485 font->glyphs[t].unicode = -1;
494 gfxfont_t* gfxfont_load(char*id, char*filename, unsigned int flags, double quality)
496 fprintf(stderr, "No freetype support compiled in! Not able to load %s\n", filename);
502 void gfxfont_free(gfxfont_t*font)
505 for(t=0;t<font->num_glyphs;t++) {
506 glyph_clear(&font->glyphs[t]);
509 free(font->glyphs);font->glyphs = 0;
511 font->num_glyphs = 0;
512 if(font->unicode2glyph) {
513 free(font->unicode2glyph);font->unicode2glyph = 0;
516 free((void*)font->id);font->id=0;
519 free(font->kerning);font->kerning=0;
525 static inline int invalid_unicode(int u)
527 return (u<32 || (u>=0xe000 && u<0xf900));
529 void gfxfont_fix_unicode(gfxfont_t*font)
533 /* find the current maximum unicode2glyph */
535 for(t=0;t<font->num_glyphs;t++) {
536 int u = font->glyphs[t].unicode;
540 char*used = rfx_calloc(max+1);
542 /* now, remap all duplicates (and invalid characters) and
543 calculate the new maximum */
546 for(t=0;t<font->num_glyphs;t++) {
547 int u = font->glyphs[t].unicode;
549 if(used[u] || invalid_unicode(u)) {
550 u = font->glyphs[t].unicode = 0xe000 + remap_pos++;
560 if(!font->unicode2glyph) {
561 /* (re)generate unicode2glyph-to-glyph mapping table by reverse mapping
562 the glyph unicode2glyph's indexes into the mapping table. For collisions,
563 we prefer the smaller unicode2glyph value.*/
564 font->max_unicode = max+1;
565 font->unicode2glyph = malloc(sizeof(font->unicode2glyph[0])*(font->max_unicode));
566 memset(font->unicode2glyph, -1, sizeof(font->unicode2glyph[0])*(font->max_unicode));
568 for(t=0;t<font->num_glyphs;t++) {
569 int u = font->glyphs[t].unicode;
571 assert(font->unicode2glyph[u]<0); // we took care of duplicates, right?
572 font->unicode2glyph[u] = t;
576 /* add the new glyph indexes (most probably, that's only the remapped values
577 at 0xe000) to the unicode2glyph table. Notice: Unlike glyph2unicode, we don't
578 care about collisions in the unicode2glyph table */
579 int new_max_unicode = max+1;
580 if(font->max_unicode < new_max_unicode) {
581 font->unicode2glyph = rfx_realloc(font->unicode2glyph, sizeof(font->unicode2glyph[0])*(font->max_unicode));
582 memset(font->unicode2glyph+font->max_unicode, -1, sizeof(font->unicode2glyph[0])*(new_max_unicode - font->max_unicode));
584 for(t=0;t<font->num_glyphs;t++) {
585 int u = font->glyphs[t].unicode;
586 if(u>=0 && font->unicode2glyph[u]<0) {
587 font->unicode2glyph[u] = t;
590 font->max_unicode = new_max_unicode;
594 ttf_t* gfxfont_to_ttf(gfxfont_t*font)
596 ttf_t*ttf = ttf_new();
597 int num_glyphs = font->num_glyphs;
600 char has_nondef_glyph =
601 font->num_glyphs && font->glyphs[0].unicode==-1 &&
602 (!font->glyphs[0].line || !font->glyphs[0].line->next);
604 if(!has_nondef_glyph) {
605 /* insert a new .nondef glyph at the start of the font */
609 ttf->num_glyphs = num_glyphs;
610 ttf->glyphs = rfx_calloc(num_glyphs*sizeof(ttfglyph_t));
612 int max_unicode = font->max_unicode;
614 for(t=0;t<font->num_glyphs;t++) {
615 gfxglyph_t*src = &font->glyphs[t];
616 ttfglyph_t*dest = &ttf->glyphs[t+offset];
617 gfxline_t*line = src->line;
621 if(line->type == gfx_splineTo)
625 dest->num_points = count;
626 dest->points = rfx_calloc(count*sizeof(ttfpoint_t));
630 if(line->type == gfx_splineTo) {
631 dest->points[count].x = line->sx*scale;
632 dest->points[count].y = line->sy*scale;
635 dest->points[count].x = line->x*scale;
636 dest->points[count].y = line->y*scale;
637 dest->points[count].flags |= GLYPH_ON_CURVE;
638 if(line->type == gfx_moveTo) {
639 dest->points[count].flags |= GLYPH_CONTOUR_START;
641 dest->points[count-1].flags |= GLYPH_CONTOUR_END;
647 dest->points[count-1].flags |= GLYPH_CONTOUR_END;
649 /* compute bounding box */
652 dest->xmin = dest->xmax = dest->points[0].x;
653 dest->ymin = dest->ymax = dest->points[0].y;
654 for(s=1;s<count;s++) {
655 if(dest->points[s].x < dest->xmin)
656 dest->xmin = dest->points[s].x;
657 if(dest->points[s].y < dest->ymin)
658 dest->ymin = dest->points[s].y;
659 if(dest->points[s].x > dest->xmax)
660 dest->xmax = dest->points[s].x;
661 if(dest->points[s].y > dest->ymax)
662 dest->ymax = dest->points[s].y;
666 dest->advance = src->advance*scale;
668 int u = font->glyphs[t].unicode;
669 if(invalid_unicode(u)) {
670 u = 0xe000 + remap_pos++;
675 ttf->unicode_size = max_unicode+1;
676 ttf->unicode = rfx_calloc(sizeof(unicode_t)*ttf->unicode_size);
678 for(t=0;t<font->num_glyphs;t++) {
679 gfxglyph_t*src = &font->glyphs[t];
680 int u = font->glyphs[t].unicode;
681 if(invalid_unicode(u)) {
682 u = 0xe000 + remap_pos++;
684 if(u>=0 && u<ttf->unicode_size)
685 ttf->unicode[u] = t+offset;
688 if(font->unicode2glyph) {
689 for(u=0;u<ttf->unicode_size;u++) {
690 int g = font->unicode2glyph[u];
691 if(invalid_unicode(u))
693 if(g>=0 && !ttf->unicode[u]) {
694 ttf->unicode[u] = g+offset;
698 ttf->ascent = font->ascent;
699 ttf->descent = font->descent;
700 ttf->lineGap = font->ascent + font->descent;
702 ttf->full_name = strdup(font->id);
703 ttf->family_name = strdup(font->id);
704 ttf->subfamily_name = strdup(font->id);
705 ttf->version_string = strdup("Version 1.0");
707 ttf_create_truetype_tables(ttf);
711 void gfxfont_save(gfxfont_t*font, const char*filename)
713 ttf_t*ttf = gfxfont_to_ttf(font);
714 ttf_save(ttf, filename);
718 void gfxfont_save_eot(gfxfont_t*font, const char*filename)
720 ttf_t*ttf = gfxfont_to_ttf(font);
721 ttf_save_eot(ttf, filename);