1 | /* |
---|
2 | * The font parser using the FreeType library version 2. |
---|
3 | * |
---|
4 | * see COPYRIGHT |
---|
5 | * |
---|
6 | */ |
---|
7 | |
---|
8 | #ifdef USE_FREETYPE |
---|
9 | |
---|
10 | #include <stdio.h> |
---|
11 | #include <string.h> |
---|
12 | #include <stdlib.h> |
---|
13 | #include <ctype.h> |
---|
14 | #include <sys/types.h> |
---|
15 | #include <freetype/config/ftheader.h> |
---|
16 | #include <freetype/freetype.h> |
---|
17 | #include <freetype/ftglyph.h> |
---|
18 | #include <freetype/ftsnames.h> |
---|
19 | #include <freetype/ttnameid.h> |
---|
20 | #include <freetype/ftoutln.h> |
---|
21 | #include "pt1.h" |
---|
22 | #include "global.h" |
---|
23 | |
---|
24 | /* prototypes of call entries */ |
---|
25 | static void openfont(char *fname, char *arg); |
---|
26 | static void closefont( void); |
---|
27 | static int getnglyphs ( void); |
---|
28 | static int glnames( GLYPH *glyph_list); |
---|
29 | static void glmetrics( GLYPH *glyph_list); |
---|
30 | static int glenc( GLYPH *glyph_list, int *encoding, int *unimap); |
---|
31 | static void fnmetrics( struct font_metrics *fm); |
---|
32 | static void glpath( int glyphno, GLYPH *glyph_list); |
---|
33 | static void kerning( GLYPH *glyph_list); |
---|
34 | |
---|
35 | /* globals */ |
---|
36 | |
---|
37 | /* front-end descriptor */ |
---|
38 | struct frontsw freetype_sw = { |
---|
39 | /*name*/ "ft", |
---|
40 | /*descr*/ "based on the FreeType library", |
---|
41 | /*suffix*/ { "ttf", "otf", "pfa", "pfb" }, |
---|
42 | /*open*/ openfont, |
---|
43 | /*close*/ closefont, |
---|
44 | /*nglyphs*/ getnglyphs, |
---|
45 | /*glnames*/ glnames, |
---|
46 | /*glmetrics*/ glmetrics, |
---|
47 | /*glenc*/ glenc, |
---|
48 | /*fnmetrics*/ fnmetrics, |
---|
49 | /*glpath*/ glpath, |
---|
50 | /*kerning*/ kerning, |
---|
51 | }; |
---|
52 | |
---|
53 | /* statics */ |
---|
54 | |
---|
55 | static FT_Library library; |
---|
56 | static FT_Face face; |
---|
57 | |
---|
58 | static int enc_type, enc_found; |
---|
59 | |
---|
60 | /* SFNT functions do not seem to be included by default in FT2beta8 */ |
---|
61 | #define ENABLE_SFNT |
---|
62 | |
---|
63 | /* |
---|
64 | * Open font and prepare to return information to the main driver. |
---|
65 | * May print error and warning messages. |
---|
66 | * Exit on error. |
---|
67 | */ |
---|
68 | |
---|
69 | static void |
---|
70 | openfont( |
---|
71 | char *fname, |
---|
72 | char *arg /* unused now */ |
---|
73 | ) |
---|
74 | { |
---|
75 | FT_Error error; |
---|
76 | |
---|
77 | if( FT_Init_FreeType( &library ) ) { |
---|
78 | fprintf(stderr, "** FreeType initialization failed\n"); |
---|
79 | exit(1); |
---|
80 | } |
---|
81 | |
---|
82 | if( error = FT_New_Face( library, fname, 0, &face ) ) { |
---|
83 | if ( error == FT_Err_Unknown_File_Format ) |
---|
84 | fprintf(stderr, "**** %s has format unknown to FreeType\n", fname); |
---|
85 | else |
---|
86 | fprintf(stderr, "**** Cannot access %s ****\n", fname); |
---|
87 | exit(1); |
---|
88 | } |
---|
89 | |
---|
90 | if(FT_HAS_FIXED_SIZES(face)) { |
---|
91 | WARNING_1 fprintf(stderr, "Font contains bitmaps\n"); |
---|
92 | } |
---|
93 | if(FT_HAS_MULTIPLE_MASTERS(face)) { |
---|
94 | WARNING_1 fprintf(stderr, "Font contains multiple masters, using default\n"); |
---|
95 | } |
---|
96 | |
---|
97 | if(ISDBG(FT)) fprintf(stderr," %d units per EM\n", face->units_per_EM); |
---|
98 | |
---|
99 | enc_found = 0; |
---|
100 | } |
---|
101 | |
---|
102 | /* |
---|
103 | * Close font. |
---|
104 | * Exit on error. |
---|
105 | */ |
---|
106 | |
---|
107 | static void |
---|
108 | closefont( |
---|
109 | void |
---|
110 | ) |
---|
111 | { |
---|
112 | if( FT_Done_Face(face) ) { |
---|
113 | WARNING_1 fprintf(stderr, "Errors when closing the font file, ignored\n"); |
---|
114 | } |
---|
115 | if( FT_Done_FreeType(library) ) { |
---|
116 | WARNING_1 fprintf(stderr, "Errors when stopping FreeType, ignored\n"); |
---|
117 | } |
---|
118 | } |
---|
119 | |
---|
120 | /* |
---|
121 | * Get the number of glyphs in font. |
---|
122 | */ |
---|
123 | |
---|
124 | static int |
---|
125 | getnglyphs ( |
---|
126 | void |
---|
127 | ) |
---|
128 | { |
---|
129 | if(ISDBG(FT)) fprintf(stderr, "%d glyphs in font\n", face->num_glyphs); |
---|
130 | return (int)face->num_glyphs; |
---|
131 | } |
---|
132 | |
---|
133 | /* |
---|
134 | * Get the names of the glyphs. |
---|
135 | * Returns 0 if the names were assigned, non-zero if the font |
---|
136 | * provides no glyph names. |
---|
137 | */ |
---|
138 | |
---|
139 | static int |
---|
140 | glnames( |
---|
141 | GLYPH *glyph_list |
---|
142 | ) |
---|
143 | { |
---|
144 | #define MAX_NAMELEN 1024 |
---|
145 | unsigned char bf[1024]; |
---|
146 | int i; |
---|
147 | |
---|
148 | if( ! FT_HAS_GLYPH_NAMES(face) ) { |
---|
149 | WARNING_1 fprintf(stderr, "Font has no glyph names\n"); |
---|
150 | return 1; |
---|
151 | } |
---|
152 | |
---|
153 | for(i=0; i < face->num_glyphs; i++) { |
---|
154 | if( FT_Get_Glyph_Name(face, i, bf, MAX_NAMELEN) || bf[0]==0 ) { |
---|
155 | sprintf(bf, "_g_%d", i); |
---|
156 | WARNING_2 fprintf(stderr, |
---|
157 | "Glyph No. %d has no postscript name, becomes %s\n", i, bf); |
---|
158 | } |
---|
159 | glyph_list[i].name = strdup(bf); |
---|
160 | if(ISDBG(FT)) fprintf(stderr, "%d has name %s\n", i, bf); |
---|
161 | if (glyph_list[i].name == NULL) { |
---|
162 | fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); |
---|
163 | exit(255); |
---|
164 | } |
---|
165 | } |
---|
166 | return 0; |
---|
167 | } |
---|
168 | |
---|
169 | /* |
---|
170 | * Get the metrics of the glyphs. |
---|
171 | */ |
---|
172 | |
---|
173 | static void |
---|
174 | glmetrics( |
---|
175 | GLYPH *glyph_list |
---|
176 | ) |
---|
177 | { |
---|
178 | GLYPH *g; |
---|
179 | int i; |
---|
180 | FT_Glyph_Metrics *met; |
---|
181 | FT_BBox bbox; |
---|
182 | FT_Glyph gly; |
---|
183 | FT_ULong charcode; |
---|
184 | FT_UInt index; |
---|
185 | |
---|
186 | for(i=0; i < face->num_glyphs; i++) { |
---|
187 | g = &(glyph_list[i]); |
---|
188 | |
---|
189 | if( FT_Load_Glyph(face, i, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE) ) { |
---|
190 | fprintf(stderr, "Can't load glyph %s, skipped\n", g->name); |
---|
191 | continue; |
---|
192 | } |
---|
193 | |
---|
194 | met = &face->glyph->metrics; |
---|
195 | |
---|
196 | if(FT_HAS_HORIZONTAL(face)) { |
---|
197 | g->width = met->horiAdvance; |
---|
198 | g->lsb = met->horiBearingX; |
---|
199 | } else { |
---|
200 | WARNING_2 fprintf(stderr, "Glyph %s has no horizontal metrics, guessed them\n", g->name); |
---|
201 | g->width = met->width; |
---|
202 | g->lsb = 0; |
---|
203 | } |
---|
204 | |
---|
205 | if( FT_Get_Glyph(face->glyph, &gly) ) { |
---|
206 | fprintf(stderr, "Can't access glyph %s bbox, skipped\n", g->name); |
---|
207 | continue; |
---|
208 | } |
---|
209 | |
---|
210 | FT_Glyph_Get_CBox(gly, ft_glyph_bbox_unscaled, &bbox); |
---|
211 | g->xMin = bbox.xMin; |
---|
212 | g->yMin = bbox.yMin; |
---|
213 | g->xMax = bbox.xMax; |
---|
214 | g->yMax = bbox.yMax; |
---|
215 | |
---|
216 | g->ttf_pathlen = face->glyph->outline.n_points; |
---|
217 | |
---|
218 | } |
---|
219 | |
---|
220 | charcode = FT_Get_First_Char(face, &index); |
---|
221 | while ( index != 0 ) { |
---|
222 | if ( index >= face->num_glyphs ) { |
---|
223 | break; |
---|
224 | } |
---|
225 | for ( i = 0; i < GLYPH_MAX_ENCODINGS; i++ ) { |
---|
226 | if ( glyph_list[index].orig_code[i] == -1 ) |
---|
227 | break; |
---|
228 | } |
---|
229 | |
---|
230 | if ( i == GLYPH_MAX_ENCODINGS ) { |
---|
231 | if (strcmp(glyph_list[index].name, ".notdef") != 0) { |
---|
232 | WARNING_2 fprintf(stderr, |
---|
233 | "Glyph %s has >= %d encodings (A), %4.4x & %4.4x\n", |
---|
234 | GLYPH_MAX_ENCODINGS, |
---|
235 | glyph_list[index].name, |
---|
236 | glyph_list[index].orig_code[i], |
---|
237 | charcode); |
---|
238 | } |
---|
239 | } else { |
---|
240 | glyph_list[index].orig_code[i] = charcode; |
---|
241 | } |
---|
242 | |
---|
243 | charcode = FT_Get_Next_Char(face, charcode, &index); |
---|
244 | } |
---|
245 | } |
---|
246 | |
---|
247 | /* |
---|
248 | * Get the original encoding of the font. |
---|
249 | * Returns 1 for if the original encoding is Unicode, 2 if the |
---|
250 | * original encoding is other 16-bit, 0 if 8-bit. |
---|
251 | */ |
---|
252 | |
---|
253 | static int |
---|
254 | glenc( |
---|
255 | GLYPH *glyph_list, |
---|
256 | int *encoding, |
---|
257 | int *unimap |
---|
258 | ) |
---|
259 | { |
---|
260 | int i, e; |
---|
261 | unsigned code, index; |
---|
262 | |
---|
263 | if(ISDBG(FT)) |
---|
264 | for(e=0; e < face->num_charmaps; e++) { |
---|
265 | fprintf(stderr, "found encoding pid=%d eid=%d\n", |
---|
266 | face->charmaps[e]->platform_id, |
---|
267 | face->charmaps[e]->encoding_id); |
---|
268 | } |
---|
269 | |
---|
270 | if(enc_found) |
---|
271 | goto populate_map; |
---|
272 | |
---|
273 | enc_type = 0; |
---|
274 | |
---|
275 | /* first check for an explicit PID/EID */ |
---|
276 | |
---|
277 | if(force_pid != -1) { |
---|
278 | for(e=0; e < face->num_charmaps; e++) { |
---|
279 | if(face->charmaps[e]->platform_id == force_pid |
---|
280 | && face->charmaps[e]->encoding_id == force_eid) { |
---|
281 | WARNING_1 fprintf(stderr, "Found Encoding PID=%d/EID=%d\n", |
---|
282 | force_pid, force_eid); |
---|
283 | if( !face->charmaps || FT_Set_Charmap(face, face->charmaps[e]) ) { |
---|
284 | fprintf(stderr, "**** Cannot set charmap in FreeType ****\n"); |
---|
285 | exit(1); |
---|
286 | } |
---|
287 | enc_type = 1; |
---|
288 | goto populate_map; |
---|
289 | } |
---|
290 | } |
---|
291 | fprintf(stderr, "*** TTF encoding table PID=%d/EID=%d not found\n", |
---|
292 | force_pid, force_eid); |
---|
293 | exit(1); |
---|
294 | } |
---|
295 | |
---|
296 | /* next check for a direct Adobe mapping */ |
---|
297 | |
---|
298 | if(!forcemap) { |
---|
299 | for(e=0; e < face->num_charmaps; e++) { |
---|
300 | if(face->charmaps[e]->encoding == ft_encoding_adobe_custom) { |
---|
301 | WARNING_1 fputs("Found Adobe Custom Encoding\n", stderr); |
---|
302 | if( FT_Set_Charmap(face, face->charmaps[e]) ) { |
---|
303 | fprintf(stderr, "**** Cannot set charmap in FreeType ****\n"); |
---|
304 | exit(1); |
---|
305 | } |
---|
306 | goto populate_map; |
---|
307 | } |
---|
308 | } |
---|
309 | } |
---|
310 | |
---|
311 | for(e=0; e < face->num_charmaps; e++) { |
---|
312 | if(face->charmaps[e]->platform_id == 3) { |
---|
313 | switch(face->charmaps[e]->encoding_id) { |
---|
314 | case 0: |
---|
315 | WARNING_1 fputs("Found Symbol Encoding\n", stderr); |
---|
316 | break; |
---|
317 | case 1: |
---|
318 | WARNING_1 fputs("Found Unicode Encoding\n", stderr); |
---|
319 | enc_type = 1; |
---|
320 | break; |
---|
321 | default: |
---|
322 | WARNING_1 { |
---|
323 | fprintf(stderr, |
---|
324 | "****MS Encoding ID %d not supported****\n", |
---|
325 | face->charmaps[e]->encoding_id); |
---|
326 | fputs("Treating it like Symbol encoding\n", stderr); |
---|
327 | } |
---|
328 | break; |
---|
329 | } |
---|
330 | break; |
---|
331 | } |
---|
332 | } |
---|
333 | if(e >= face->num_charmaps) { |
---|
334 | WARNING_1 fputs("No Microsoft encoding, using first encoding available\n", stderr); |
---|
335 | e = 0; |
---|
336 | } |
---|
337 | |
---|
338 | if( FT_Set_Charmap(face, face->charmaps[e]) ) { |
---|
339 | fprintf(stderr, "**** Cannot set charmap in FreeType ****\n"); |
---|
340 | exit(1); |
---|
341 | } |
---|
342 | |
---|
343 | populate_map: |
---|
344 | enc_found = 1; |
---|
345 | |
---|
346 | for(i=0; i<ENCTABSZ; i++) { |
---|
347 | if(encoding[i] != -1) |
---|
348 | continue; |
---|
349 | if(enc_type == 1 || forcemap) { |
---|
350 | code = unimap[i]; |
---|
351 | if(code == (unsigned) -1) |
---|
352 | continue; |
---|
353 | } else |
---|
354 | code = i; |
---|
355 | |
---|
356 | code = FT_Get_Char_Index(face, code); |
---|
357 | if(0 && ISDBG(FT)) fprintf(stderr, "code of %3d is %3d\n", i, code); |
---|
358 | if(code == 0) |
---|
359 | continue; /* .notdef */ |
---|
360 | encoding[i] = code; |
---|
361 | } |
---|
362 | |
---|
363 | return enc_type; |
---|
364 | } |
---|
365 | |
---|
366 | /* |
---|
367 | * Get the font metrics |
---|
368 | */ |
---|
369 | static void |
---|
370 | fnmetrics( |
---|
371 | struct font_metrics *fm |
---|
372 | ) |
---|
373 | { |
---|
374 | char *str; |
---|
375 | static char *fieldstocheck[3]; |
---|
376 | #ifdef ENABLE_SFNT |
---|
377 | FT_SfntName sn; |
---|
378 | #endif /* ENABLE_SFNT */ |
---|
379 | int i, j, len; |
---|
380 | |
---|
381 | fm->italic_angle = 0.0; /* FreeType hides the angle */ |
---|
382 | fm->underline_position = face->underline_position; |
---|
383 | fm->underline_thickness = face->underline_thickness; |
---|
384 | fm->is_fixed_pitch = FT_IS_FIXED_WIDTH(face); |
---|
385 | |
---|
386 | fm->ascender = face->ascender; |
---|
387 | fm->descender = face->descender; |
---|
388 | |
---|
389 | fm->units_per_em = face->units_per_EM; |
---|
390 | |
---|
391 | fm->bbox[0] = face->bbox.xMin; |
---|
392 | fm->bbox[1] = face->bbox.yMin; |
---|
393 | fm->bbox[2] = face->bbox.xMax; |
---|
394 | fm->bbox[3] = face->bbox.yMax; |
---|
395 | |
---|
396 | #ifdef ENABLE_SFNT |
---|
397 | if( FT_Get_Sfnt_Name(face, TT_NAME_ID_COPYRIGHT, &sn) ) |
---|
398 | #endif /* ENABLE_SFNT */ |
---|
399 | fm->name_copyright = ""; |
---|
400 | #ifdef ENABLE_SFNT |
---|
401 | else |
---|
402 | fm->name_copyright = dupcnstring(sn.string, sn.string_len); |
---|
403 | #endif /* ENABLE_SFNT */ |
---|
404 | |
---|
405 | fm->name_family = face->family_name; |
---|
406 | |
---|
407 | fm->name_style = face->style_name; |
---|
408 | if(fm->name_style == NULL) |
---|
409 | fm->name_style = ""; |
---|
410 | |
---|
411 | #ifdef ENABLE_SFNT |
---|
412 | if( FT_Get_Sfnt_Name(face, TT_NAME_ID_FULL_NAME, &sn) ) |
---|
413 | #endif /* ENABLE_SFNT */ |
---|
414 | { |
---|
415 | int len; |
---|
416 | |
---|
417 | len = strlen(fm->name_family) + strlen(fm->name_style) + 2; |
---|
418 | if(( fm->name_full = malloc(len) )==NULL) { |
---|
419 | fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); |
---|
420 | exit(255); |
---|
421 | } |
---|
422 | strcpy(fm->name_full, fm->name_family); |
---|
423 | if(strlen(fm->name_style) != 0) { |
---|
424 | strcat(fm->name_full, " "); |
---|
425 | strcat(fm->name_full, fm->name_style); |
---|
426 | } |
---|
427 | } |
---|
428 | #ifdef ENABLE_SFNT |
---|
429 | else |
---|
430 | fm->name_full = dupcnstring(sn.string, sn.string_len); |
---|
431 | #endif /* ENABLE_SFNT */ |
---|
432 | |
---|
433 | #ifdef ENABLE_SFNT |
---|
434 | if( FT_Get_Sfnt_Name(face, TT_NAME_ID_VERSION_STRING, &sn) ) |
---|
435 | #endif /* ENABLE_SFNT */ |
---|
436 | fm->name_version = "1.0"; |
---|
437 | #ifdef ENABLE_SFNT |
---|
438 | else |
---|
439 | fm->name_version = dupcnstring(sn.string, sn.string_len); |
---|
440 | #endif /* ENABLE_SFNT */ |
---|
441 | |
---|
442 | #ifdef ENABLE_SFNT |
---|
443 | if( FT_Get_Sfnt_Name(face, TT_NAME_ID_PS_NAME , &sn) ) { |
---|
444 | #endif /* ENABLE_SFNT */ |
---|
445 | if(( fm->name_ps = strdup(fm->name_full) )==NULL) { |
---|
446 | fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); |
---|
447 | exit(255); |
---|
448 | } |
---|
449 | #ifdef ENABLE_SFNT |
---|
450 | } else |
---|
451 | fm->name_ps = dupcnstring(sn.string, sn.string_len); |
---|
452 | #endif /* ENABLE_SFNT */ |
---|
453 | for(i=0; fm->name_ps[i]!=0; i++) |
---|
454 | if(fm->name_ps[i] == ' ') |
---|
455 | fm->name_ps[i] = '_'; /* no spaces in the Postscript name *m |
---|
456 | |
---|
457 | /* guess the boldness from the font names */ |
---|
458 | fm->force_bold=0; |
---|
459 | |
---|
460 | fieldstocheck[0] = fm->name_style; |
---|
461 | fieldstocheck[1] = fm->name_full; |
---|
462 | fieldstocheck[2] = fm->name_ps; |
---|
463 | |
---|
464 | for(i=0; !fm->force_bold && i<sizeof fieldstocheck /sizeof(fieldstocheck[0]); i++) { |
---|
465 | str=fieldstocheck[i]; |
---|
466 | len = strlen(str); |
---|
467 | for(j=0; j<len; j++) { |
---|
468 | if( (str[j]=='B' |
---|
469 | || str[j]=='b' |
---|
470 | && ( j==0 || !isalpha(str[j-1]) ) |
---|
471 | ) |
---|
472 | && !strncmp("old",&str[j+1],3) |
---|
473 | && (j+4 >= len || !islower(str[j+4])) |
---|
474 | ) { |
---|
475 | fm->force_bold=1; |
---|
476 | break; |
---|
477 | } |
---|
478 | } |
---|
479 | } |
---|
480 | } |
---|
481 | |
---|
482 | /* |
---|
483 | * Functions to decompose the outlines |
---|
484 | */ |
---|
485 | |
---|
486 | static GLYPH *curg; |
---|
487 | static double lastx, lasty; |
---|
488 | |
---|
489 | static int |
---|
490 | outl_moveto( |
---|
491 | FT_Vector *to, |
---|
492 | void *unused |
---|
493 | ) |
---|
494 | { |
---|
495 | double tox, toy; |
---|
496 | |
---|
497 | tox = fscale((double)to->x); toy = fscale((double)to->y); |
---|
498 | |
---|
499 | /* FreeType does not do explicit closepath() */ |
---|
500 | if(curg->lastentry) { |
---|
501 | g_closepath(curg); |
---|
502 | } |
---|
503 | fg_rmoveto(curg, tox, toy); |
---|
504 | lastx = tox; lasty = toy; |
---|
505 | |
---|
506 | return 0; |
---|
507 | } |
---|
508 | |
---|
509 | static int |
---|
510 | outl_lineto( |
---|
511 | FT_Vector *to, |
---|
512 | void *unused |
---|
513 | ) |
---|
514 | { |
---|
515 | double tox, toy; |
---|
516 | |
---|
517 | tox = fscale((double)to->x); toy = fscale((double)to->y); |
---|
518 | |
---|
519 | fg_rlineto(curg, tox, toy); |
---|
520 | lastx = tox; lasty = toy; |
---|
521 | |
---|
522 | return 0; |
---|
523 | } |
---|
524 | |
---|
525 | static int |
---|
526 | outl_conicto( |
---|
527 | FT_Vector *control1, |
---|
528 | FT_Vector *to, |
---|
529 | void *unused |
---|
530 | ) |
---|
531 | { |
---|
532 | double c1x, c1y, tox, toy; |
---|
533 | |
---|
534 | c1x = fscale((double)control1->x); c1y = fscale((double)control1->y); |
---|
535 | tox = fscale((double)to->x); toy = fscale((double)to->y); |
---|
536 | |
---|
537 | fg_rrcurveto(curg, |
---|
538 | (lastx + 2.0 * c1x) / 3.0, (lasty + 2.0 * c1y) / 3.0, |
---|
539 | (2.0 * c1x + tox) / 3.0, (2.0 * c1y + toy) / 3.0, |
---|
540 | tox, toy ); |
---|
541 | lastx = tox; lasty = toy; |
---|
542 | |
---|
543 | return 0; |
---|
544 | } |
---|
545 | |
---|
546 | static int |
---|
547 | outl_cubicto( |
---|
548 | FT_Vector *control1, |
---|
549 | FT_Vector *control2, |
---|
550 | FT_Vector *to, |
---|
551 | void *unused |
---|
552 | ) |
---|
553 | { |
---|
554 | double c1x, c1y, c2x, c2y, tox, toy; |
---|
555 | |
---|
556 | c1x = fscale((double)control1->x); c1y = fscale((double)control1->y); |
---|
557 | c2x = fscale((double)control2->x); c2y = fscale((double)control2->y); |
---|
558 | tox = fscale((double)to->x); toy = fscale((double)to->y); |
---|
559 | |
---|
560 | fg_rrcurveto(curg, c1x, c1y, c2x, c2y, tox, toy); |
---|
561 | lastx = tox; lasty = toy; |
---|
562 | |
---|
563 | return 0; |
---|
564 | } |
---|
565 | |
---|
566 | static FT_Outline_Funcs ft_outl_funcs = { |
---|
567 | outl_moveto, |
---|
568 | outl_lineto, |
---|
569 | outl_conicto, |
---|
570 | outl_cubicto, |
---|
571 | 0, |
---|
572 | 0 |
---|
573 | }; |
---|
574 | |
---|
575 | /* |
---|
576 | * Get the path of contrours for a glyph. |
---|
577 | */ |
---|
578 | |
---|
579 | static void |
---|
580 | glpath( |
---|
581 | int glyphno, |
---|
582 | GLYPH *glyf_list |
---|
583 | ) |
---|
584 | { |
---|
585 | FT_Outline *ol; |
---|
586 | |
---|
587 | curg = &glyf_list[glyphno]; |
---|
588 | |
---|
589 | if( FT_Load_Glyph(face, glyphno, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE|FT_LOAD_NO_HINTING) |
---|
590 | || face->glyph->format != ft_glyph_format_outline ) { |
---|
591 | fprintf(stderr, "Can't load glyph %s, skipped\n", curg->name); |
---|
592 | return; |
---|
593 | } |
---|
594 | |
---|
595 | ol = &face->glyph->outline; |
---|
596 | lastx = 0.0; lasty = 0.0; |
---|
597 | |
---|
598 | if( FT_Outline_Decompose(ol, &ft_outl_funcs, NULL) ) { |
---|
599 | fprintf(stderr, "Can't decompose outline of glyph %s, skipped\n", curg->name); |
---|
600 | return; |
---|
601 | } |
---|
602 | |
---|
603 | /* FreeType does not do explicit closepath() */ |
---|
604 | if(curg->lastentry) { |
---|
605 | g_closepath(curg); |
---|
606 | } |
---|
607 | |
---|
608 | if(ol->flags & ft_outline_reverse_fill) { |
---|
609 | assertpath(curg->entries, __FILE__, __LINE__, curg->name); |
---|
610 | reversepaths(curg); |
---|
611 | } |
---|
612 | } |
---|
613 | |
---|
614 | /* |
---|
615 | * Get the kerning data. |
---|
616 | */ |
---|
617 | |
---|
618 | static void |
---|
619 | kerning( |
---|
620 | GLYPH *glyph_list |
---|
621 | ) |
---|
622 | { |
---|
623 | int i, j, n; |
---|
624 | int nglyphs = face->num_glyphs; |
---|
625 | FT_Vector k; |
---|
626 | GLYPH *gl; |
---|
627 | |
---|
628 | if( nglyphs == 0 || !FT_HAS_KERNING(face) ) { |
---|
629 | WARNING_1 fputs("No Kerning data\n", stderr); |
---|
630 | return; |
---|
631 | } |
---|
632 | |
---|
633 | for(i=0; i<nglyphs; i++) { |
---|
634 | if( (glyph_list[i].flags & GF_USED) ==0) |
---|
635 | continue; |
---|
636 | for(j=0; j<nglyphs; j++) { |
---|
637 | if( (glyph_list[j].flags & GF_USED) ==0) |
---|
638 | continue; |
---|
639 | if( FT_Get_Kerning(face, i, j, ft_kerning_unscaled, &k) ) |
---|
640 | continue; |
---|
641 | if( k.x == 0 ) |
---|
642 | continue; |
---|
643 | |
---|
644 | addkernpair(i, j, k.x); |
---|
645 | } |
---|
646 | } |
---|
647 | } |
---|
648 | |
---|
649 | #endif |
---|