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