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