3 Functions for loading external fonts.
5 Extension module for the rfxswf library.
6 Part of the swftools package.
8 Copyright (c) 2003, 2004 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 */
26 #include <freetype/freetype.h>
27 #include <freetype/ftglyph.h>
28 #include <freetype/ftsnames.h>
29 #include <freetype/ttnameid.h>
30 #include <freetype/ftoutln.h>
33 #define FT_SUBPIXELS 64
35 static int ft_move_to(FT_Vector* _to, void* user)
37 drawer_t* draw = (drawer_t*)user;
39 to.x = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
40 to.y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
41 draw->moveTo(draw, &to);
44 static int ft_line_to(FT_Vector* _to, void* user)
46 drawer_t* draw = (drawer_t*)user;
48 to.x = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
49 to.y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
50 draw->lineTo(draw, &to);
53 static int ft_cubic_to(FT_Vector* _c1, FT_Vector* _c2, FT_Vector* _to, void* user)
55 drawer_t* draw = (drawer_t*)user;
57 to.x = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
58 to.y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
59 c1.x = _c1->x*FT_SCALE/(float)FT_SUBPIXELS;
60 c1.y = -_c1->y*FT_SCALE/(float)FT_SUBPIXELS;
61 c2.x = _c2->x*FT_SCALE/(float)FT_SUBPIXELS;
62 c2.y = -_c2->y*FT_SCALE/(float)FT_SUBPIXELS;
63 draw_cubicTo(draw, &c1, &c2, &to);
66 static int ft_conic_to(FT_Vector* _c, FT_Vector* _to, void* user)
68 drawer_t* draw = (drawer_t*)user;
70 to.x = _to->x*FT_SCALE/(float)FT_SUBPIXELS;
71 to.y = -_to->y*FT_SCALE/(float)FT_SUBPIXELS;
72 c.x = _c->x*FT_SCALE/(float)FT_SUBPIXELS;
73 c.y = -_c->y*FT_SCALE/(float)FT_SUBPIXELS;
74 draw_conicTo(draw, &c, &to);
77 static FT_Outline_Funcs outline_functions =
86 static FT_Library ftlibrary = 0;
88 SWFFONT* swf_LoadTrueTypeFont(char*filename)
99 if(FT_Init_FreeType(&ftlibrary)) {
100 fprintf(stderr, "Couldn't init freetype library!\n");
104 error = FT_New_Face(ftlibrary, filename, 0, &face);
106 fprintf(stderr, "Couldn't load file %s- not a TTF file?\n", filename);
109 if(face->num_glyphs <= 0)
112 font = malloc(sizeof(SWFFONT));
113 memset(font, 0, sizeof(SWFFONT));
116 font->layout = malloc(sizeof(SWFLAYOUT));
117 memset(font->layout, 0, sizeof(SWFLAYOUT));
118 font->layout->bounds = malloc(face->num_glyphs*sizeof(SRECT));
119 font->numchars = face->num_glyphs;
120 font->style = ((face->style_flags&FT_STYLE_FLAG_ITALIC)?FONT_STYLE_ITALIC:0)
121 |((face->style_flags&FT_STYLE_FLAG_BOLD)?FONT_STYLE_BOLD:0);
122 font->encoding = FONT_ENCODING_UNICODE;
123 font->glyph2ascii = malloc(face->num_glyphs*sizeof(U16));
124 memset(font->glyph2ascii, 0, face->num_glyphs*sizeof(U16));
126 memset(font->ascii2glyph, -1, font->maxascii*sizeof(int));
127 font->glyph = malloc(face->num_glyphs*sizeof(SWFGLYPH));
128 memset(font->glyph, 0, face->num_glyphs*sizeof(U16));
129 if(FT_HAS_GLYPH_NAMES(face)) {
130 font->glyphnames = malloc(face->num_glyphs*sizeof(char*));
133 font->layout->ascent = face->ascender; //face->bbox.xMin;
134 font->layout->descent = face->descender; //face->bbox.xMax;
135 font->layout->leading = -face->bbox.xMin;
136 font->layout->kerningcount = 0;
138 name = FT_Get_Postscript_Name(face);
140 font->name = (U8*)strdup(name);
142 /* // Map Glyphs to Unicode, version 1 (quick and dirty):
144 for(t=0;t<65536;t++) {
145 int index = FT_Get_Char_Index(face, t);
146 if(index>=0 && index<face->num_glyphs) {
147 if(font->glyph2ascii[index]<0)
148 font->glyph2ascii[index] = t;
152 // Map Glyphs to Unicode, version 2 (much nicer):
153 // (The third way would be the AGL algorithm, as proposed
154 // by Werner Lemberg on freetype@freetype.org)
156 charcode = FT_Get_First_Char(face, &gindex);
159 if(gindex >= 0 && gindex<face->num_glyphs) {
160 if(!font->glyph2ascii[gindex]) {
161 font->glyph2ascii[gindex] = charcode;
162 if(charcode + 1 > font->maxascii) {
163 font->maxascii = charcode + 1;
167 charcode = FT_Get_Next_Char(face, charcode, &gindex);
170 font->ascii2glyph = malloc(font->maxascii*sizeof(int));
172 for(t=0;t<font->maxascii;t++) {
173 font->ascii2glyph[t] = FT_Get_Char_Index(face, t);
174 if(!font->ascii2glyph[t])
175 font->ascii2glyph[t] = -1;
178 for(t=0; t < face->num_glyphs; t++) {
186 if(FT_HAS_GLYPH_NAMES(face)) {
187 error = FT_Get_Glyph_Name(face, t, name, 127);
189 font->glyphnames[t] = strdup(name);
191 error = FT_Load_Glyph(face, t, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE);
193 error = FT_Get_Glyph(face->glyph, &glyph);
196 FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_unscaled, &bbox);
197 bbox.yMin = -bbox.yMin;
198 bbox.yMax = -bbox.yMax;
199 if(bbox.xMax < bbox.xMin) {
201 bbox.xMax ^= bbox.xMin;
202 bbox.xMin ^= bbox.xMax;
203 bbox.xMax ^= bbox.xMin;
205 if(bbox.yMax < bbox.yMin) {
207 bbox.yMax ^= bbox.yMin;
208 bbox.yMin ^= bbox.yMax;
209 bbox.yMax ^= bbox.yMin;
212 swf_Shape01DrawerInit(&draw, 0);
214 //error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &draw);
215 error = FT_Outline_Decompose(&face->glyph->outline, &outline_functions, &draw);
222 font->glyph[t].advance = (bbox.xMax*FT_SCALE)/FT_SUBPIXELS;
224 font->glyph[t].advance = ((bbox.xMax - bbox.xMin)*FT_SCALE)/FT_SUBPIXELS;
227 font->glyph[t].advance = glyph->advance.x/65536;
230 font->glyph[t].shape = swf_ShapeDrawerToShape(&draw);
232 font->layout->bounds[t].xmin = (bbox.xMin*FT_SCALE*20)/FT_SUBPIXELS;
233 font->layout->bounds[t].ymin = (bbox.yMin*FT_SCALE*20)/FT_SUBPIXELS;
234 font->layout->bounds[t].xmax = (bbox.xMax*FT_SCALE*20)/FT_SUBPIXELS;
235 font->layout->bounds[t].ymax = (bbox.yMax*FT_SCALE*20)/FT_SUBPIXELS;
239 FT_Done_Glyph(glyph);
243 FT_Done_FreeType(ftlibrary);ftlibrary=0;
247 #else //HAVE_FREETYPE
249 SWFFONT* swf_LoadTrueTypeFont(char*filename)
251 fprintf(stderr, "Warning: no freetype library- not able to load %s\n", filename);
261 static int t1lib_initialized = 0;
263 SWFFONT* swf_LoadT1Font(char*filename)
267 float angle,underline;
268 char*fontname,*fullname,*familyname;
276 if(!t1lib_initialized) {
278 if ((T1_InitLib(NO_LOGFILE)==NULL)){
279 fprintf(stderr, "Initialization of t1lib failed\n");
282 t1lib_initialized = 1;
284 nr = T1_AddFont(filename);
287 num = T1_SetDefaultEncoding(encoding);
288 for(;num<256;num++) encoding[num] = 0;
290 charnames = T1_GetAllCharNames(nr);
292 angle = T1_GetItalicAngle(nr);
293 fontname = T1_GetFontName(nr);
294 fullname = T1_GetFullName(nr);
295 familyname = T1_GetFamilyName(nr);
296 underline = T1_GetUnderlinePosition(nr);
297 bbox = T1_GetFontBBox(nr);
299 font = (SWFFONT*)malloc(sizeof(SWFFONT));
300 memset(font, 0, sizeof(SWFFONT));
304 font->name = (U8*)strdup(fontname);
307 font->layout = (SWFLAYOUT*)malloc(sizeof(SWFLAYOUT));
308 memset(font->layout, 0, sizeof(SWFLAYOUT));
311 charname = charnames;
317 font->maxascii = num;
318 font->numchars = num;
320 font->style = (/*bold*/0?FONT_STYLE_BOLD:0) + (angle>0.05?FONT_STYLE_ITALIC:0);
322 font->glyph = (SWFGLYPH*)malloc(num*sizeof(SWFGLYPH));
323 memset(font->glyph, 0, num*sizeof(SWFGLYPH));
324 font->glyph2ascii = (U16*)malloc(num*sizeof(U16));
325 memset(font->glyph2ascii, 0, num*sizeof(U16));
326 font->ascii2glyph = (int*)malloc(font->maxascii*sizeof(int));
327 memset(font->ascii2glyph, -1, font->maxascii*sizeof(int));
328 font->layout->ascent = (U16)(underline - bbox.lly);
329 font->layout->descent = (U16)(bbox.ury - underline);
330 font->layout->leading = (U16)(font->layout->ascent -
331 font->layout->descent -
332 (bbox.lly - bbox.ury));
333 font->layout->bounds = (SRECT*)malloc(sizeof(SRECT)*num);
334 memset(font->layout->bounds, 0, sizeof(SRECT)*num);
335 font->layout->kerningcount = 0;
336 font->layout->kerning = 0;
337 font->glyphnames = malloc(num*sizeof(char*));
338 memset(font->glyphnames, 0, num*sizeof(char*));
342 charname = charnames;
343 for(c=0;c<font->numchars;c++) {
346 T1_OUTLINE * outline;
350 outline = T1_GetCharOutline(nr, c, 100.0, 0);
351 firstx = outline->dest.x/0xffff;
357 font->glyphnames[c] = strdup(*charname);
360 font->ascii2glyph[c] = c;
361 font->glyph2ascii[c] = c;
363 swf_Shape01DrawerInit(&draw, 0);
366 pos.x += (outline->dest.x/(float)0xffff);
367 pos.y += (outline->dest.y/(float)0xffff);
369 if(outline->type == T1_PATHTYPE_MOVE) {
370 draw.moveTo(&draw,&pos);
371 } else if(outline->type == T1_PATHTYPE_LINE) {
372 draw.lineTo(&draw,&pos);
373 } else if(outline->type == T1_PATHTYPE_BEZIER) {
374 T1_BEZIERSEGMENT*o2 = (T1_BEZIERSEGMENT*)outline;
376 b.x = o2->B.x/(float)0xffff+last.x;
377 b.y = o2->B.y/(float)0xffff+last.y;
378 c.x = o2->C.x/(float)0xffff+last.x;
379 c.y = o2->C.y/(float)0xffff+last.y;
380 draw_cubicTo(&draw,&b,&c,&pos);
382 fprintf(stderr, "loadT1Font: unknown outline type:%d\n", outline->type);
385 outline = outline->link;
390 font->glyph[c].shape = swf_ShapeDrawerToShape(&draw);
391 bbox = swf_ShapeDrawerGetBBox(&draw);
394 font->layout->bounds[c] = bbox;
395 font->glyph[c].advance = bbox.xmax/20;
396 if(!font->glyph[c].advance) {
397 font->glyph[c].advance = firstx;
406 SWFFONT* swf_LoadT1Font(char*filename)
408 fprintf(stderr, "Warning: no t1lib- not able to load %s\n", filename);
414 static int isSWF(const char*filename)
416 FILE*fi = fopen(filename, "rb");
422 memset(a, 0, sizeof(a));
426 if(!strncmp(a, "FWS", 3) || !strncmp(a, "CWS", 3)) {
432 SWFFONT* swf_LoadFont(char*filename)
434 int is_swf = isSWF(filename);
438 return swf_ReadFont(filename);
440 #if defined(HAVE_FREETYPE)
441 return swf_LoadTrueTypeFont(filename);
442 #elif defined(HAVE_T1LIB)
443 return swf_LoadT1Font(filename);
445 fprintf(stderr, "Error: Neither T1lib nor FreeType support compiled in. Could not load %s\n", filename);