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