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