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