sdk-world v2026.11.05
PS2 SDK - world tier (copyleft-allowed, non-essential packages)
Loading...
Searching...
No Matches
ttobjs.c
1/****************************************************************************
2 *
3 * ttobjs.c
4 *
5 * Objects manager (body).
6 *
7 * Copyright (C) 1996-2025 by
8 * David Turner, Robert Wilhelm, and Werner Lemberg.
9 *
10 * This file is part of the FreeType project, and may only be used,
11 * modified, and distributed under the terms of the FreeType project
12 * license, LICENSE.TXT. By continuing to use, modify, or distribute
13 * this file you indicate that you have read the license and
14 * understand and accept it fully.
15 *
16 */
17
18
21#include <freetype/tttags.h>
23#include <freetype/ftdriver.h>
24
25#include "ttgload.h"
26#include "ttpload.h"
27
28#include "tterrors.h"
29
30#ifdef TT_USE_BYTECODE_INTERPRETER
31#include "ttinterp.h"
32#endif
33
34#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
35#include "ttgxvar.h"
36#endif
37
38 /**************************************************************************
39 *
40 * The macro FT_COMPONENT is used in trace mode. It is an implicit
41 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
42 * messages during execution.
43 */
44#undef FT_COMPONENT
45#define FT_COMPONENT ttobjs
46
47
48#ifdef TT_USE_BYTECODE_INTERPRETER
49
50 /**************************************************************************
51 *
52 * GLYPH ZONE FUNCTIONS
53 *
54 */
55
56
57 /**************************************************************************
58 *
59 * @Function:
60 * tt_glyphzone_done
61 *
62 * @Description:
63 * Deallocate a glyph zone.
64 *
65 * @Input:
66 * zone ::
67 * A pointer to the target glyph zone.
68 */
69 FT_LOCAL_DEF( void )
70 tt_glyphzone_done( FT_Memory memory,
71 TT_GlyphZone zone )
72 {
73 FT_FREE( zone->org );
74
75 zone->n_points = 0;
76 zone->n_contours = 0;
77 }
78
79
80 /**************************************************************************
81 *
82 * @Function:
83 * tt_glyphzone_new
84 *
85 * @Description:
86 * Allocate a new glyph zone.
87 *
88 * @Input:
89 * memory ::
90 * A handle to the current memory object.
91 *
92 * maxPoints ::
93 * The capacity of glyph zone in points.
94 *
95 * maxContours ::
96 * The capacity of glyph zone in contours.
97 *
98 * @Output:
99 * zone ::
100 * A pointer to the target glyph zone record.
101 *
102 * @Return:
103 * FreeType error code. 0 means success.
104 */
105 FT_LOCAL_DEF( FT_Error )
106 tt_glyphzone_new( FT_Memory memory,
107 FT_UShort maxPoints,
108 FT_UShort maxContours,
109 TT_GlyphZone zone )
110 {
111 FT_Error error;
112 FT_Long size = 3 * maxPoints * sizeof ( FT_Vector ) +
113 maxContours * sizeof ( FT_UShort ) +
114 maxPoints * sizeof ( FT_Byte );
115
116
117 if ( !FT_ALLOC( zone->org, size ) )
118 {
119 zone->n_points = maxPoints;
120 zone->n_contours = maxContours;
121
122 zone->cur = zone->org + maxPoints;
123 zone->orus = zone->cur + maxPoints;
124 zone->contours = (FT_UShort*)( zone->orus + maxPoints );
125 zone->tags = (FT_Byte*)( zone->contours + maxContours );
126
127 zone->first_point = 0;
128 }
129
130 return error;
131 }
132
133
134 /*
135 * Fonts embedded in PDFs are made unique by prepending randomization
136 * prefixes to their names: as defined in Section 5.5.3, 'Font Subsets',
137 * of the PDF Reference, they consist of 6 uppercase letters followed by
138 * the `+` sign. For safety, we do not skip prefixes violating this rule.
139 */
140
141 static const FT_String*
142 tt_skip_pdffont_random_tag( const FT_String* name )
143 {
144 if ( ft_isupper( name[0] ) &&
145 ft_isupper( name[1] ) &&
146 ft_isupper( name[2] ) &&
147 ft_isupper( name[3] ) &&
148 ft_isupper( name[4] ) &&
149 ft_isupper( name[5] ) &&
150 '+' == name[6] &&
151 name[7] )
152 {
153 FT_TRACE7(( "name without randomization tag: %s\n", name + 7 ));
154 return name + 7;
155 }
156
157 return name;
158 }
159
160
161 /* Compare the face with a list of well-known `tricky' fonts. */
162 /* This list shall be expanded as we find more of them. */
163
164 static FT_Bool
165 tt_check_trickyness_family( const FT_String* name )
166 {
167
168#define TRICK_NAMES_MAX_CHARACTERS 19
169#define TRICK_NAMES_COUNT 20
170
171 static const char trick_names[TRICK_NAMES_COUNT]
172 [TRICK_NAMES_MAX_CHARACTERS + 1] =
173 {
174 /*
175 PostScript names are given in brackets if they differ from the
176 family name. The version numbers, together with the copyright or
177 release year data, are taken from fonts available to the
178 developers.
179
180 Note that later versions of the fonts might be no longer tricky;
181 for example, `MingLiU' version 7.00 (file `mingliu.ttc' from
182 Windows 7) is an ordinary TTC with non-tricky subfonts.
183 */
184
185 "cpop", /* dftt-p7.ttf; version 1.00, 1992 [DLJGyShoMedium] */
186 "DFGirl-W6-WIN-BF", /* dftt-h6.ttf; version 1.00, 1993 */
187 "DFGothic-EB", /* DynaLab Inc. 1992-1995 */
188 "DFGyoSho-Lt", /* DynaLab Inc. 1992-1995 */
189 "DFHei", /* DynaLab Inc. 1992-1995 [DFHei-Bd-WIN-HK-BF] */
190 /* covers "DFHei-Md-HK-BF", maybe DynaLab Inc. */
191
192 "DFHSGothic-W5", /* DynaLab Inc. 1992-1995 */
193 "DFHSMincho-W3", /* DynaLab Inc. 1992-1995 */
194 "DFHSMincho-W7", /* DynaLab Inc. 1992-1995 */
195 "DFKaiSho-SB", /* dfkaisb.ttf */
196 "DFKaiShu", /* covers "DFKaiShu-Md-HK-BF", maybe DynaLab Inc. */
197 "DFKai-SB", /* kaiu.ttf; version 3.00, 1998 [DFKaiShu-SB-Estd-BF] */
198
199 "DFMing", /* DynaLab Inc. 1992-1995 [DFMing-Md-WIN-HK-BF] */
200 /* covers "DFMing-Bd-HK-BF", maybe DynaLab Inc. */
201
202 "DLC", /* dftt-m7.ttf; version 1.00, 1993 [DLCMingBold] */
203 /* dftt-f5.ttf; version 1.00, 1993 [DLCFongSung] */
204 /* covers following */
205 /* "DLCHayMedium", dftt-b5.ttf; version 1.00, 1993 */
206 /* "DLCHayBold", dftt-b7.ttf; version 1.00, 1993 */
207 /* "DLCKaiMedium", dftt-k5.ttf; version 1.00, 1992 */
208 /* "DLCLiShu", dftt-l5.ttf; version 1.00, 1992 */
209 /* "DLCRoundBold", dftt-r7.ttf; version 1.00, 1993 */
210
211 "HuaTianKaiTi?", /* htkt2.ttf */
212 "HuaTianSongTi?", /* htst3.ttf */
213 "Ming(for ISO10646)", /* hkscsiic.ttf; version 0.12, 2007 [Ming] */
214 /* iicore.ttf; version 0.07, 2007 [Ming] */
215 "MingLiU", /* mingliu.ttf */
216 /* mingliu.ttc; version 3.21, 2001 */
217 "MingMedium", /* dftt-m5.ttf; version 1.00, 1993 [DLCMingMedium] */
218 "PMingLiU", /* mingliu.ttc; version 3.21, 2001 */
219 "MingLi43", /* mingli.ttf; version 1.00, 1992 */
220 };
221
222 int nn;
223 const FT_String* name_without_tag;
224
225
226 name_without_tag = tt_skip_pdffont_random_tag( name );
227 for ( nn = 0; nn < TRICK_NAMES_COUNT; nn++ )
228 if ( ft_strstr( name_without_tag, trick_names[nn] ) )
229 return TRUE;
230
231 return FALSE;
232 }
233
234
235 /* XXX: This function should be in the `sfnt' module. */
236
237 /* Some PDF generators clear the checksums in the TrueType header table. */
238 /* For example, Quartz ContextPDF clears all entries, or Bullzip PDF */
239 /* Printer clears the entries for subsetted subtables. We thus have to */
240 /* recalculate the checksums where necessary. */
241
242 static FT_UInt32
243 tt_synth_sfnt_checksum( FT_Stream stream,
244 FT_ULong length )
245 {
246 FT_Error error;
247 FT_UInt32 checksum = 0;
248 FT_Byte* p;
249 FT_Int shift;
250
251
252 if ( FT_FRAME_ENTER( length ) )
253 return 0;
254
255 p = (FT_Byte*)stream->cursor;
256
257 for ( ; length > 3; length -= 4 )
258 checksum += FT_NEXT_ULONG( p );
259
260 for ( shift = 24; length > 0; length--, shift -=8 )
261 checksum += (FT_UInt32)FT_NEXT_BYTE( p ) << shift;
262
263 FT_FRAME_EXIT();
264
265 return checksum;
266 }
267
268
269 /* XXX: This function should be in the `sfnt' module. */
270
271 static FT_ULong
272 tt_get_sfnt_checksum( TT_Face face,
273 FT_UShort i )
274 {
275#if 0 /* if we believe the written value, use following part. */
276 if ( face->dir_tables[i].CheckSum )
277 return face->dir_tables[i].CheckSum;
278#endif
279
280 if ( !face->goto_table )
281 return 0;
282
283 if ( face->goto_table( face,
284 face->dir_tables[i].Tag,
285 face->root.stream,
286 NULL ) )
287 return 0;
288
289 return (FT_ULong)tt_synth_sfnt_checksum( face->root.stream,
290 face->dir_tables[i].Length );
291 }
292
293
294 typedef struct tt_sfnt_id_rec_
295 {
296 FT_ULong CheckSum;
297 FT_ULong Length;
298
299 } tt_sfnt_id_rec;
300
301
302 static FT_Bool
303 tt_check_trickyness_sfnt_ids( TT_Face face )
304 {
305#define TRICK_SFNT_IDS_PER_FACE 3
306#define TRICK_SFNT_IDS_NUM_FACES 31
307
308 static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES]
309 [TRICK_SFNT_IDS_PER_FACE] =
310 {
311
312#define TRICK_SFNT_ID_cvt 0
313#define TRICK_SFNT_ID_fpgm 1
314#define TRICK_SFNT_ID_prep 2
315
316 { /* MingLiU 1995 */
317 { 0x05BCF058UL, 0x000002E4UL }, /* cvt */
318 { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */
319 { 0xA344A1EAUL, 0x000001E1UL } /* prep */
320 },
321 { /* MingLiU 1996- */
322 { 0x05BCF058UL, 0x000002E4UL }, /* cvt */
323 { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */
324 { 0xA344A1EBUL, 0x000001E1UL } /* prep */
325 },
326 { /* DFGothic-EB */
327 { 0x12C3EBB2UL, 0x00000350UL }, /* cvt */
328 { 0xB680EE64UL, 0x000087A7UL }, /* fpgm */
329 { 0xCE939563UL, 0x00000758UL } /* prep */
330 },
331 { /* DFGyoSho-Lt */
332 { 0x11E5EAD4UL, 0x00000350UL }, /* cvt */
333 { 0xCE5956E9UL, 0x0000BC85UL }, /* fpgm */
334 { 0x8272F416UL, 0x00000045UL } /* prep */
335 },
336 { /* DFHei-Md-HK-BF */
337 { 0x1257EB46UL, 0x00000350UL }, /* cvt */
338 { 0xF699D160UL, 0x0000715FUL }, /* fpgm */
339 { 0xD222F568UL, 0x000003BCUL } /* prep */
340 },
341 { /* DFHSGothic-W5 */
342 { 0x1262EB4EUL, 0x00000350UL }, /* cvt */
343 { 0xE86A5D64UL, 0x00007940UL }, /* fpgm */
344 { 0x7850F729UL, 0x000005FFUL } /* prep */
345 },
346 { /* DFHSMincho-W3 */
347 { 0x122DEB0AUL, 0x00000350UL }, /* cvt */
348 { 0x3D16328AUL, 0x0000859BUL }, /* fpgm */
349 { 0xA93FC33BUL, 0x000002CBUL } /* prep */
350 },
351 { /* DFHSMincho-W7 */
352 { 0x125FEB26UL, 0x00000350UL }, /* cvt */
353 { 0xA5ACC982UL, 0x00007EE1UL }, /* fpgm */
354 { 0x90999196UL, 0x0000041FUL } /* prep */
355 },
356 { /* DFKaiShu */
357 { 0x11E5EAD4UL, 0x00000350UL }, /* cvt */
358 { 0x5A30CA3BUL, 0x00009063UL }, /* fpgm */
359 { 0x13A42602UL, 0x0000007EUL } /* prep */
360 },
361 { /* DFKaiShu, variant */
362 { 0x11E5EAD4UL, 0x00000350UL }, /* cvt */
363 { 0xA6E78C01UL, 0x00008998UL }, /* fpgm */
364 { 0x13A42602UL, 0x0000007EUL } /* prep */
365 },
366 { /* DFKaiShu-Md-HK-BF */
367 { 0x11E5EAD4UL, 0x00000360UL }, /* cvt */
368 { 0x9DB282B2UL, 0x0000C06EUL }, /* fpgm */
369 { 0x53E6D7CAUL, 0x00000082UL } /* prep */
370 },
371 { /* DFMing-Bd-HK-BF */
372 { 0x1243EB18UL, 0x00000350UL }, /* cvt */
373 { 0xBA0A8C30UL, 0x000074ADUL }, /* fpgm */
374 { 0xF3D83409UL, 0x0000037BUL } /* prep */
375 },
376 { /* DLCLiShu */
377 { 0x07DCF546UL, 0x00000308UL }, /* cvt */
378 { 0x40FE7C90UL, 0x00008E2AUL }, /* fpgm */
379 { 0x608174B5UL, 0x0000007AUL } /* prep */
380 },
381 { /* DLCHayBold */
382 { 0xEB891238UL, 0x00000308UL }, /* cvt */
383 { 0xD2E4DCD4UL, 0x0000676FUL }, /* fpgm */
384 { 0x8EA5F293UL, 0x000003B8UL } /* prep */
385 },
386 { /* HuaTianKaiTi */
387 { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt */
388 { 0x9C9E48B8UL, 0x0000BEA2UL }, /* fpgm */
389 { 0x70020112UL, 0x00000008UL } /* prep */
390 },
391 { /* HuaTianSongTi */
392 { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt */
393 { 0x0A5A0483UL, 0x00017C39UL }, /* fpgm */
394 { 0x70020112UL, 0x00000008UL } /* prep */
395 },
396 { /* NEC fadpop7.ttf */
397 { 0x00000000UL, 0x00000000UL }, /* cvt */
398 { 0x40C92555UL, 0x000000E5UL }, /* fpgm */
399 { 0xA39B58E3UL, 0x0000117CUL } /* prep */
400 },
401 { /* NEC fadrei5.ttf */
402 { 0x00000000UL, 0x00000000UL }, /* cvt */
403 { 0x33C41652UL, 0x000000E5UL }, /* fpgm */
404 { 0x26D6C52AUL, 0x00000F6AUL } /* prep */
405 },
406 { /* NEC fangot7.ttf */
407 { 0x00000000UL, 0x00000000UL }, /* cvt */
408 { 0x6DB1651DUL, 0x0000019DUL }, /* fpgm */
409 { 0x6C6E4B03UL, 0x00002492UL } /* prep */
410 },
411 { /* NEC fangyo5.ttf */
412 { 0x00000000UL, 0x00000000UL }, /* cvt */
413 { 0x40C92555UL, 0x000000E5UL }, /* fpgm */
414 { 0xDE51FAD0UL, 0x0000117CUL } /* prep */
415 },
416 { /* NEC fankyo5.ttf */
417 { 0x00000000UL, 0x00000000UL }, /* cvt */
418 { 0x85E47664UL, 0x000000E5UL }, /* fpgm */
419 { 0xA6C62831UL, 0x00001CAAUL } /* prep */
420 },
421 { /* NEC fanrgo5.ttf */
422 { 0x00000000UL, 0x00000000UL }, /* cvt */
423 { 0x2D891CFDUL, 0x0000019DUL }, /* fpgm */
424 { 0xA0604633UL, 0x00001DE8UL } /* prep */
425 },
426 { /* NEC fangot5.ttc */
427 { 0x00000000UL, 0x00000000UL }, /* cvt */
428 { 0x40AA774CUL, 0x000001CBUL }, /* fpgm */
429 { 0x9B5CAA96UL, 0x00001F9AUL } /* prep */
430 },
431 { /* NEC fanmin3.ttc */
432 { 0x00000000UL, 0x00000000UL }, /* cvt */
433 { 0x0D3DE9CBUL, 0x00000141UL }, /* fpgm */
434 { 0xD4127766UL, 0x00002280UL } /* prep */
435 },
436 { /* NEC FA-Gothic, 1996 */
437 { 0x00000000UL, 0x00000000UL }, /* cvt */
438 { 0x4A692698UL, 0x000001F0UL }, /* fpgm */
439 { 0x340D4346UL, 0x00001FCAUL } /* prep */
440 },
441 { /* NEC FA-Minchou, 1996 */
442 { 0x00000000UL, 0x00000000UL }, /* cvt */
443 { 0xCD34C604UL, 0x00000166UL }, /* fpgm */
444 { 0x6CF31046UL, 0x000022B0UL } /* prep */
445 },
446 { /* NEC FA-RoundGothicB, 1996 */
447 { 0x00000000UL, 0x00000000UL }, /* cvt */
448 { 0x5DA75315UL, 0x0000019DUL }, /* fpgm */
449 { 0x40745A5FUL, 0x000022E0UL } /* prep */
450 },
451 { /* NEC FA-RoundGothicM, 1996 */
452 { 0x00000000UL, 0x00000000UL }, /* cvt */
453 { 0xF055FC48UL, 0x000001C2UL }, /* fpgm */
454 { 0x3900DED3UL, 0x00001E18UL } /* prep */
455 },
456 { /* MINGLI.TTF, 1992 */
457 { 0x00170003UL, 0x00000060UL }, /* cvt */
458 { 0xDBB4306EUL, 0x000058AAUL }, /* fpgm */
459 { 0xD643482AUL, 0x00000035UL } /* prep */
460 },
461 { /* DFHei-Bd-WIN-HK-BF, issue #1087 */
462 { 0x1269EB58UL, 0x00000350UL }, /* cvt */
463 { 0x5CD5957AUL, 0x00006A4EUL }, /* fpgm */
464 { 0xF758323AUL, 0x00000380UL } /* prep */
465 },
466 { /* DFMing-Md-WIN-HK-BF, issue #1087 */
467 { 0x122FEB0BUL, 0x00000350UL }, /* cvt */
468 { 0x7F10919AUL, 0x000070A9UL }, /* fpgm */
469 { 0x7CD7E7B7UL, 0x0000025CUL } /* prep */
470 }
471 };
472
473 FT_ULong checksum;
474 int num_matched_ids[TRICK_SFNT_IDS_NUM_FACES];
475 FT_Bool has_cvt, has_fpgm, has_prep;
476 FT_UShort i;
477 int j, k;
478
479
480 FT_ARRAY_ZERO( num_matched_ids, TRICK_SFNT_IDS_NUM_FACES );
481 has_cvt = FALSE;
482 has_fpgm = FALSE;
483 has_prep = FALSE;
484
485 for ( i = 0; i < face->num_tables; i++ )
486 {
487 checksum = 0;
488
489 switch( face->dir_tables[i].Tag )
490 {
491 case TTAG_cvt:
492 k = TRICK_SFNT_ID_cvt;
493 has_cvt = TRUE;
494 break;
495
496 case TTAG_fpgm:
497 k = TRICK_SFNT_ID_fpgm;
498 has_fpgm = TRUE;
499 break;
500
501 case TTAG_prep:
502 k = TRICK_SFNT_ID_prep;
503 has_prep = TRUE;
504 break;
505
506 default:
507 continue;
508 }
509
510 for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ )
511 if ( face->dir_tables[i].Length == sfnt_id[j][k].Length )
512 {
513 if ( !checksum )
514 checksum = tt_get_sfnt_checksum( face, i );
515
516 if ( sfnt_id[j][k].CheckSum == checksum )
517 num_matched_ids[j]++;
518
519 if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE )
520 return TRUE;
521 }
522 }
523
524 for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ )
525 {
526 if ( !has_cvt && !sfnt_id[j][TRICK_SFNT_ID_cvt].Length )
527 num_matched_ids[j]++;
528 if ( !has_fpgm && !sfnt_id[j][TRICK_SFNT_ID_fpgm].Length )
529 num_matched_ids[j]++;
530 if ( !has_prep && !sfnt_id[j][TRICK_SFNT_ID_prep].Length )
531 num_matched_ids[j]++;
532 if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE )
533 return TRUE;
534 }
535
536 return FALSE;
537 }
538
539
540 static FT_Bool
541 tt_check_trickyness( FT_Face face )
542 {
543 if ( !face )
544 return FALSE;
545
546 /* For first, check the face name for quick check. */
547 if ( face->family_name &&
548 tt_check_trickyness_family( face->family_name ) )
549 {
550 FT_TRACE3(( "found as a tricky font"
551 " by its family name: %s\n", face->family_name ));
552 return TRUE;
553 }
554
555 /* Type42 fonts may lack `name' tables, we thus try to identify */
556 /* tricky fonts by checking the checksums of Type42-persistent */
557 /* sfnt tables (`cvt', `fpgm', and `prep'). */
558 if ( tt_check_trickyness_sfnt_ids( (TT_Face)face ) )
559 {
560 FT_TRACE3(( "found as a tricky font"
561 " by its cvt/fpgm/prep table checksum\n" ));
562 return TRUE;
563 }
564
565 return FALSE;
566 }
567
568#endif /* TT_USE_BYTECODE_INTERPRETER */
569
570
571 /* Check whether `.notdef' is the only glyph in the `loca' table. */
572 static FT_Bool
573 tt_check_single_notdef( FT_Face ttface )
574 {
575 FT_Bool result = FALSE;
576
577 TT_Face face = (TT_Face)ttface;
578 FT_ULong asize;
579 FT_ULong i;
580 FT_ULong glyph_index = 0;
581 FT_UInt count = 0;
582
583
584 for( i = 0; i < face->num_locations; i++ )
585 {
586 tt_face_get_location( ttface, i, &asize );
587 if ( asize > 0 )
588 {
589 count += 1;
590 if ( count > 1 )
591 break;
592 glyph_index = i;
593 }
594 }
595
596 /* Only have a single outline. */
597 if ( count == 1 )
598 {
599 if ( glyph_index == 0 )
600 result = TRUE;
601 else
602 {
603 /* FIXME: Need to test glyphname == .notdef ? */
604 FT_Error error;
605 char buf[8];
606
607
608 error = FT_Get_Glyph_Name( ttface, glyph_index, buf, 8 );
609 if ( !error &&
610 buf[0] == '.' && !ft_strncmp( buf, ".notdef", 8 ) )
611 result = TRUE;
612 }
613 }
614
615 return result;
616 }
617
618
619 /**************************************************************************
620 *
621 * @Function:
622 * tt_face_init
623 *
624 * @Description:
625 * Initialize a given TrueType face object.
626 *
627 * @Input:
628 * stream ::
629 * The source font stream.
630 *
631 * face_index ::
632 * The index of the TrueType font, if we are opening a
633 * collection, in bits 0-15. The numbered instance
634 * index~+~1 of a GX (sub)font, if applicable, in bits
635 * 16-30.
636 *
637 * num_params ::
638 * Number of additional generic parameters. Ignored.
639 *
640 * params ::
641 * Additional generic parameters. Ignored.
642 *
643 * @InOut:
644 * face ::
645 * The newly built face object.
646 *
647 * @Return:
648 * FreeType error code. 0 means success.
649 */
650 FT_LOCAL_DEF( FT_Error )
651 tt_face_init( FT_Stream stream,
652 FT_Face ttface, /* TT_Face */
653 FT_Int face_index,
654 FT_Int num_params,
655 FT_Parameter* params )
656 {
657 FT_Error error;
658 FT_Library library;
659 SFNT_Service sfnt;
660 TT_Face face = (TT_Face)ttface;
661
662
663 FT_TRACE2(( "TTF driver\n" ));
664
665 library = ttface->driver->root.library;
666
667 sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );
668 if ( !sfnt )
669 {
670 FT_ERROR(( "tt_face_init: cannot access `sfnt' module\n" ));
671 error = FT_THROW( Missing_Module );
672 goto Exit;
673 }
674
675 /* create input stream from resource */
676 if ( FT_STREAM_SEEK( 0 ) )
677 goto Exit;
678
679 /* check that we have a valid TrueType file */
680 FT_TRACE2(( " " ));
681 error = sfnt->init_face( stream, face, face_index, num_params, params );
682
683 /* Stream may have changed. */
684 stream = face->root.stream;
685
686 if ( error )
687 goto Exit;
688
689 /* We must also be able to accept Mac/GX fonts, as well as OT ones. */
690 /* The 0x00020000 tag is completely undocumented; some fonts from */
691 /* Arphic made for Chinese Windows 3.1 have this. */
692 if ( face->format_tag != 0x00010000L && /* MS fonts */
693 face->format_tag != 0x00020000L && /* CJK fonts for Win 3.1 */
694 face->format_tag != TTAG_true && /* Mac fonts */
695 face->format_tag != TTAG_0xA5kbd && /* `Keyboard.dfont' (legacy Mac OS X) */
696 face->format_tag != TTAG_0xA5lst ) /* `LastResort.dfont' (legacy Mac OS X) */
697 {
698 FT_TRACE2(( " not a TTF font\n" ));
699 goto Bad_Format;
700 }
701
702#ifdef TT_USE_BYTECODE_INTERPRETER
703 ttface->face_flags |= FT_FACE_FLAG_HINTER;
704#endif
705
706 /* If we are performing a simple font format check, exit immediately. */
707 if ( face_index < 0 )
708 return FT_Err_Ok;
709
710 /* Load font directory */
711 error = sfnt->load_face( stream, face, face_index, num_params, params );
712 if ( error )
713 goto Exit;
714
715#ifdef TT_USE_BYTECODE_INTERPRETER
716 if ( tt_check_trickyness( ttface ) )
717 ttface->face_flags |= FT_FACE_FLAG_TRICKY;
718#endif
719
720 error = tt_face_load_hdmx( face, stream );
721 if ( error )
722 goto Exit;
723
724 if ( FT_IS_SCALABLE( ttface ) ||
725 FT_HAS_SBIX( ttface ) )
726 {
727#ifdef FT_CONFIG_OPTION_INCREMENTAL
728 if ( !ttface->internal->incremental_interface )
729#endif
730 {
731 error = tt_face_load_loca( face, stream );
732
733 /* having a (non-zero) `glyf' table without */
734 /* a `loca' table is not valid */
735 if ( face->glyf_len && FT_ERR_EQ( error, Table_Missing ) )
736 goto Exit;
737 if ( error )
738 goto Exit;
739 }
740
741 /* `fpgm', `cvt', and `prep' are optional */
742 error = tt_face_load_cvt( face, stream );
743 if ( error && FT_ERR_NEQ( error, Table_Missing ) )
744 goto Exit;
745
746 error = tt_face_load_fpgm( face, stream );
747 if ( error && FT_ERR_NEQ( error, Table_Missing ) )
748 goto Exit;
749
750 error = tt_face_load_prep( face, stream );
751 if ( error && FT_ERR_NEQ( error, Table_Missing ) )
752 goto Exit;
753
754 /* Check the scalable flag based on `loca'. */
755#ifdef FT_CONFIG_OPTION_INCREMENTAL
756 if ( !ttface->internal->incremental_interface )
757#endif
758 {
759 if ( ttface->num_fixed_sizes &&
760 face->glyph_locations &&
761 tt_check_single_notdef( ttface ) )
762 {
763 FT_TRACE5(( "tt_face_init:"
764 " Only the `.notdef' glyph has an outline.\n" ));
765 FT_TRACE5(( " "
766 " Resetting scalable flag to FALSE.\n" ));
767
768 ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
769 }
770 }
771 }
772
773#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
774 {
775 FT_UInt instance_index = (FT_UInt)face_index >> 16;
776
777
778 if ( instance_index && FT_HAS_MULTIPLE_MASTERS( ttface ) )
779 {
780 error = FT_Set_Named_Instance( ttface, instance_index );
781 if ( error )
782 goto Exit;
783 }
784 }
785#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
786
787 /* initialize standard glyph loading routines */
788 TT_Init_Glyph_Loading( face );
789
790 Exit:
791 return error;
792
793 Bad_Format:
794 error = FT_THROW( Unknown_File_Format );
795 goto Exit;
796 }
797
798
799 /**************************************************************************
800 *
801 * @Function:
802 * tt_face_done
803 *
804 * @Description:
805 * Finalize a given face object.
806 *
807 * @Input:
808 * face ::
809 * A pointer to the face object to destroy.
810 */
811 FT_LOCAL_DEF( void )
812 tt_face_done( FT_Face ttface ) /* TT_Face */
813 {
814 TT_Face face = (TT_Face)ttface;
815 FT_Memory memory;
816 FT_Stream stream;
817 SFNT_Service sfnt;
818
819
820 if ( !face )
821 return;
822
823 memory = ttface->memory;
824 stream = ttface->stream;
825 sfnt = (SFNT_Service)face->sfnt;
826
827 /* for `extended TrueType formats' (i.e. compressed versions) */
828 if ( face->extra.finalizer )
829 face->extra.finalizer( face->extra.data );
830
831 if ( sfnt )
832 sfnt->done_face( face );
833
834 /* freeing the locations table */
835 tt_face_done_loca( face );
836
837 tt_face_free_hdmx( face );
838
839 /* freeing the CVT */
840 FT_FREE( face->cvt );
841 face->cvt_size = 0;
842
843 /* freeing the programs */
844 FT_FRAME_RELEASE( face->font_program );
845 FT_FRAME_RELEASE( face->cvt_program );
846 face->font_program_size = 0;
847 face->cvt_program_size = 0;
848
849#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
850 tt_done_blend( ttface );
851 face->blend = NULL;
852#endif
853 }
854
855
856 /**************************************************************************
857 *
858 * SIZE FUNCTIONS
859 *
860 */
861
862#ifdef TT_USE_BYTECODE_INTERPRETER
863
864 /**************************************************************************
865 *
866 * @Function:
867 * tt_size_run_fpgm
868 *
869 * @Description:
870 * Run the font program.
871 *
872 * @Input:
873 * size ::
874 * A handle to the size object.
875 *
876 * @Return:
877 * FreeType error code. 0 means success.
878 */
879 FT_LOCAL_DEF( FT_Error )
880 tt_size_run_fpgm( TT_Size size )
881 {
882 TT_Face face = (TT_Face)size->root.face;
883 TT_ExecContext exec = size->context;
884 FT_Error error;
885
886
887 error = TT_Load_Context( exec, face, size );
888 if ( error )
889 return error;
890
891 /* disable CVT and glyph programs coderange */
892 TT_Clear_CodeRange( exec, tt_coderange_cvt );
893 TT_Clear_CodeRange( exec, tt_coderange_glyph );
894
895 if ( face->font_program_size > 0 )
896 {
897 /* allow font program execution */
898 TT_Set_CodeRange( exec,
899 tt_coderange_font,
900 face->font_program,
901 (FT_Long)face->font_program_size );
902
903 exec->pts.n_points = 0;
904 exec->pts.n_contours = 0;
905
906 FT_TRACE4(( "Executing `fpgm' table.\n" ));
907 error = TT_Run_Context( exec, size );
908 FT_TRACE4(( error ? " failed (error code 0x%x)\n" : "",
909 error ));
910 }
911 else
912 error = FT_Err_Ok;
913
914 size->bytecode_ready = error;
915
916 if ( !error )
917 TT_Save_Context( exec, size );
918
919 return error;
920 }
921
922
923 /**************************************************************************
924 *
925 * @Function:
926 * tt_size_run_prep
927 *
928 * @Description:
929 * Run the control value program.
930 *
931 * @Input:
932 * size ::
933 * A handle to the size object.
934 *
935 * @Return:
936 * FreeType error code. 0 means success.
937 */
938 FT_LOCAL_DEF( FT_Error )
939 tt_size_run_prep( TT_Size size )
940 {
941 TT_Face face = (TT_Face)size->root.face;
942 TT_ExecContext exec = size->context;
943 FT_Error error;
944 FT_UInt i;
945
946
947 /* set default GS, twilight points, and storage */
948 /* before CV program can modify them. */
949 size->GS = tt_default_graphics_state;
950
951 /* all twilight points are originally zero */
952 FT_ARRAY_ZERO( size->twilight.org, size->twilight.n_points );
953 FT_ARRAY_ZERO( size->twilight.cur, size->twilight.n_points );
954
955 error = TT_Load_Context( exec, face, size );
956 if ( error )
957 return error;
958
959 /* clear storage area */
960 FT_ARRAY_ZERO( exec->storage, exec->storeSize );
961
962 /* Scale the cvt values to the new ppem. */
963 /* By default, we use the y ppem value for scaling. */
964 FT_TRACE6(( "CVT values:\n" ));
965 for ( i = 0; i < exec->cvtSize; i++ )
966 {
967 /* Unscaled CVT values are already stored in 26.6 format. */
968 /* Note that this scaling operation is very sensitive to rounding; */
969 /* the integer division by 64 must be applied to the first argument. */
970 exec->cvt[i] = FT_MulFix( face->cvt[i] / 64, size->ttmetrics.scale );
971 FT_TRACE6(( " %3u: %f (%f)\n",
972 i, (double)face->cvt[i] / 64, (double)exec->cvt[i] / 64 ));
973 }
974 FT_TRACE6(( "\n" ));
975
976 TT_Clear_CodeRange( exec, tt_coderange_glyph );
977
978 if ( face->cvt_program_size > 0 )
979 {
980 /* allow CV program execution */
981 TT_Set_CodeRange( exec,
982 tt_coderange_cvt,
983 face->cvt_program,
984 (FT_Long)face->cvt_program_size );
985
986 exec->pts.n_points = 0;
987 exec->pts.n_contours = 0;
988
989 FT_TRACE4(( "Executing `prep' table.\n" ));
990 error = TT_Run_Context( exec, size );
991 FT_TRACE4(( error ? " failed (error code 0x%x)\n" : "",
992 error ));
993 }
994 else
995 error = FT_Err_Ok;
996
997 size->cvt_ready = error;
998
999 if ( !error )
1000 TT_Save_Context( exec, size );
1001
1002 return error;
1003 }
1004
1005
1006 static void
1007 tt_size_done_bytecode( TT_Size size )
1008 {
1009 FT_Memory memory = size->root.face->memory;
1010 TT_ExecContext exec = size->context;
1011
1012
1013 if ( exec )
1014 {
1015 FT_FREE( exec->stack );
1016 FT_FREE( exec->FDefs );
1017
1018 TT_Done_Context( exec );
1019 size->context = NULL;
1020 }
1021
1022 /* twilight zone */
1023 tt_glyphzone_done( memory, &size->twilight );
1024 }
1025
1026
1027 /* Initialize bytecode-related fields in the size object. */
1028 /* We do this only if bytecode interpretation is really needed. */
1029 FT_LOCAL_DEF( FT_Error )
1030 tt_size_init_bytecode( TT_Size size,
1031 FT_Bool pedantic )
1032 {
1033 FT_Error error;
1034 TT_Face face = (TT_Face)size->root.face;
1035 FT_Memory memory = size->root.face->memory;
1036
1037 FT_UShort n_twilight;
1038 TT_MaxProfile* maxp = &face->max_profile;
1039 TT_ExecContext exec;
1040
1041
1042 exec = TT_New_Context( (TT_Driver)face->root.driver );
1043 if ( !exec )
1044 return FT_THROW( Could_Not_Find_Context );
1045
1046 exec->pedantic_hinting = pedantic;
1047
1048 exec->maxFDefs = maxp->maxFunctionDefs;
1049 exec->maxIDefs = maxp->maxInstructionDefs;
1050
1051 if ( FT_NEW_ARRAY( exec->FDefs, exec->maxFDefs + exec->maxIDefs ) )
1052 goto Exit;
1053
1054 exec->IDefs = exec->FDefs + exec->maxFDefs;
1055
1056 exec->numFDefs = 0;
1057 exec->numIDefs = 0;
1058
1059 exec->maxFunc = 0;
1060 exec->maxIns = 0;
1061
1062 /* XXX: We reserve a little more elements on the stack to deal */
1063 /* with broken fonts like arialbs, courbs, timesbs, etc. */
1064 exec->stackSize = maxp->maxStackElements + 32;
1065 exec->storeSize = maxp->maxStorage;
1066 exec->cvtSize = face->cvt_size;
1067
1068 if ( FT_NEW_ARRAY( exec->stack,
1069 exec->stackSize +
1070 (FT_Long)( exec->storeSize + exec->cvtSize ) ) )
1071 goto Exit;
1072
1073 /* reserve twilight zone and set GS before fpgm is executed, */
1074 /* just in case, even though fpgm should not touch them */
1075 n_twilight = maxp->maxTwilightPoints;
1076
1077 /* there are 4 phantom points (do we need this?) */
1078 n_twilight += 4;
1079
1080 error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight );
1081 if ( error )
1082 goto Exit;
1083
1084 size->GS = tt_default_graphics_state;
1085 size->cvt_ready = -1;
1086 size->context = exec;
1087
1088 size->ttmetrics.rotated = FALSE;
1089 size->ttmetrics.stretched = FALSE;
1090
1091 /* Fine, now run the font program! */
1092
1093 /* In case of an error while executing `fpgm', we intentionally don't */
1094 /* clean up immediately – bugs in the `fpgm' are so fundamental that */
1095 /* all following hinting calls should fail. Additionally, `fpgm' is */
1096 /* to be executed just once; calling it again is completely useless */
1097 /* and might even lead to extremely slow behaviour if it is malformed */
1098 /* (containing an infinite loop, for example). */
1099 error = tt_size_run_fpgm( size );
1100 return error;
1101
1102 Exit:
1103 if ( error )
1104 tt_size_done_bytecode( size );
1105
1106 return error;
1107 }
1108
1109#endif /* TT_USE_BYTECODE_INTERPRETER */
1110
1111
1112 /**************************************************************************
1113 *
1114 * @Function:
1115 * tt_size_init
1116 *
1117 * @Description:
1118 * Initialize a new TrueType size object.
1119 *
1120 * @InOut:
1121 * size ::
1122 * A handle to the size object.
1123 *
1124 * @Return:
1125 * FreeType error code. 0 means success.
1126 */
1127 FT_LOCAL_DEF( FT_Error )
1128 tt_size_init( FT_Size ttsize ) /* TT_Size */
1129 {
1130 TT_Size size = (TT_Size)ttsize;
1131 FT_Error error = FT_Err_Ok;
1132
1133
1134#ifdef TT_USE_BYTECODE_INTERPRETER
1135 size->bytecode_ready = -1;
1136#endif
1137
1138 size->strike_index = 0xFFFFFFFFUL;
1139
1140 return error;
1141 }
1142
1143
1144 /**************************************************************************
1145 *
1146 * @Function:
1147 * tt_size_done
1148 *
1149 * @Description:
1150 * The TrueType size object finalizer.
1151 *
1152 * @Input:
1153 * size ::
1154 * A handle to the target size object.
1155 */
1156 FT_LOCAL_DEF( void )
1157 tt_size_done( FT_Size ttsize ) /* TT_Size */
1158 {
1159#ifdef TT_USE_BYTECODE_INTERPRETER
1160 tt_size_done_bytecode( (TT_Size)ttsize );
1161#else
1162 FT_UNUSED( ttsize );
1163#endif
1164 }
1165
1166
1167 /**************************************************************************
1168 *
1169 * @Function:
1170 * tt_size_reset_height
1171 *
1172 * @Description:
1173 * Recompute a TrueType size's ascender, descender, and height
1174 * when resolutions and character dimensions have been changed.
1175 * Used for variation fonts as an iterator function.
1176 *
1177 * @Input:
1178 * ft_size ::
1179 * A handle to the target TT_Size object. This function will be called
1180 * through a `FT_Size_Reset_Func` pointer which takes `FT_Size`. This
1181 * function must take `FT_Size` as a result. The passed `FT_Size` is
1182 * expected to point to a `TT_Size`.
1183 */
1184 FT_LOCAL_DEF( void )
1185 tt_size_reset_height( FT_Size ft_size )
1186 {
1187 TT_Size size = (TT_Size)ft_size;
1188 TT_Face face = (TT_Face)ft_size->face;
1189 FT_Size_Metrics* size_metrics = &size->hinted_metrics;
1190
1191 /* This bit flag, if set, indicates that the ppems must be */
1192 /* rounded to integers. Nearly all TrueType fonts have this bit */
1193 /* set, as hinting won't work really well otherwise. */
1194 /* */
1195 if ( face->header.Flags & 8 )
1196 {
1197 /* the TT spec always asks for ROUND, not FLOOR or CEIL */
1198 size_metrics->ascender = FT_PIX_ROUND(
1199 FT_MulFix( face->root.ascender,
1200 size_metrics->y_scale ) );
1201 size_metrics->descender = FT_PIX_ROUND(
1202 FT_MulFix( face->root.descender,
1203 size_metrics->y_scale ) );
1204 size_metrics->height = FT_PIX_ROUND(
1205 FT_MulFix( face->root.height,
1206 size_metrics->y_scale ) );
1207 }
1208 }
1209
1210
1211 /**************************************************************************
1212 *
1213 * @Function:
1214 * tt_size_reset
1215 *
1216 * @Description:
1217 * Reset a TrueType size when resolutions and character dimensions
1218 * have been changed.
1219 *
1220 * @Input:
1221 * size ::
1222 * A handle to the target size object.
1223 */
1224 FT_LOCAL_DEF( FT_Error )
1225 tt_size_reset( TT_Size size )
1226 {
1227 TT_Face face = (TT_Face)size->root.face;
1228 FT_Size_Metrics* size_metrics = &size->hinted_metrics;
1229
1230
1231 /* invalidate the size object first */
1232 size->ttmetrics.ppem = 0;
1233
1234 if ( size->root.metrics.x_ppem == 0 || size->root.metrics.y_ppem == 0 )
1235 return FT_THROW( Invalid_PPem );
1236
1237 /* copy the result from base layer */
1238 *size_metrics = size->root.metrics;
1239
1240 tt_size_reset_height( (FT_Size)size );
1241
1242 if ( face->header.Flags & 8 )
1243 {
1244 /* base scaling values on integer ppem values, */
1245 /* as mandated by the TrueType specification */
1246 size_metrics->x_scale = FT_DivFix( size_metrics->x_ppem << 6,
1247 face->root.units_per_EM );
1248 size_metrics->y_scale = FT_DivFix( size_metrics->y_ppem << 6,
1249 face->root.units_per_EM );
1250
1251 size_metrics->max_advance = FT_PIX_ROUND(
1252 FT_MulFix( face->root.max_advance_width,
1253 size_metrics->x_scale ) );
1254 }
1255
1256 /* compute new transformation */
1257 if ( size_metrics->x_ppem >= size_metrics->y_ppem )
1258 {
1259 size->ttmetrics.scale = size_metrics->x_scale;
1260 size->ttmetrics.ppem = size_metrics->x_ppem;
1261 size->ttmetrics.x_ratio = 0x10000L;
1262 size->ttmetrics.y_ratio = FT_DivFix( size_metrics->y_ppem,
1263 size_metrics->x_ppem );
1264 }
1265 else
1266 {
1267 size->ttmetrics.scale = size_metrics->y_scale;
1268 size->ttmetrics.ppem = size_metrics->y_ppem;
1269 size->ttmetrics.x_ratio = FT_DivFix( size_metrics->x_ppem,
1270 size_metrics->y_ppem );
1271 size->ttmetrics.y_ratio = 0x10000L;
1272 }
1273
1274 size->widthp = tt_face_get_device_metrics( face, size_metrics->x_ppem, 0 );
1275
1276 size->metrics = size_metrics;
1277
1278#ifdef TT_USE_BYTECODE_INTERPRETER
1279 size->cvt_ready = -1;
1280#endif /* TT_USE_BYTECODE_INTERPRETER */
1281
1282 return FT_Err_Ok;
1283 }
1284
1285
1286 /**************************************************************************
1287 *
1288 * @Function:
1289 * tt_driver_init
1290 *
1291 * @Description:
1292 * Initialize a given TrueType driver object.
1293 *
1294 * @Input:
1295 * driver ::
1296 * A handle to the target driver object.
1297 *
1298 * @Return:
1299 * FreeType error code. 0 means success.
1300 */
1301 FT_LOCAL_DEF( FT_Error )
1302 tt_driver_init( FT_Module ttdriver ) /* TT_Driver */
1303 {
1304
1305#ifdef TT_USE_BYTECODE_INTERPRETER
1306
1307 TT_Driver driver = (TT_Driver)ttdriver;
1308
1309 driver->interpreter_version = TT_INTERPRETER_VERSION_35;
1310#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
1311 driver->interpreter_version = TT_INTERPRETER_VERSION_40;
1312#endif
1313
1314#else /* !TT_USE_BYTECODE_INTERPRETER */
1315
1316 FT_UNUSED( ttdriver );
1317
1318#endif /* !TT_USE_BYTECODE_INTERPRETER */
1319
1320 return FT_Err_Ok;
1321 }
1322
1323
1324 /**************************************************************************
1325 *
1326 * @Function:
1327 * tt_driver_done
1328 *
1329 * @Description:
1330 * Finalize a given TrueType driver.
1331 *
1332 * @Input:
1333 * driver ::
1334 * A handle to the target TrueType driver.
1335 */
1336 FT_LOCAL_DEF( void )
1337 tt_driver_done( FT_Module ttdriver ) /* TT_Driver */
1338 {
1339 FT_UNUSED( ttdriver );
1340 }
1341
1342
1343 /**************************************************************************
1344 *
1345 * @Function:
1346 * tt_slot_init
1347 *
1348 * @Description:
1349 * Initialize a new slot object.
1350 *
1351 * @InOut:
1352 * slot ::
1353 * A handle to the slot object.
1354 *
1355 * @Return:
1356 * FreeType error code. 0 means success.
1357 */
1358 FT_LOCAL_DEF( FT_Error )
1359 tt_slot_init( FT_GlyphSlot slot )
1360 {
1361 return FT_GlyphLoader_CreateExtra( slot->internal->loader );
1362 }
1363
1364
1365/* END */