Bug 1690340 - Part 1: Hide all the panel tools in the developer tools menu. r=jdescottes
[gecko.git] / modules / freetype2 / src / truetype / ttobjs.c
blob06d45695597b1d027b03daf583d8c26b69bfbf79
1 /****************************************************************************
3 * ttobjs.c
5 * Objects manager (body).
7 * Copyright (C) 1996-2020 by
8 * David Turner, Robert Wilhelm, and Werner Lemberg.
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.
19 #include <freetype/internal/ftdebug.h>
20 #include <freetype/internal/ftstream.h>
21 #include <freetype/tttags.h>
22 #include <freetype/internal/sfnt.h>
23 #include <freetype/ftdriver.h>
25 #include "ttgload.h"
26 #include "ttpload.h"
28 #include "tterrors.h"
30 #ifdef TT_USE_BYTECODE_INTERPRETER
31 #include "ttinterp.h"
32 #endif
34 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
35 #include "ttgxvar.h"
36 #endif
38 /**************************************************************************
40 * The macro FT_COMPONENT is used in trace mode. It is an implicit
41 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
42 * messages during execution.
44 #undef FT_COMPONENT
45 #define FT_COMPONENT ttobjs
48 #ifdef TT_USE_BYTECODE_INTERPRETER
50 /**************************************************************************
52 * GLYPH ZONE FUNCTIONS
57 /**************************************************************************
59 * @Function:
60 * tt_glyphzone_done
62 * @Description:
63 * Deallocate a glyph zone.
65 * @Input:
66 * zone ::
67 * A pointer to the target glyph zone.
69 FT_LOCAL_DEF( void )
70 tt_glyphzone_done( TT_GlyphZone zone )
72 FT_Memory memory = zone->memory;
75 if ( memory )
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 );
83 zone->max_points = zone->n_points = 0;
84 zone->max_contours = zone->n_contours = 0;
85 zone->memory = NULL;
90 /**************************************************************************
92 * @Function:
93 * tt_glyphzone_new
95 * @Description:
96 * Allocate a new glyph zone.
98 * @Input:
99 * memory ::
100 * A handle to the current memory object.
102 * maxPoints ::
103 * The capacity of glyph zone in points.
105 * maxContours ::
106 * The capacity of glyph zone in contours.
108 * @Output:
109 * zone ::
110 * A pointer to the target glyph zone record.
112 * @Return:
113 * FreeType error code. 0 means success.
115 FT_LOCAL_DEF( FT_Error )
116 tt_glyphzone_new( FT_Memory memory,
117 FT_UShort maxPoints,
118 FT_Short maxContours,
119 TT_GlyphZone zone )
121 FT_Error error;
124 FT_ZERO( zone );
125 zone->memory = memory;
127 if ( FT_NEW_ARRAY( zone->org, maxPoints ) ||
128 FT_NEW_ARRAY( zone->cur, maxPoints ) ||
129 FT_NEW_ARRAY( zone->orus, maxPoints ) ||
130 FT_NEW_ARRAY( zone->tags, maxPoints ) ||
131 FT_NEW_ARRAY( zone->contours, maxContours ) )
133 tt_glyphzone_done( zone );
135 else
137 zone->max_points = maxPoints;
138 zone->max_contours = maxContours;
141 return error;
143 #endif /* TT_USE_BYTECODE_INTERPRETER */
146 /* Compare the face with a list of well-known `tricky' fonts. */
147 /* This list shall be expanded as we find more of them. */
149 static FT_Bool
150 tt_check_trickyness_family( const FT_String* name )
153 #define TRICK_NAMES_MAX_CHARACTERS 19
154 #define TRICK_NAMES_COUNT 26
156 static const char trick_names[TRICK_NAMES_COUNT]
157 [TRICK_NAMES_MAX_CHARACTERS + 1] =
160 PostScript names are given in brackets if they differ from the
161 family name. The version numbers, together with the copyright or
162 release year data, are taken from fonts available to the
163 developers.
165 Note that later versions of the fonts might be no longer tricky;
166 for example, `MingLiU' version 7.00 (file `mingliu.ttc' from
167 Windows 7) is an ordinary TTC with non-tricky subfonts.
170 "cpop", /* dftt-p7.ttf; version 1.00, 1992 [DLJGyShoMedium] */
171 "DFGirl-W6-WIN-BF", /* dftt-h6.ttf; version 1.00, 1993 */
172 "DFGothic-EB", /* DynaLab Inc. 1992-1995 */
173 "DFGyoSho-Lt", /* DynaLab Inc. 1992-1995 */
174 "DFHei-Md-HK-BF", /* maybe DynaLab Inc. */
175 "DFHSGothic-W5", /* DynaLab Inc. 1992-1995 */
176 "DFHSMincho-W3", /* DynaLab Inc. 1992-1995 */
177 "DFHSMincho-W7", /* DynaLab Inc. 1992-1995 */
178 "DFKaiSho-SB", /* dfkaisb.ttf */
179 "DFKaiShu",
180 "DFKaiShu-Md-HK-BF", /* maybe DynaLab Inc. */
181 "DFKai-SB", /* kaiu.ttf; version 3.00, 1998 [DFKaiShu-SB-Estd-BF] */
182 "DFMing-Bd-HK-BF", /* maybe DynaLab Inc. */
183 "DLC", /* dftt-m7.ttf; version 1.00, 1993 [DLCMingBold] */
184 /* dftt-f5.ttf; version 1.00, 1993 [DLCFongSung] */
185 "DLCHayMedium", /* dftt-b5.ttf; version 1.00, 1993 */
186 "DLCHayBold", /* dftt-b7.ttf; version 1.00, 1993 */
187 "DLCKaiMedium", /* dftt-k5.ttf; version 1.00, 1992 */
188 "DLCLiShu", /* dftt-l5.ttf; version 1.00, 1992 */
189 "DLCRoundBold", /* dftt-r7.ttf; version 1.00, 1993 */
190 "HuaTianKaiTi?", /* htkt2.ttf */
191 "HuaTianSongTi?", /* htst3.ttf */
192 "Ming(for ISO10646)", /* hkscsiic.ttf; version 0.12, 2007 [Ming] */
193 /* iicore.ttf; version 0.07, 2007 [Ming] */
194 "MingLiU", /* mingliu.ttf */
195 /* mingliu.ttc; version 3.21, 2001 */
196 "MingMedium", /* dftt-m5.ttf; version 1.00, 1993 [DLCMingMedium] */
197 "PMingLiU", /* mingliu.ttc; version 3.21, 2001 */
198 "MingLi43", /* mingli.ttf; version 1.00, 1992 */
201 int nn;
204 for ( nn = 0; nn < TRICK_NAMES_COUNT; nn++ )
205 if ( ft_strstr( name, trick_names[nn] ) )
206 return TRUE;
208 return FALSE;
212 /* XXX: This function should be in the `sfnt' module. */
214 /* Some PDF generators clear the checksums in the TrueType header table. */
215 /* For example, Quartz ContextPDF clears all entries, or Bullzip PDF */
216 /* Printer clears the entries for subsetted subtables. We thus have to */
217 /* recalculate the checksums where necessary. */
219 static FT_UInt32
220 tt_synth_sfnt_checksum( FT_Stream stream,
221 FT_ULong length )
223 FT_Error error;
224 FT_UInt32 checksum = 0;
225 FT_UInt i;
228 if ( FT_FRAME_ENTER( length ) )
229 return 0;
231 for ( ; length > 3; length -= 4 )
232 checksum += (FT_UInt32)FT_GET_ULONG();
234 for ( i = 3; length > 0; length--, i-- )
235 checksum += (FT_UInt32)FT_GET_BYTE() << ( i * 8 );
237 FT_FRAME_EXIT();
239 return checksum;
243 /* XXX: This function should be in the `sfnt' module. */
245 static FT_ULong
246 tt_get_sfnt_checksum( TT_Face face,
247 FT_UShort i )
249 #if 0 /* if we believe the written value, use following part. */
250 if ( face->dir_tables[i].CheckSum )
251 return face->dir_tables[i].CheckSum;
252 #endif
254 if ( !face->goto_table )
255 return 0;
257 if ( face->goto_table( face,
258 face->dir_tables[i].Tag,
259 face->root.stream,
260 NULL ) )
261 return 0;
263 return (FT_ULong)tt_synth_sfnt_checksum( face->root.stream,
264 face->dir_tables[i].Length );
268 typedef struct tt_sfnt_id_rec_
270 FT_ULong CheckSum;
271 FT_ULong Length;
273 } tt_sfnt_id_rec;
276 static FT_Bool
277 tt_check_trickyness_sfnt_ids( TT_Face face )
279 #define TRICK_SFNT_IDS_PER_FACE 3
280 #define TRICK_SFNT_IDS_NUM_FACES 29
282 static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES]
283 [TRICK_SFNT_IDS_PER_FACE] = {
285 #define TRICK_SFNT_ID_cvt 0
286 #define TRICK_SFNT_ID_fpgm 1
287 #define TRICK_SFNT_ID_prep 2
289 { /* MingLiU 1995 */
290 { 0x05BCF058UL, 0x000002E4UL }, /* cvt */
291 { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */
292 { 0xA344A1EAUL, 0x000001E1UL } /* prep */
294 { /* MingLiU 1996- */
295 { 0x05BCF058UL, 0x000002E4UL }, /* cvt */
296 { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */
297 { 0xA344A1EBUL, 0x000001E1UL } /* prep */
299 { /* DFGothic-EB */
300 { 0x12C3EBB2UL, 0x00000350UL }, /* cvt */
301 { 0xB680EE64UL, 0x000087A7UL }, /* fpgm */
302 { 0xCE939563UL, 0x00000758UL } /* prep */
304 { /* DFGyoSho-Lt */
305 { 0x11E5EAD4UL, 0x00000350UL }, /* cvt */
306 { 0xCE5956E9UL, 0x0000BC85UL }, /* fpgm */
307 { 0x8272F416UL, 0x00000045UL } /* prep */
309 { /* DFHei-Md-HK-BF */
310 { 0x1257EB46UL, 0x00000350UL }, /* cvt */
311 { 0xF699D160UL, 0x0000715FUL }, /* fpgm */
312 { 0xD222F568UL, 0x000003BCUL } /* prep */
314 { /* DFHSGothic-W5 */
315 { 0x1262EB4EUL, 0x00000350UL }, /* cvt */
316 { 0xE86A5D64UL, 0x00007940UL }, /* fpgm */
317 { 0x7850F729UL, 0x000005FFUL } /* prep */
319 { /* DFHSMincho-W3 */
320 { 0x122DEB0AUL, 0x00000350UL }, /* cvt */
321 { 0x3D16328AUL, 0x0000859BUL }, /* fpgm */
322 { 0xA93FC33BUL, 0x000002CBUL } /* prep */
324 { /* DFHSMincho-W7 */
325 { 0x125FEB26UL, 0x00000350UL }, /* cvt */
326 { 0xA5ACC982UL, 0x00007EE1UL }, /* fpgm */
327 { 0x90999196UL, 0x0000041FUL } /* prep */
329 { /* DFKaiShu */
330 { 0x11E5EAD4UL, 0x00000350UL }, /* cvt */
331 { 0x5A30CA3BUL, 0x00009063UL }, /* fpgm */
332 { 0x13A42602UL, 0x0000007EUL } /* prep */
334 { /* DFKaiShu, variant */
335 { 0x11E5EAD4UL, 0x00000350UL }, /* cvt */
336 { 0xA6E78C01UL, 0x00008998UL }, /* fpgm */
337 { 0x13A42602UL, 0x0000007EUL } /* prep */
339 { /* DFKaiShu-Md-HK-BF */
340 { 0x11E5EAD4UL, 0x00000360UL }, /* cvt */
341 { 0x9DB282B2UL, 0x0000C06EUL }, /* fpgm */
342 { 0x53E6D7CAUL, 0x00000082UL } /* prep */
344 { /* DFMing-Bd-HK-BF */
345 { 0x1243EB18UL, 0x00000350UL }, /* cvt */
346 { 0xBA0A8C30UL, 0x000074ADUL }, /* fpgm */
347 { 0xF3D83409UL, 0x0000037BUL } /* prep */
349 { /* DLCLiShu */
350 { 0x07DCF546UL, 0x00000308UL }, /* cvt */
351 { 0x40FE7C90UL, 0x00008E2AUL }, /* fpgm */
352 { 0x608174B5UL, 0x0000007AUL } /* prep */
354 { /* DLCHayBold */
355 { 0xEB891238UL, 0x00000308UL }, /* cvt */
356 { 0xD2E4DCD4UL, 0x0000676FUL }, /* fpgm */
357 { 0x8EA5F293UL, 0x000003B8UL } /* prep */
359 { /* HuaTianKaiTi */
360 { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt */
361 { 0x9C9E48B8UL, 0x0000BEA2UL }, /* fpgm */
362 { 0x70020112UL, 0x00000008UL } /* prep */
364 { /* HuaTianSongTi */
365 { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt */
366 { 0x0A5A0483UL, 0x00017C39UL }, /* fpgm */
367 { 0x70020112UL, 0x00000008UL } /* prep */
369 { /* NEC fadpop7.ttf */
370 { 0x00000000UL, 0x00000000UL }, /* cvt */
371 { 0x40C92555UL, 0x000000E5UL }, /* fpgm */
372 { 0xA39B58E3UL, 0x0000117CUL } /* prep */
374 { /* NEC fadrei5.ttf */
375 { 0x00000000UL, 0x00000000UL }, /* cvt */
376 { 0x33C41652UL, 0x000000E5UL }, /* fpgm */
377 { 0x26D6C52AUL, 0x00000F6AUL } /* prep */
379 { /* NEC fangot7.ttf */
380 { 0x00000000UL, 0x00000000UL }, /* cvt */
381 { 0x6DB1651DUL, 0x0000019DUL }, /* fpgm */
382 { 0x6C6E4B03UL, 0x00002492UL } /* prep */
384 { /* NEC fangyo5.ttf */
385 { 0x00000000UL, 0x00000000UL }, /* cvt */
386 { 0x40C92555UL, 0x000000E5UL }, /* fpgm */
387 { 0xDE51FAD0UL, 0x0000117CUL } /* prep */
389 { /* NEC fankyo5.ttf */
390 { 0x00000000UL, 0x00000000UL }, /* cvt */
391 { 0x85E47664UL, 0x000000E5UL }, /* fpgm */
392 { 0xA6C62831UL, 0x00001CAAUL } /* prep */
394 { /* NEC fanrgo5.ttf */
395 { 0x00000000UL, 0x00000000UL }, /* cvt */
396 { 0x2D891CFDUL, 0x0000019DUL }, /* fpgm */
397 { 0xA0604633UL, 0x00001DE8UL } /* prep */
399 { /* NEC fangot5.ttc */
400 { 0x00000000UL, 0x00000000UL }, /* cvt */
401 { 0x40AA774CUL, 0x000001CBUL }, /* fpgm */
402 { 0x9B5CAA96UL, 0x00001F9AUL } /* prep */
404 { /* NEC fanmin3.ttc */
405 { 0x00000000UL, 0x00000000UL }, /* cvt */
406 { 0x0D3DE9CBUL, 0x00000141UL }, /* fpgm */
407 { 0xD4127766UL, 0x00002280UL } /* prep */
409 { /* NEC FA-Gothic, 1996 */
410 { 0x00000000UL, 0x00000000UL }, /* cvt */
411 { 0x4A692698UL, 0x000001F0UL }, /* fpgm */
412 { 0x340D4346UL, 0x00001FCAUL } /* prep */
414 { /* NEC FA-Minchou, 1996 */
415 { 0x00000000UL, 0x00000000UL }, /* cvt */
416 { 0xCD34C604UL, 0x00000166UL }, /* fpgm */
417 { 0x6CF31046UL, 0x000022B0UL } /* prep */
419 { /* NEC FA-RoundGothicB, 1996 */
420 { 0x00000000UL, 0x00000000UL }, /* cvt */
421 { 0x5DA75315UL, 0x0000019DUL }, /* fpgm */
422 { 0x40745A5FUL, 0x000022E0UL } /* prep */
424 { /* NEC FA-RoundGothicM, 1996 */
425 { 0x00000000UL, 0x00000000UL }, /* cvt */
426 { 0xF055FC48UL, 0x000001C2UL }, /* fpgm */
427 { 0x3900DED3UL, 0x00001E18UL } /* prep */
429 { /* MINGLI.TTF, 1992 */
430 { 0x00170003UL, 0x00000060UL }, /* cvt */
431 { 0xDBB4306EUL, 0x000058AAUL }, /* fpgm */
432 { 0xD643482AUL, 0x00000035UL } /* prep */
436 FT_ULong checksum;
437 int num_matched_ids[TRICK_SFNT_IDS_NUM_FACES];
438 FT_Bool has_cvt, has_fpgm, has_prep;
439 FT_UShort i;
440 int j, k;
443 FT_MEM_SET( num_matched_ids, 0,
444 sizeof ( int ) * TRICK_SFNT_IDS_NUM_FACES );
445 has_cvt = FALSE;
446 has_fpgm = FALSE;
447 has_prep = FALSE;
449 for ( i = 0; i < face->num_tables; i++ )
451 checksum = 0;
453 switch( face->dir_tables[i].Tag )
455 case TTAG_cvt:
456 k = TRICK_SFNT_ID_cvt;
457 has_cvt = TRUE;
458 break;
460 case TTAG_fpgm:
461 k = TRICK_SFNT_ID_fpgm;
462 has_fpgm = TRUE;
463 break;
465 case TTAG_prep:
466 k = TRICK_SFNT_ID_prep;
467 has_prep = TRUE;
468 break;
470 default:
471 continue;
474 for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ )
475 if ( face->dir_tables[i].Length == sfnt_id[j][k].Length )
477 if ( !checksum )
478 checksum = tt_get_sfnt_checksum( face, i );
480 if ( sfnt_id[j][k].CheckSum == checksum )
481 num_matched_ids[j]++;
483 if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE )
484 return TRUE;
488 for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ )
490 if ( !has_cvt && !sfnt_id[j][TRICK_SFNT_ID_cvt].Length )
491 num_matched_ids[j]++;
492 if ( !has_fpgm && !sfnt_id[j][TRICK_SFNT_ID_fpgm].Length )
493 num_matched_ids[j]++;
494 if ( !has_prep && !sfnt_id[j][TRICK_SFNT_ID_prep].Length )
495 num_matched_ids[j]++;
496 if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE )
497 return TRUE;
500 return FALSE;
504 static FT_Bool
505 tt_check_trickyness( FT_Face face )
507 if ( !face )
508 return FALSE;
510 /* For first, check the face name for quick check. */
511 if ( face->family_name &&
512 tt_check_trickyness_family( face->family_name ) )
513 return TRUE;
515 /* Type42 fonts may lack `name' tables, we thus try to identify */
516 /* tricky fonts by checking the checksums of Type42-persistent */
517 /* sfnt tables (`cvt', `fpgm', and `prep'). */
518 if ( tt_check_trickyness_sfnt_ids( (TT_Face)face ) )
519 return TRUE;
521 return FALSE;
525 /* Check whether `.notdef' is the only glyph in the `loca' table. */
526 static FT_Bool
527 tt_check_single_notdef( FT_Face ttface )
529 FT_Bool result = FALSE;
531 TT_Face face = (TT_Face)ttface;
532 FT_UInt asize;
533 FT_ULong i;
534 FT_ULong glyph_index = 0;
535 FT_UInt count = 0;
538 for( i = 0; i < face->num_locations; i++ )
540 tt_face_get_location( face, i, &asize );
541 if ( asize > 0 )
543 count += 1;
544 if ( count > 1 )
545 break;
546 glyph_index = i;
550 /* Only have a single outline. */
551 if ( count == 1 )
553 if ( glyph_index == 0 )
554 result = TRUE;
555 else
557 /* FIXME: Need to test glyphname == .notdef ? */
558 FT_Error error;
559 char buf[8];
562 error = FT_Get_Glyph_Name( ttface, glyph_index, buf, 8 );
563 if ( !error &&
564 buf[0] == '.' && !ft_strncmp( buf, ".notdef", 8 ) )
565 result = TRUE;
569 return result;
573 /**************************************************************************
575 * @Function:
576 * tt_face_init
578 * @Description:
579 * Initialize a given TrueType face object.
581 * @Input:
582 * stream ::
583 * The source font stream.
585 * face_index ::
586 * The index of the TrueType font, if we are opening a
587 * collection, in bits 0-15. The numbered instance
588 * index~+~1 of a GX (sub)font, if applicable, in bits
589 * 16-30.
591 * num_params ::
592 * Number of additional generic parameters. Ignored.
594 * params ::
595 * Additional generic parameters. Ignored.
597 * @InOut:
598 * face ::
599 * The newly built face object.
601 * @Return:
602 * FreeType error code. 0 means success.
604 FT_LOCAL_DEF( FT_Error )
605 tt_face_init( FT_Stream stream,
606 FT_Face ttface, /* TT_Face */
607 FT_Int face_index,
608 FT_Int num_params,
609 FT_Parameter* params )
611 FT_Error error;
612 FT_Library library;
613 SFNT_Service sfnt;
614 TT_Face face = (TT_Face)ttface;
617 FT_TRACE2(( "TTF driver\n" ));
619 library = ttface->driver->root.library;
621 sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );
622 if ( !sfnt )
624 FT_ERROR(( "tt_face_init: cannot access `sfnt' module\n" ));
625 error = FT_THROW( Missing_Module );
626 goto Exit;
629 /* create input stream from resource */
630 if ( FT_STREAM_SEEK( 0 ) )
631 goto Exit;
633 /* check that we have a valid TrueType file */
634 FT_TRACE2(( " " ));
635 error = sfnt->init_face( stream, face, face_index, num_params, params );
637 /* Stream may have changed. */
638 stream = face->root.stream;
640 if ( error )
641 goto Exit;
643 /* We must also be able to accept Mac/GX fonts, as well as OT ones. */
644 /* The 0x00020000 tag is completely undocumented; some fonts from */
645 /* Arphic made for Chinese Windows 3.1 have this. */
646 if ( face->format_tag != 0x00010000L && /* MS fonts */
647 face->format_tag != 0x00020000L && /* CJK fonts for Win 3.1 */
648 face->format_tag != TTAG_true && /* Mac fonts */
649 face->format_tag != TTAG_0xA5kbd && /* `Keyboard.dfont' (legacy Mac OS X) */
650 face->format_tag != TTAG_0xA5lst ) /* `LastResort.dfont' (legacy Mac OS X) */
652 FT_TRACE2(( " not a TTF font\n" ));
653 goto Bad_Format;
656 #ifdef TT_USE_BYTECODE_INTERPRETER
657 ttface->face_flags |= FT_FACE_FLAG_HINTER;
658 #endif
660 /* If we are performing a simple font format check, exit immediately. */
661 if ( face_index < 0 )
662 return FT_Err_Ok;
664 /* Load font directory */
665 error = sfnt->load_face( stream, face, face_index, num_params, params );
666 if ( error )
667 goto Exit;
669 if ( tt_check_trickyness( ttface ) )
670 ttface->face_flags |= FT_FACE_FLAG_TRICKY;
672 error = tt_face_load_hdmx( face, stream );
673 if ( error )
674 goto Exit;
676 if ( FT_IS_SCALABLE( ttface ) )
678 #ifdef FT_CONFIG_OPTION_INCREMENTAL
679 if ( !ttface->internal->incremental_interface )
680 #endif
682 error = tt_face_load_loca( face, stream );
684 /* having a (non-zero) `glyf' table without */
685 /* a `loca' table is not valid */
686 if ( face->glyf_len && FT_ERR_EQ( error, Table_Missing ) )
687 goto Exit;
688 if ( error )
689 goto Exit;
692 /* `fpgm', `cvt', and `prep' are optional */
693 error = tt_face_load_cvt( face, stream );
694 if ( error && FT_ERR_NEQ( error, Table_Missing ) )
695 goto Exit;
697 error = tt_face_load_fpgm( face, stream );
698 if ( error && FT_ERR_NEQ( error, Table_Missing ) )
699 goto Exit;
701 error = tt_face_load_prep( face, stream );
702 if ( error && FT_ERR_NEQ( error, Table_Missing ) )
703 goto Exit;
705 /* Check the scalable flag based on `loca'. */
706 #ifdef FT_CONFIG_OPTION_INCREMENTAL
707 if ( !ttface->internal->incremental_interface )
708 #endif
710 if ( ttface->num_fixed_sizes &&
711 face->glyph_locations &&
712 tt_check_single_notdef( ttface ) )
714 FT_TRACE5(( "tt_face_init:"
715 " Only the `.notdef' glyph has an outline.\n"
717 " Resetting scalable flag to FALSE.\n" ));
719 ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
724 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
727 FT_UInt instance_index = (FT_UInt)face_index >> 16;
730 if ( FT_HAS_MULTIPLE_MASTERS( ttface ) &&
731 instance_index > 0 )
733 error = TT_Set_Named_Instance( face, instance_index );
734 if ( error )
735 goto Exit;
737 tt_apply_mvar( face );
741 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
743 /* initialize standard glyph loading routines */
744 TT_Init_Glyph_Loading( face );
746 Exit:
747 return error;
749 Bad_Format:
750 error = FT_THROW( Unknown_File_Format );
751 goto Exit;
755 /**************************************************************************
757 * @Function:
758 * tt_face_done
760 * @Description:
761 * Finalize a given face object.
763 * @Input:
764 * face ::
765 * A pointer to the face object to destroy.
767 FT_LOCAL_DEF( void )
768 tt_face_done( FT_Face ttface ) /* TT_Face */
770 TT_Face face = (TT_Face)ttface;
771 FT_Memory memory;
772 FT_Stream stream;
773 SFNT_Service sfnt;
776 if ( !face )
777 return;
779 memory = ttface->memory;
780 stream = ttface->stream;
781 sfnt = (SFNT_Service)face->sfnt;
783 /* for `extended TrueType formats' (i.e. compressed versions) */
784 if ( face->extra.finalizer )
785 face->extra.finalizer( face->extra.data );
787 if ( sfnt )
788 sfnt->done_face( face );
790 /* freeing the locations table */
791 tt_face_done_loca( face );
793 tt_face_free_hdmx( face );
795 /* freeing the CVT */
796 FT_FREE( face->cvt );
797 face->cvt_size = 0;
799 /* freeing the programs */
800 FT_FRAME_RELEASE( face->font_program );
801 FT_FRAME_RELEASE( face->cvt_program );
802 face->font_program_size = 0;
803 face->cvt_program_size = 0;
805 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
806 tt_done_blend( face );
807 face->blend = NULL;
808 #endif
812 /**************************************************************************
814 * SIZE FUNCTIONS
818 #ifdef TT_USE_BYTECODE_INTERPRETER
820 /**************************************************************************
822 * @Function:
823 * tt_size_run_fpgm
825 * @Description:
826 * Run the font program.
828 * @Input:
829 * size ::
830 * A handle to the size object.
832 * pedantic ::
833 * Set if bytecode execution should be pedantic.
835 * @Return:
836 * FreeType error code. 0 means success.
838 FT_LOCAL_DEF( FT_Error )
839 tt_size_run_fpgm( TT_Size size,
840 FT_Bool pedantic )
842 TT_Face face = (TT_Face)size->root.face;
843 TT_ExecContext exec;
844 FT_Error error;
847 exec = size->context;
849 error = TT_Load_Context( exec, face, size );
850 if ( error )
851 return error;
853 exec->callTop = 0;
854 exec->top = 0;
856 exec->period = 64;
857 exec->phase = 0;
858 exec->threshold = 0;
860 exec->instruction_trap = FALSE;
861 exec->F_dot_P = 0x4000L;
863 exec->pedantic_hinting = pedantic;
866 FT_Size_Metrics* size_metrics = &exec->metrics;
867 TT_Size_Metrics* tt_metrics = &exec->tt_metrics;
870 size_metrics->x_ppem = 0;
871 size_metrics->y_ppem = 0;
872 size_metrics->x_scale = 0;
873 size_metrics->y_scale = 0;
875 tt_metrics->ppem = 0;
876 tt_metrics->scale = 0;
877 tt_metrics->ratio = 0x10000L;
880 /* allow font program execution */
881 TT_Set_CodeRange( exec,
882 tt_coderange_font,
883 face->font_program,
884 (FT_Long)face->font_program_size );
886 /* disable CVT and glyph programs coderange */
887 TT_Clear_CodeRange( exec, tt_coderange_cvt );
888 TT_Clear_CodeRange( exec, tt_coderange_glyph );
890 if ( face->font_program_size > 0 )
892 TT_Goto_CodeRange( exec, tt_coderange_font, 0 );
894 FT_TRACE4(( "Executing `fpgm' table.\n" ));
895 error = face->interpreter( exec );
896 #ifdef FT_DEBUG_LEVEL_TRACE
897 if ( error )
898 FT_TRACE4(( " interpretation failed with error code 0x%x\n",
899 error ));
900 #endif
902 else
903 error = FT_Err_Ok;
905 size->bytecode_ready = error;
907 if ( !error )
908 TT_Save_Context( exec, size );
910 return error;
914 /**************************************************************************
916 * @Function:
917 * tt_size_run_prep
919 * @Description:
920 * Run the control value program.
922 * @Input:
923 * size ::
924 * A handle to the size object.
926 * pedantic ::
927 * Set if bytecode execution should be pedantic.
929 * @Return:
930 * FreeType error code. 0 means success.
932 FT_LOCAL_DEF( FT_Error )
933 tt_size_run_prep( TT_Size size,
934 FT_Bool pedantic )
936 TT_Face face = (TT_Face)size->root.face;
937 TT_ExecContext exec;
938 FT_Error error;
939 FT_UInt i;
941 /* unscaled CVT values are already stored in 26.6 format */
942 FT_Fixed scale = size->ttmetrics.scale >> 6;
945 /* Scale the cvt values to the new ppem. */
946 /* By default, we use the y ppem value for scaling. */
947 FT_TRACE6(( "CVT values:\n" ));
948 for ( i = 0; i < size->cvt_size; i++ )
950 size->cvt[i] = FT_MulFix( face->cvt[i], scale );
951 FT_TRACE6(( " %3d: %f (%f)\n",
952 i, face->cvt[i] / 64.0, size->cvt[i] / 64.0 ));
954 FT_TRACE6(( "\n" ));
956 exec = size->context;
958 error = TT_Load_Context( exec, face, size );
959 if ( error )
960 return error;
962 exec->callTop = 0;
963 exec->top = 0;
965 exec->instruction_trap = FALSE;
967 exec->pedantic_hinting = pedantic;
969 TT_Set_CodeRange( exec,
970 tt_coderange_cvt,
971 face->cvt_program,
972 (FT_Long)face->cvt_program_size );
974 TT_Clear_CodeRange( exec, tt_coderange_glyph );
976 if ( face->cvt_program_size > 0 )
978 TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 );
980 FT_TRACE4(( "Executing `prep' table.\n" ));
981 error = face->interpreter( exec );
982 #ifdef FT_DEBUG_LEVEL_TRACE
983 if ( error )
984 FT_TRACE4(( " interpretation failed with error code 0x%x\n",
985 error ));
986 #endif
988 else
989 error = FT_Err_Ok;
991 size->cvt_ready = error;
993 /* UNDOCUMENTED! The MS rasterizer doesn't allow the following */
994 /* graphics state variables to be modified by the CVT program. */
996 exec->GS.dualVector.x = 0x4000;
997 exec->GS.dualVector.y = 0;
998 exec->GS.projVector.x = 0x4000;
999 exec->GS.projVector.y = 0x0;
1000 exec->GS.freeVector.x = 0x4000;
1001 exec->GS.freeVector.y = 0x0;
1003 exec->GS.rp0 = 0;
1004 exec->GS.rp1 = 0;
1005 exec->GS.rp2 = 0;
1007 exec->GS.gep0 = 1;
1008 exec->GS.gep1 = 1;
1009 exec->GS.gep2 = 1;
1011 exec->GS.loop = 1;
1013 /* save as default graphics state */
1014 size->GS = exec->GS;
1016 TT_Save_Context( exec, size );
1018 return error;
1022 static void
1023 tt_size_done_bytecode( FT_Size ftsize )
1025 TT_Size size = (TT_Size)ftsize;
1026 TT_Face face = (TT_Face)ftsize->face;
1027 FT_Memory memory = face->root.memory;
1029 if ( size->context )
1031 TT_Done_Context( size->context );
1032 size->context = NULL;
1035 FT_FREE( size->cvt );
1036 size->cvt_size = 0;
1038 /* free storage area */
1039 FT_FREE( size->storage );
1040 size->storage_size = 0;
1042 /* twilight zone */
1043 tt_glyphzone_done( &size->twilight );
1045 FT_FREE( size->function_defs );
1046 FT_FREE( size->instruction_defs );
1048 size->num_function_defs = 0;
1049 size->max_function_defs = 0;
1050 size->num_instruction_defs = 0;
1051 size->max_instruction_defs = 0;
1053 size->max_func = 0;
1054 size->max_ins = 0;
1056 size->bytecode_ready = -1;
1057 size->cvt_ready = -1;
1061 /* Initialize bytecode-related fields in the size object. */
1062 /* We do this only if bytecode interpretation is really needed. */
1063 static FT_Error
1064 tt_size_init_bytecode( FT_Size ftsize,
1065 FT_Bool pedantic )
1067 FT_Error error;
1068 TT_Size size = (TT_Size)ftsize;
1069 TT_Face face = (TT_Face)ftsize->face;
1070 FT_Memory memory = face->root.memory;
1072 FT_UShort n_twilight;
1073 TT_MaxProfile* maxp = &face->max_profile;
1076 /* clean up bytecode related data */
1077 FT_FREE( size->function_defs );
1078 FT_FREE( size->instruction_defs );
1079 FT_FREE( size->cvt );
1080 FT_FREE( size->storage );
1082 if ( size->context )
1083 TT_Done_Context( size->context );
1084 tt_glyphzone_done( &size->twilight );
1086 size->bytecode_ready = -1;
1087 size->cvt_ready = -1;
1089 size->context = TT_New_Context( (TT_Driver)face->root.driver );
1091 size->max_function_defs = maxp->maxFunctionDefs;
1092 size->max_instruction_defs = maxp->maxInstructionDefs;
1094 size->num_function_defs = 0;
1095 size->num_instruction_defs = 0;
1097 size->max_func = 0;
1098 size->max_ins = 0;
1100 size->cvt_size = face->cvt_size;
1101 size->storage_size = maxp->maxStorage;
1103 /* Set default metrics */
1105 TT_Size_Metrics* tt_metrics = &size->ttmetrics;
1108 tt_metrics->rotated = FALSE;
1109 tt_metrics->stretched = FALSE;
1111 /* Set default engine compensation. Value 3 is not described */
1112 /* in the OpenType specification (as of Mai 2019), but Greg */
1113 /* says that MS handles it the same as `gray'. */
1114 /* */
1115 /* The Apple specification says that the compensation for */
1116 /* `gray' is always zero. FreeType doesn't do any */
1117 /* compensation at all. */
1118 tt_metrics->compensations[0] = 0; /* gray */
1119 tt_metrics->compensations[1] = 0; /* black */
1120 tt_metrics->compensations[2] = 0; /* white */
1121 tt_metrics->compensations[3] = 0; /* zero */
1124 /* allocate function defs, instruction defs, cvt, and storage area */
1125 if ( FT_NEW_ARRAY( size->function_defs, size->max_function_defs ) ||
1126 FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) ||
1127 FT_NEW_ARRAY( size->cvt, size->cvt_size ) ||
1128 FT_NEW_ARRAY( size->storage, size->storage_size ) )
1129 goto Exit;
1131 /* reserve twilight zone */
1132 n_twilight = maxp->maxTwilightPoints;
1134 /* there are 4 phantom points (do we need this?) */
1135 n_twilight += 4;
1137 error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight );
1138 if ( error )
1139 goto Exit;
1141 size->twilight.n_points = n_twilight;
1143 size->GS = tt_default_graphics_state;
1145 /* set `face->interpreter' according to the debug hook present */
1147 FT_Library library = face->root.driver->root.library;
1150 face->interpreter = (TT_Interpreter)
1151 library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE];
1152 if ( !face->interpreter )
1153 face->interpreter = (TT_Interpreter)TT_RunIns;
1156 /* Fine, now run the font program! */
1158 /* In case of an error while executing `fpgm', we intentionally don't */
1159 /* clean up immediately – bugs in the `fpgm' are so fundamental that */
1160 /* all following hinting calls should fail. Additionally, `fpgm' is */
1161 /* to be executed just once; calling it again is completely useless */
1162 /* and might even lead to extremely slow behaviour if it is malformed */
1163 /* (containing an infinite loop, for example). */
1164 error = tt_size_run_fpgm( size, pedantic );
1165 return error;
1167 Exit:
1168 if ( error )
1169 tt_size_done_bytecode( ftsize );
1171 return error;
1175 FT_LOCAL_DEF( FT_Error )
1176 tt_size_ready_bytecode( TT_Size size,
1177 FT_Bool pedantic )
1179 FT_Error error = FT_Err_Ok;
1182 if ( size->bytecode_ready < 0 )
1183 error = tt_size_init_bytecode( (FT_Size)size, pedantic );
1184 else
1185 error = size->bytecode_ready;
1187 if ( error )
1188 goto Exit;
1190 /* rescale CVT when needed */
1191 if ( size->cvt_ready < 0 )
1193 FT_UInt i;
1196 /* all twilight points are originally zero */
1197 for ( i = 0; i < (FT_UInt)size->twilight.n_points; i++ )
1199 size->twilight.org[i].x = 0;
1200 size->twilight.org[i].y = 0;
1201 size->twilight.cur[i].x = 0;
1202 size->twilight.cur[i].y = 0;
1205 /* clear storage area */
1206 for ( i = 0; i < (FT_UInt)size->storage_size; i++ )
1207 size->storage[i] = 0;
1209 size->GS = tt_default_graphics_state;
1211 error = tt_size_run_prep( size, pedantic );
1213 else
1214 error = size->cvt_ready;
1216 Exit:
1217 return error;
1220 #endif /* TT_USE_BYTECODE_INTERPRETER */
1223 /**************************************************************************
1225 * @Function:
1226 * tt_size_init
1228 * @Description:
1229 * Initialize a new TrueType size object.
1231 * @InOut:
1232 * size ::
1233 * A handle to the size object.
1235 * @Return:
1236 * FreeType error code. 0 means success.
1238 FT_LOCAL_DEF( FT_Error )
1239 tt_size_init( FT_Size ttsize ) /* TT_Size */
1241 TT_Size size = (TT_Size)ttsize;
1242 FT_Error error = FT_Err_Ok;
1245 #ifdef TT_USE_BYTECODE_INTERPRETER
1246 size->bytecode_ready = -1;
1247 size->cvt_ready = -1;
1248 #endif
1250 size->ttmetrics.valid = FALSE;
1251 size->strike_index = 0xFFFFFFFFUL;
1253 return error;
1257 /**************************************************************************
1259 * @Function:
1260 * tt_size_done
1262 * @Description:
1263 * The TrueType size object finalizer.
1265 * @Input:
1266 * size ::
1267 * A handle to the target size object.
1269 FT_LOCAL_DEF( void )
1270 tt_size_done( FT_Size ttsize ) /* TT_Size */
1272 TT_Size size = (TT_Size)ttsize;
1275 #ifdef TT_USE_BYTECODE_INTERPRETER
1276 tt_size_done_bytecode( ttsize );
1277 #endif
1279 size->ttmetrics.valid = FALSE;
1283 /**************************************************************************
1285 * @Function:
1286 * tt_size_reset
1288 * @Description:
1289 * Reset a TrueType size when resolutions and character dimensions
1290 * have been changed.
1292 * @Input:
1293 * size ::
1294 * A handle to the target size object.
1296 * only_height ::
1297 * Only recompute ascender, descender, and height;
1298 * this flag is used for variation fonts where
1299 * `tt_size_reset' is used as an iterator function.
1301 FT_LOCAL_DEF( FT_Error )
1302 tt_size_reset( TT_Size size,
1303 FT_Bool only_height )
1305 TT_Face face;
1306 FT_Size_Metrics* size_metrics;
1309 face = (TT_Face)size->root.face;
1311 /* nothing to do for CFF2 */
1312 if ( face->is_cff2 )
1313 return FT_Err_Ok;
1315 size->ttmetrics.valid = FALSE;
1317 size_metrics = &size->hinted_metrics;
1319 /* copy the result from base layer */
1320 *size_metrics = size->root.metrics;
1322 if ( size_metrics->x_ppem < 1 || size_metrics->y_ppem < 1 )
1323 return FT_THROW( Invalid_PPem );
1325 /* This bit flag, if set, indicates that the ppems must be */
1326 /* rounded to integers. Nearly all TrueType fonts have this bit */
1327 /* set, as hinting won't work really well otherwise. */
1328 /* */
1329 if ( face->header.Flags & 8 )
1331 /* the TT spec always asks for ROUND, not FLOOR or CEIL */
1332 size_metrics->ascender = FT_PIX_ROUND(
1333 FT_MulFix( face->root.ascender,
1334 size_metrics->y_scale ) );
1335 size_metrics->descender = FT_PIX_ROUND(
1336 FT_MulFix( face->root.descender,
1337 size_metrics->y_scale ) );
1338 size_metrics->height = FT_PIX_ROUND(
1339 FT_MulFix( face->root.height,
1340 size_metrics->y_scale ) );
1343 size->ttmetrics.valid = TRUE;
1345 if ( only_height )
1347 /* we must not recompute the scaling values here since */
1348 /* `tt_size_reset' was already called (with only_height = 0) */
1349 return FT_Err_Ok;
1352 if ( face->header.Flags & 8 )
1354 /* base scaling values on integer ppem values, */
1355 /* as mandated by the TrueType specification */
1356 size_metrics->x_scale = FT_DivFix( size_metrics->x_ppem << 6,
1357 face->root.units_per_EM );
1358 size_metrics->y_scale = FT_DivFix( size_metrics->y_ppem << 6,
1359 face->root.units_per_EM );
1361 size_metrics->max_advance = FT_PIX_ROUND(
1362 FT_MulFix( face->root.max_advance_width,
1363 size_metrics->x_scale ) );
1366 /* compute new transformation */
1367 if ( size_metrics->x_ppem >= size_metrics->y_ppem )
1369 size->ttmetrics.scale = size_metrics->x_scale;
1370 size->ttmetrics.ppem = size_metrics->x_ppem;
1371 size->ttmetrics.x_ratio = 0x10000L;
1372 size->ttmetrics.y_ratio = FT_DivFix( size_metrics->y_ppem,
1373 size_metrics->x_ppem );
1375 else
1377 size->ttmetrics.scale = size_metrics->y_scale;
1378 size->ttmetrics.ppem = size_metrics->y_ppem;
1379 size->ttmetrics.x_ratio = FT_DivFix( size_metrics->x_ppem,
1380 size_metrics->y_ppem );
1381 size->ttmetrics.y_ratio = 0x10000L;
1384 size->metrics = size_metrics;
1386 #ifdef TT_USE_BYTECODE_INTERPRETER
1387 size->cvt_ready = -1;
1388 #endif /* TT_USE_BYTECODE_INTERPRETER */
1390 return FT_Err_Ok;
1394 /**************************************************************************
1396 * @Function:
1397 * tt_driver_init
1399 * @Description:
1400 * Initialize a given TrueType driver object.
1402 * @Input:
1403 * driver ::
1404 * A handle to the target driver object.
1406 * @Return:
1407 * FreeType error code. 0 means success.
1409 FT_LOCAL_DEF( FT_Error )
1410 tt_driver_init( FT_Module ttdriver ) /* TT_Driver */
1413 #ifdef TT_USE_BYTECODE_INTERPRETER
1415 TT_Driver driver = (TT_Driver)ttdriver;
1417 driver->interpreter_version = TT_INTERPRETER_VERSION_35;
1418 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
1419 driver->interpreter_version = TT_INTERPRETER_VERSION_38;
1420 #endif
1421 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
1422 driver->interpreter_version = TT_INTERPRETER_VERSION_40;
1423 #endif
1425 #else /* !TT_USE_BYTECODE_INTERPRETER */
1427 FT_UNUSED( ttdriver );
1429 #endif /* !TT_USE_BYTECODE_INTERPRETER */
1431 return FT_Err_Ok;
1435 /**************************************************************************
1437 * @Function:
1438 * tt_driver_done
1440 * @Description:
1441 * Finalize a given TrueType driver.
1443 * @Input:
1444 * driver ::
1445 * A handle to the target TrueType driver.
1447 FT_LOCAL_DEF( void )
1448 tt_driver_done( FT_Module ttdriver ) /* TT_Driver */
1450 FT_UNUSED( ttdriver );
1454 /**************************************************************************
1456 * @Function:
1457 * tt_slot_init
1459 * @Description:
1460 * Initialize a new slot object.
1462 * @InOut:
1463 * slot ::
1464 * A handle to the slot object.
1466 * @Return:
1467 * FreeType error code. 0 means success.
1469 FT_LOCAL_DEF( FT_Error )
1470 tt_slot_init( FT_GlyphSlot slot )
1472 return FT_GlyphLoader_CreateExtra( slot->internal->loader );
1476 /* END */