• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define TRICK_SFNT_ID_cvt   0
318 #define TRICK_SFNT_ID_fpgm  1
319 #define TRICK_SFNT_ID_prep  2
320 
321       { /* MingLiU 1995 */
322         { 0x05BCF058UL, 0x000002E4UL }, /* cvt  */
323         { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */
324         { 0xA344A1EAUL, 0x000001E1UL }  /* prep */
325       },
326       { /* MingLiU 1996- */
327         { 0x05BCF058UL, 0x000002E4UL }, /* cvt  */
328         { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */
329         { 0xA344A1EBUL, 0x000001E1UL }  /* prep */
330       },
331       { /* DFGothic-EB */
332         { 0x12C3EBB2UL, 0x00000350UL }, /* cvt  */
333         { 0xB680EE64UL, 0x000087A7UL }, /* fpgm */
334         { 0xCE939563UL, 0x00000758UL }  /* prep */
335       },
336       { /* DFGyoSho-Lt */
337         { 0x11E5EAD4UL, 0x00000350UL }, /* cvt  */
338         { 0xCE5956E9UL, 0x0000BC85UL }, /* fpgm */
339         { 0x8272F416UL, 0x00000045UL }  /* prep */
340       },
341       { /* DFHei-Md-HK-BF */
342         { 0x1257EB46UL, 0x00000350UL }, /* cvt  */
343         { 0xF699D160UL, 0x0000715FUL }, /* fpgm */
344         { 0xD222F568UL, 0x000003BCUL }  /* prep */
345       },
346       { /* DFHSGothic-W5 */
347         { 0x1262EB4EUL, 0x00000350UL }, /* cvt  */
348         { 0xE86A5D64UL, 0x00007940UL }, /* fpgm */
349         { 0x7850F729UL, 0x000005FFUL }  /* prep */
350       },
351       { /* DFHSMincho-W3 */
352         { 0x122DEB0AUL, 0x00000350UL }, /* cvt  */
353         { 0x3D16328AUL, 0x0000859BUL }, /* fpgm */
354         { 0xA93FC33BUL, 0x000002CBUL }  /* prep */
355       },
356       { /* DFHSMincho-W7 */
357         { 0x125FEB26UL, 0x00000350UL }, /* cvt  */
358         { 0xA5ACC982UL, 0x00007EE1UL }, /* fpgm */
359         { 0x90999196UL, 0x0000041FUL }  /* prep */
360       },
361       { /* DFKaiShu */
362         { 0x11E5EAD4UL, 0x00000350UL }, /* cvt  */
363         { 0x5A30CA3BUL, 0x00009063UL }, /* fpgm */
364         { 0x13A42602UL, 0x0000007EUL }  /* prep */
365       },
366       { /* DFKaiShu, variant */
367         { 0x11E5EAD4UL, 0x00000350UL }, /* cvt  */
368         { 0xA6E78C01UL, 0x00008998UL }, /* fpgm */
369         { 0x13A42602UL, 0x0000007EUL }  /* prep */
370       },
371       { /* DFKaiShu-Md-HK-BF */
372         { 0x11E5EAD4UL, 0x00000360UL }, /* cvt  */
373         { 0x9DB282B2UL, 0x0000C06EUL }, /* fpgm */
374         { 0x53E6D7CAUL, 0x00000082UL }  /* prep */
375       },
376       { /* DFMing-Bd-HK-BF */
377         { 0x1243EB18UL, 0x00000350UL }, /* cvt  */
378         { 0xBA0A8C30UL, 0x000074ADUL }, /* fpgm */
379         { 0xF3D83409UL, 0x0000037BUL }  /* prep */
380       },
381       { /* DLCLiShu */
382         { 0x07DCF546UL, 0x00000308UL }, /* cvt  */
383         { 0x40FE7C90UL, 0x00008E2AUL }, /* fpgm */
384         { 0x608174B5UL, 0x0000007AUL }  /* prep */
385       },
386       { /* DLCHayBold */
387         { 0xEB891238UL, 0x00000308UL }, /* cvt  */
388         { 0xD2E4DCD4UL, 0x0000676FUL }, /* fpgm */
389         { 0x8EA5F293UL, 0x000003B8UL }  /* prep */
390       },
391       { /* HuaTianKaiTi */
392         { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt  */
393         { 0x9C9E48B8UL, 0x0000BEA2UL }, /* fpgm */
394         { 0x70020112UL, 0x00000008UL }  /* prep */
395       },
396       { /* HuaTianSongTi */
397         { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt  */
398         { 0x0A5A0483UL, 0x00017C39UL }, /* fpgm */
399         { 0x70020112UL, 0x00000008UL }  /* prep */
400       },
401       { /* NEC fadpop7.ttf */
402         { 0x00000000UL, 0x00000000UL }, /* cvt  */
403         { 0x40C92555UL, 0x000000E5UL }, /* fpgm */
404         { 0xA39B58E3UL, 0x0000117CUL }  /* prep */
405       },
406       { /* NEC fadrei5.ttf */
407         { 0x00000000UL, 0x00000000UL }, /* cvt  */
408         { 0x33C41652UL, 0x000000E5UL }, /* fpgm */
409         { 0x26D6C52AUL, 0x00000F6AUL }  /* prep */
410       },
411       { /* NEC fangot7.ttf */
412         { 0x00000000UL, 0x00000000UL }, /* cvt  */
413         { 0x6DB1651DUL, 0x0000019DUL }, /* fpgm */
414         { 0x6C6E4B03UL, 0x00002492UL }  /* prep */
415       },
416       { /* NEC fangyo5.ttf */
417         { 0x00000000UL, 0x00000000UL }, /* cvt  */
418         { 0x40C92555UL, 0x000000E5UL }, /* fpgm */
419         { 0xDE51FAD0UL, 0x0000117CUL }  /* prep */
420       },
421       { /* NEC fankyo5.ttf */
422         { 0x00000000UL, 0x00000000UL }, /* cvt  */
423         { 0x85E47664UL, 0x000000E5UL }, /* fpgm */
424         { 0xA6C62831UL, 0x00001CAAUL }  /* prep */
425       },
426       { /* NEC fanrgo5.ttf */
427         { 0x00000000UL, 0x00000000UL }, /* cvt  */
428         { 0x2D891CFDUL, 0x0000019DUL }, /* fpgm */
429         { 0xA0604633UL, 0x00001DE8UL }  /* prep */
430       },
431       { /* NEC fangot5.ttc */
432         { 0x00000000UL, 0x00000000UL }, /* cvt  */
433         { 0x40AA774CUL, 0x000001CBUL }, /* fpgm */
434         { 0x9B5CAA96UL, 0x00001F9AUL }  /* prep */
435       },
436       { /* NEC fanmin3.ttc */
437         { 0x00000000UL, 0x00000000UL }, /* cvt  */
438         { 0x0D3DE9CBUL, 0x00000141UL }, /* fpgm */
439         { 0xD4127766UL, 0x00002280UL }  /* prep */
440       },
441       { /* NEC FA-Gothic, 1996 */
442         { 0x00000000UL, 0x00000000UL }, /* cvt  */
443         { 0x4A692698UL, 0x000001F0UL }, /* fpgm */
444         { 0x340D4346UL, 0x00001FCAUL }  /* prep */
445       },
446       { /* NEC FA-Minchou, 1996 */
447         { 0x00000000UL, 0x00000000UL }, /* cvt  */
448         { 0xCD34C604UL, 0x00000166UL }, /* fpgm */
449         { 0x6CF31046UL, 0x000022B0UL }  /* prep */
450       },
451       { /* NEC FA-RoundGothicB, 1996 */
452         { 0x00000000UL, 0x00000000UL }, /* cvt  */
453         { 0x5DA75315UL, 0x0000019DUL }, /* fpgm */
454         { 0x40745A5FUL, 0x000022E0UL }  /* prep */
455       },
456       { /* NEC FA-RoundGothicM, 1996 */
457         { 0x00000000UL, 0x00000000UL }, /* cvt  */
458         { 0xF055FC48UL, 0x000001C2UL }, /* fpgm */
459         { 0x3900DED3UL, 0x00001E18UL }  /* prep */
460       },
461         { /* MINGLI.TTF, 1992 */
462         { 0x00170003UL, 0x00000060UL }, /* cvt  */
463         { 0xDBB4306EUL, 0x000058AAUL }, /* fpgm */
464         { 0xD643482AUL, 0x00000035UL }  /* prep */
465       },
466         { /* DFHei-Bd-WIN-HK-BF, issue #1087 */
467         { 0x1269EB58UL, 0x00000350UL }, /* cvt  */
468         { 0x5CD5957AUL, 0x00006A4EUL }, /* fpgm */
469         { 0xF758323AUL, 0x00000380UL }  /* prep */
470       },
471         { /* DFMing-Md-WIN-HK-BF, issue #1087 */
472         { 0x122FEB0BUL, 0x00000350UL }, /* cvt  */
473         { 0x7F10919AUL, 0x000070A9UL }, /* fpgm */
474         { 0x7CD7E7B7UL, 0x0000025CUL }  /* prep */
475       }
476     };
477 
478     FT_ULong   checksum;
479     int        num_matched_ids[TRICK_SFNT_IDS_NUM_FACES];
480     FT_Bool    has_cvt, has_fpgm, has_prep;
481     FT_UShort  i;
482     int        j, k;
483 
484 
485     FT_MEM_SET( num_matched_ids, 0,
486                 sizeof ( int ) * TRICK_SFNT_IDS_NUM_FACES );
487     has_cvt  = FALSE;
488     has_fpgm = FALSE;
489     has_prep = FALSE;
490 
491     for ( i = 0; i < face->num_tables; i++ )
492     {
493       checksum = 0;
494 
495       switch( face->dir_tables[i].Tag )
496       {
497       case TTAG_cvt:
498         k = TRICK_SFNT_ID_cvt;
499         has_cvt  = TRUE;
500         break;
501 
502       case TTAG_fpgm:
503         k = TRICK_SFNT_ID_fpgm;
504         has_fpgm = TRUE;
505         break;
506 
507       case TTAG_prep:
508         k = TRICK_SFNT_ID_prep;
509         has_prep = TRUE;
510         break;
511 
512       default:
513         continue;
514       }
515 
516       for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ )
517         if ( face->dir_tables[i].Length == sfnt_id[j][k].Length )
518         {
519           if ( !checksum )
520             checksum = tt_get_sfnt_checksum( face, i );
521 
522           if ( sfnt_id[j][k].CheckSum == checksum )
523             num_matched_ids[j]++;
524 
525           if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE )
526             return TRUE;
527         }
528     }
529 
530     for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ )
531     {
532       if ( !has_cvt  && !sfnt_id[j][TRICK_SFNT_ID_cvt].Length )
533         num_matched_ids[j]++;
534       if ( !has_fpgm && !sfnt_id[j][TRICK_SFNT_ID_fpgm].Length )
535         num_matched_ids[j]++;
536       if ( !has_prep && !sfnt_id[j][TRICK_SFNT_ID_prep].Length )
537         num_matched_ids[j]++;
538       if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE )
539         return TRUE;
540     }
541 
542     return FALSE;
543   }
544 
545 
546   static FT_Bool
tt_check_trickyness(FT_Face face)547   tt_check_trickyness( FT_Face  face )
548   {
549     if ( !face )
550       return FALSE;
551 
552     /* For first, check the face name for quick check. */
553     if ( face->family_name                               &&
554          tt_check_trickyness_family( face->family_name ) )
555     {
556       FT_TRACE3(( "found as a tricky font"
557                   " by its family name: %s\n", face->family_name ));
558       return TRUE;
559     }
560 
561     /* Type42 fonts may lack `name' tables, we thus try to identify */
562     /* tricky fonts by checking the checksums of Type42-persistent  */
563     /* sfnt tables (`cvt', `fpgm', and `prep').                     */
564     if ( tt_check_trickyness_sfnt_ids( (TT_Face)face ) )
565     {
566       FT_TRACE3(( "found as a tricky font"
567                   " by its cvt/fpgm/prep table checksum\n" ));
568       return TRUE;
569     }
570 
571     return FALSE;
572   }
573 
574 #endif /* TT_USE_BYTECODE_INTERPRETER */
575 
576 
577   /* Check whether `.notdef' is the only glyph in the `loca' table. */
578   static FT_Bool
tt_check_single_notdef(FT_Face ttface)579   tt_check_single_notdef( FT_Face  ttface )
580   {
581     FT_Bool   result = FALSE;
582 
583     TT_Face   face = (TT_Face)ttface;
584     FT_UInt   asize;
585     FT_ULong  i;
586     FT_ULong  glyph_index = 0;
587     FT_UInt   count       = 0;
588 
589 
590     for( i = 0; i < face->num_locations; i++ )
591     {
592       tt_face_get_location( face, i, &asize );
593       if ( asize > 0 )
594       {
595         count += 1;
596         if ( count > 1 )
597           break;
598         glyph_index = i;
599       }
600     }
601 
602     /* Only have a single outline. */
603     if ( count == 1 )
604     {
605       if ( glyph_index == 0 )
606         result = TRUE;
607       else
608       {
609         /* FIXME: Need to test glyphname == .notdef ? */
610         FT_Error error;
611         char buf[8];
612 
613 
614         error = FT_Get_Glyph_Name( ttface, glyph_index, buf, 8 );
615         if ( !error                                            &&
616              buf[0] == '.' && !ft_strncmp( buf, ".notdef", 8 ) )
617           result = TRUE;
618       }
619     }
620 
621     return result;
622   }
623 
624 
625   /**************************************************************************
626    *
627    * @Function:
628    *   tt_face_init
629    *
630    * @Description:
631    *   Initialize a given TrueType face object.
632    *
633    * @Input:
634    *   stream ::
635    *     The source font stream.
636    *
637    *   face_index ::
638    *     The index of the TrueType font, if we are opening a
639    *     collection, in bits 0-15.  The numbered instance
640    *     index~+~1 of a GX (sub)font, if applicable, in bits
641    *     16-30.
642    *
643    *   num_params ::
644    *     Number of additional generic parameters.  Ignored.
645    *
646    *   params ::
647    *     Additional generic parameters.  Ignored.
648    *
649    * @InOut:
650    *   face ::
651    *     The newly built face object.
652    *
653    * @Return:
654    *   FreeType error code.  0 means success.
655    */
656   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)657   tt_face_init( FT_Stream      stream,
658                 FT_Face        ttface,      /* TT_Face */
659                 FT_Int         face_index,
660                 FT_Int         num_params,
661                 FT_Parameter*  params )
662   {
663     FT_Error      error;
664     FT_Library    library;
665     SFNT_Service  sfnt;
666     TT_Face       face = (TT_Face)ttface;
667 
668 
669     FT_TRACE2(( "TTF driver\n" ));
670 
671     library = ttface->driver->root.library;
672 
673     sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );
674     if ( !sfnt )
675     {
676       FT_ERROR(( "tt_face_init: cannot access `sfnt' module\n" ));
677       error = FT_THROW( Missing_Module );
678       goto Exit;
679     }
680 
681     /* create input stream from resource */
682     if ( FT_STREAM_SEEK( 0 ) )
683       goto Exit;
684 
685     /* check that we have a valid TrueType file */
686     FT_TRACE2(( "  " ));
687     error = sfnt->init_face( stream, face, face_index, num_params, params );
688 
689     /* Stream may have changed. */
690     stream = face->root.stream;
691 
692     if ( error )
693       goto Exit;
694 
695     /* We must also be able to accept Mac/GX fonts, as well as OT ones. */
696     /* The 0x00020000 tag is completely undocumented; some fonts from   */
697     /* Arphic made for Chinese Windows 3.1 have this.                   */
698     if ( face->format_tag != 0x00010000L  && /* MS fonts                             */
699          face->format_tag != 0x00020000L  && /* CJK fonts for Win 3.1                */
700          face->format_tag != TTAG_true    && /* Mac fonts                            */
701          face->format_tag != TTAG_0xA5kbd && /* `Keyboard.dfont' (legacy Mac OS X)   */
702          face->format_tag != TTAG_0xA5lst )  /* `LastResort.dfont' (legacy Mac OS X) */
703     {
704       FT_TRACE2(( "  not a TTF font\n" ));
705       goto Bad_Format;
706     }
707 
708 #ifdef TT_USE_BYTECODE_INTERPRETER
709     ttface->face_flags |= FT_FACE_FLAG_HINTER;
710 #endif
711 
712     /* If we are performing a simple font format check, exit immediately. */
713     if ( face_index < 0 )
714       return FT_Err_Ok;
715 
716     /* Load font directory */
717     error = sfnt->load_face( stream, face, face_index, num_params, params );
718     if ( error )
719       goto Exit;
720 
721 #ifdef TT_USE_BYTECODE_INTERPRETER
722     if ( tt_check_trickyness( ttface ) )
723       ttface->face_flags |= FT_FACE_FLAG_TRICKY;
724 #endif
725 
726     error = tt_face_load_hdmx( face, stream );
727     if ( error )
728       goto Exit;
729 
730     if ( FT_IS_SCALABLE( ttface ) ||
731          FT_HAS_SBIX( ttface )    )
732     {
733 #ifdef FT_CONFIG_OPTION_INCREMENTAL
734       if ( !ttface->internal->incremental_interface )
735 #endif
736       {
737         error = tt_face_load_loca( face, stream );
738 
739         /* having a (non-zero) `glyf' table without */
740         /* a `loca' table is not valid              */
741         if ( face->glyf_len && FT_ERR_EQ( error, Table_Missing ) )
742           goto Exit;
743         if ( error )
744           goto Exit;
745       }
746 
747       /* `fpgm', `cvt', and `prep' are optional */
748       error = tt_face_load_cvt( face, stream );
749       if ( error && FT_ERR_NEQ( error, Table_Missing ) )
750         goto Exit;
751 
752       error = tt_face_load_fpgm( face, stream );
753       if ( error && FT_ERR_NEQ( error, Table_Missing ) )
754         goto Exit;
755 
756       error = tt_face_load_prep( face, stream );
757       if ( error && FT_ERR_NEQ( error, Table_Missing ) )
758         goto Exit;
759 
760       /* Check the scalable flag based on `loca'. */
761 #ifdef FT_CONFIG_OPTION_INCREMENTAL
762       if ( !ttface->internal->incremental_interface )
763 #endif
764       {
765         if ( ttface->num_fixed_sizes          &&
766              face->glyph_locations            &&
767              tt_check_single_notdef( ttface ) )
768         {
769           FT_TRACE5(( "tt_face_init:"
770                       " Only the `.notdef' glyph has an outline.\n" ));
771           FT_TRACE5(( "             "
772                       " Resetting scalable flag to FALSE.\n" ));
773 
774           ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
775         }
776       }
777     }
778 
779 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
780 
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 = TT_Set_Named_Instance( face, instance_index );
789         if ( error )
790           goto Exit;
791 
792         tt_apply_mvar( face );
793       }
794     }
795 
796 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
797 
798     /* initialize standard glyph loading routines */
799     TT_Init_Glyph_Loading( face );
800 
801   Exit:
802     return error;
803 
804   Bad_Format:
805     error = FT_THROW( Unknown_File_Format );
806     goto Exit;
807   }
808 
809 
810   /**************************************************************************
811    *
812    * @Function:
813    *   tt_face_done
814    *
815    * @Description:
816    *   Finalize a given face object.
817    *
818    * @Input:
819    *   face ::
820    *     A pointer to the face object to destroy.
821    */
822   FT_LOCAL_DEF( void )
tt_face_done(FT_Face ttface)823   tt_face_done( FT_Face  ttface )           /* TT_Face */
824   {
825     TT_Face       face = (TT_Face)ttface;
826     FT_Memory     memory;
827     FT_Stream     stream;
828     SFNT_Service  sfnt;
829 
830 
831     if ( !face )
832       return;
833 
834     memory = ttface->memory;
835     stream = ttface->stream;
836     sfnt   = (SFNT_Service)face->sfnt;
837 
838     /* for `extended TrueType formats' (i.e. compressed versions) */
839     if ( face->extra.finalizer )
840       face->extra.finalizer( face->extra.data );
841 
842     if ( sfnt )
843       sfnt->done_face( face );
844 
845     /* freeing the locations table */
846     tt_face_done_loca( face );
847 
848     tt_face_free_hdmx( face );
849 
850     /* freeing the CVT */
851     FT_FREE( face->cvt );
852     face->cvt_size = 0;
853 
854     /* freeing the programs */
855     FT_FRAME_RELEASE( face->font_program );
856     FT_FRAME_RELEASE( face->cvt_program );
857     face->font_program_size = 0;
858     face->cvt_program_size  = 0;
859 
860 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
861     tt_done_blend( face );
862     face->blend = NULL;
863 #endif
864   }
865 
866 
867   /**************************************************************************
868    *
869    *                          SIZE  FUNCTIONS
870    *
871    */
872 
873 #ifdef TT_USE_BYTECODE_INTERPRETER
874 
875   /**************************************************************************
876    *
877    * @Function:
878    *   tt_size_run_fpgm
879    *
880    * @Description:
881    *   Run the font program.
882    *
883    * @Input:
884    *   size ::
885    *     A handle to the size object.
886    *
887    *   pedantic ::
888    *     Set if bytecode execution should be pedantic.
889    *
890    * @Return:
891    *   FreeType error code.  0 means success.
892    */
893   FT_LOCAL_DEF( FT_Error )
tt_size_run_fpgm(TT_Size size,FT_Bool pedantic)894   tt_size_run_fpgm( TT_Size  size,
895                     FT_Bool  pedantic )
896   {
897     TT_Face         face = (TT_Face)size->root.face;
898     TT_ExecContext  exec;
899     FT_Error        error;
900 
901 
902     exec = size->context;
903 
904     error = TT_Load_Context( exec, face, size );
905     if ( error )
906       return error;
907 
908     exec->callTop = 0;
909     exec->top     = 0;
910 
911     exec->period    = 64;
912     exec->phase     = 0;
913     exec->threshold = 0;
914 
915     exec->instruction_trap = FALSE;
916     exec->F_dot_P          = 0x4000L;
917 
918     exec->pedantic_hinting = pedantic;
919 
920     {
921       FT_Size_Metrics*  size_metrics = &exec->metrics;
922       TT_Size_Metrics*  tt_metrics   = &exec->tt_metrics;
923 
924 
925       size_metrics->x_ppem   = 0;
926       size_metrics->y_ppem   = 0;
927       size_metrics->x_scale  = 0;
928       size_metrics->y_scale  = 0;
929 
930       tt_metrics->ppem  = 0;
931       tt_metrics->scale = 0;
932       tt_metrics->ratio = 0x10000L;
933     }
934 
935     /* allow font program execution */
936     TT_Set_CodeRange( exec,
937                       tt_coderange_font,
938                       face->font_program,
939                       (FT_Long)face->font_program_size );
940 
941     /* disable CVT and glyph programs coderange */
942     TT_Clear_CodeRange( exec, tt_coderange_cvt );
943     TT_Clear_CodeRange( exec, tt_coderange_glyph );
944 
945     if ( face->font_program_size > 0 )
946     {
947       TT_Goto_CodeRange( exec, tt_coderange_font, 0 );
948 
949       FT_TRACE4(( "Executing `fpgm' table.\n" ));
950       error = face->interpreter( exec );
951 #ifdef FT_DEBUG_LEVEL_TRACE
952       if ( error )
953         FT_TRACE4(( "  interpretation failed with error code 0x%x\n",
954                     error ));
955 #endif
956     }
957     else
958       error = FT_Err_Ok;
959 
960     size->bytecode_ready = error;
961 
962     if ( !error )
963       TT_Save_Context( exec, size );
964 
965     return error;
966   }
967 
968 
969   /**************************************************************************
970    *
971    * @Function:
972    *   tt_size_run_prep
973    *
974    * @Description:
975    *   Run the control value program.
976    *
977    * @Input:
978    *   size ::
979    *     A handle to the size object.
980    *
981    *   pedantic ::
982    *     Set if bytecode execution should be pedantic.
983    *
984    * @Return:
985    *   FreeType error code.  0 means success.
986    */
987   FT_LOCAL_DEF( FT_Error )
tt_size_run_prep(TT_Size size,FT_Bool pedantic)988   tt_size_run_prep( TT_Size  size,
989                     FT_Bool  pedantic )
990   {
991     TT_Face         face = (TT_Face)size->root.face;
992     TT_ExecContext  exec;
993     FT_Error        error;
994     FT_UInt         i;
995 
996     /* unscaled CVT values are already stored in 26.6 format */
997     FT_Fixed  scale = size->ttmetrics.scale >> 6;
998 
999 
1000     /* Scale the cvt values to the new ppem.            */
1001     /* By default, we use the y ppem value for scaling. */
1002     FT_TRACE6(( "CVT values:\n" ));
1003     for ( i = 0; i < size->cvt_size; i++ )
1004     {
1005       size->cvt[i] = FT_MulFix( face->cvt[i], scale );
1006       FT_TRACE6(( "  %3d: %f (%f)\n",
1007                   i, (double)face->cvt[i] / 64, (double)size->cvt[i] / 64 ));
1008     }
1009     FT_TRACE6(( "\n" ));
1010 
1011     exec = size->context;
1012 
1013     error = TT_Load_Context( exec, face, size );
1014     if ( error )
1015       return error;
1016 
1017     exec->callTop = 0;
1018     exec->top     = 0;
1019 
1020     exec->instruction_trap = FALSE;
1021 
1022     exec->pedantic_hinting = pedantic;
1023 
1024     TT_Set_CodeRange( exec,
1025                       tt_coderange_cvt,
1026                       face->cvt_program,
1027                       (FT_Long)face->cvt_program_size );
1028 
1029     TT_Clear_CodeRange( exec, tt_coderange_glyph );
1030 
1031     if ( face->cvt_program_size > 0 )
1032     {
1033       TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 );
1034 
1035       FT_TRACE4(( "Executing `prep' table.\n" ));
1036       error = face->interpreter( exec );
1037 #ifdef FT_DEBUG_LEVEL_TRACE
1038       if ( error )
1039         FT_TRACE4(( "  interpretation failed with error code 0x%x\n",
1040                     error ));
1041 #endif
1042     }
1043     else
1044       error = FT_Err_Ok;
1045 
1046     size->cvt_ready = error;
1047 
1048     /* UNDOCUMENTED!  The MS rasterizer doesn't allow the following */
1049     /* graphics state variables to be modified by the CVT program.  */
1050 
1051     exec->GS.dualVector.x = 0x4000;
1052     exec->GS.dualVector.y = 0;
1053     exec->GS.projVector.x = 0x4000;
1054     exec->GS.projVector.y = 0x0;
1055     exec->GS.freeVector.x = 0x4000;
1056     exec->GS.freeVector.y = 0x0;
1057 
1058     exec->GS.rp0 = 0;
1059     exec->GS.rp1 = 0;
1060     exec->GS.rp2 = 0;
1061 
1062     exec->GS.gep0 = 1;
1063     exec->GS.gep1 = 1;
1064     exec->GS.gep2 = 1;
1065 
1066     exec->GS.loop = 1;
1067 
1068     /* save as default graphics state */
1069     size->GS = exec->GS;
1070 
1071     TT_Save_Context( exec, size );
1072 
1073     return error;
1074   }
1075 
1076 
1077   static void
tt_size_done_bytecode(FT_Size ftsize)1078   tt_size_done_bytecode( FT_Size  ftsize )
1079   {
1080     TT_Size    size   = (TT_Size)ftsize;
1081     TT_Face    face   = (TT_Face)ftsize->face;
1082     FT_Memory  memory = face->root.memory;
1083 
1084     if ( size->context )
1085     {
1086       TT_Done_Context( size->context );
1087       size->context = NULL;
1088     }
1089 
1090     FT_FREE( size->cvt );
1091     size->cvt_size = 0;
1092 
1093     /* free storage area */
1094     FT_FREE( size->storage );
1095     size->storage_size = 0;
1096 
1097     /* twilight zone */
1098     tt_glyphzone_done( &size->twilight );
1099 
1100     FT_FREE( size->function_defs );
1101     FT_FREE( size->instruction_defs );
1102 
1103     size->num_function_defs    = 0;
1104     size->max_function_defs    = 0;
1105     size->num_instruction_defs = 0;
1106     size->max_instruction_defs = 0;
1107 
1108     size->max_func = 0;
1109     size->max_ins  = 0;
1110 
1111     size->bytecode_ready = -1;
1112     size->cvt_ready      = -1;
1113   }
1114 
1115 
1116   /* Initialize bytecode-related fields in the size object.       */
1117   /* We do this only if bytecode interpretation is really needed. */
1118   static FT_Error
tt_size_init_bytecode(FT_Size ftsize,FT_Bool pedantic)1119   tt_size_init_bytecode( FT_Size  ftsize,
1120                          FT_Bool  pedantic )
1121   {
1122     FT_Error   error;
1123     TT_Size    size = (TT_Size)ftsize;
1124     TT_Face    face = (TT_Face)ftsize->face;
1125     FT_Memory  memory = face->root.memory;
1126 
1127     FT_UShort       n_twilight;
1128     TT_MaxProfile*  maxp = &face->max_profile;
1129 
1130 
1131     /* clean up bytecode related data */
1132     FT_FREE( size->function_defs );
1133     FT_FREE( size->instruction_defs );
1134     FT_FREE( size->cvt );
1135     FT_FREE( size->storage );
1136 
1137     if ( size->context )
1138       TT_Done_Context( size->context );
1139     tt_glyphzone_done( &size->twilight );
1140 
1141     size->bytecode_ready = -1;
1142     size->cvt_ready      = -1;
1143 
1144     size->context = TT_New_Context( (TT_Driver)face->root.driver );
1145 
1146     size->max_function_defs    = maxp->maxFunctionDefs;
1147     size->max_instruction_defs = maxp->maxInstructionDefs;
1148 
1149     size->num_function_defs    = 0;
1150     size->num_instruction_defs = 0;
1151 
1152     size->max_func = 0;
1153     size->max_ins  = 0;
1154 
1155     size->cvt_size     = face->cvt_size;
1156     size->storage_size = maxp->maxStorage;
1157 
1158     /* Set default metrics */
1159     {
1160       TT_Size_Metrics*  tt_metrics = &size->ttmetrics;
1161 
1162 
1163       tt_metrics->rotated   = FALSE;
1164       tt_metrics->stretched = FALSE;
1165 
1166       /* Set default engine compensation.  Value 3 is not described */
1167       /* in the OpenType specification (as of Mai 2019), but Greg   */
1168       /* says that MS handles it the same as `gray'.                */
1169       /*                                                            */
1170       /* The Apple specification says that the compensation for     */
1171       /* `gray' is always zero.  FreeType doesn't do any            */
1172       /* compensation at all.                                       */
1173       tt_metrics->compensations[0] = 0;   /* gray  */
1174       tt_metrics->compensations[1] = 0;   /* black */
1175       tt_metrics->compensations[2] = 0;   /* white */
1176       tt_metrics->compensations[3] = 0;   /* zero  */
1177     }
1178 
1179     /* allocate function defs, instruction defs, cvt, and storage area */
1180     if ( FT_NEW_ARRAY( size->function_defs,    size->max_function_defs    ) ||
1181          FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) ||
1182          FT_NEW_ARRAY( size->cvt,              size->cvt_size             ) ||
1183          FT_NEW_ARRAY( size->storage,          size->storage_size         ) )
1184       goto Exit;
1185 
1186     /* reserve twilight zone */
1187     n_twilight = maxp->maxTwilightPoints;
1188 
1189     /* there are 4 phantom points (do we need this?) */
1190     n_twilight += 4;
1191 
1192     error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight );
1193     if ( error )
1194       goto Exit;
1195 
1196     size->twilight.n_points = n_twilight;
1197 
1198     size->GS = tt_default_graphics_state;
1199 
1200     /* set `face->interpreter' according to the debug hook present */
1201     {
1202       FT_Library  library = face->root.driver->root.library;
1203 
1204 
1205       face->interpreter = (TT_Interpreter)
1206                             library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE];
1207       if ( !face->interpreter )
1208         face->interpreter = (TT_Interpreter)TT_RunIns;
1209     }
1210 
1211     /* Fine, now run the font program! */
1212 
1213     /* In case of an error while executing `fpgm', we intentionally don't */
1214     /* clean up immediately – bugs in the `fpgm' are so fundamental that  */
1215     /* all following hinting calls should fail.  Additionally, `fpgm' is  */
1216     /* to be executed just once; calling it again is completely useless   */
1217     /* and might even lead to extremely slow behaviour if it is malformed */
1218     /* (containing an infinite loop, for example).                        */
1219     error = tt_size_run_fpgm( size, pedantic );
1220     return error;
1221 
1222   Exit:
1223     if ( error )
1224       tt_size_done_bytecode( ftsize );
1225 
1226     return error;
1227   }
1228 
1229 
1230   FT_LOCAL_DEF( FT_Error )
tt_size_ready_bytecode(TT_Size size,FT_Bool pedantic)1231   tt_size_ready_bytecode( TT_Size  size,
1232                           FT_Bool  pedantic )
1233   {
1234     FT_Error  error = FT_Err_Ok;
1235 
1236 
1237     if ( size->bytecode_ready < 0 )
1238       error = tt_size_init_bytecode( (FT_Size)size, pedantic );
1239     else
1240       error = size->bytecode_ready;
1241 
1242     if ( error )
1243       goto Exit;
1244 
1245     /* rescale CVT when needed */
1246     if ( size->cvt_ready < 0 )
1247     {
1248       FT_UShort  i;
1249 
1250 
1251       /* all twilight points are originally zero */
1252       for ( i = 0; i < size->twilight.n_points; i++ )
1253       {
1254         size->twilight.org[i].x = 0;
1255         size->twilight.org[i].y = 0;
1256         size->twilight.cur[i].x = 0;
1257         size->twilight.cur[i].y = 0;
1258       }
1259 
1260       /* clear storage area */
1261       for ( i = 0; i < size->storage_size; i++ )
1262         size->storage[i] = 0;
1263 
1264       size->GS = tt_default_graphics_state;
1265 
1266       error = tt_size_run_prep( size, pedantic );
1267     }
1268     else
1269       error = size->cvt_ready;
1270 
1271   Exit:
1272     return error;
1273   }
1274 
1275 #endif /* TT_USE_BYTECODE_INTERPRETER */
1276 
1277 
1278   /**************************************************************************
1279    *
1280    * @Function:
1281    *   tt_size_init
1282    *
1283    * @Description:
1284    *   Initialize a new TrueType size object.
1285    *
1286    * @InOut:
1287    *   size ::
1288    *     A handle to the size object.
1289    *
1290    * @Return:
1291    *   FreeType error code.  0 means success.
1292    */
1293   FT_LOCAL_DEF( FT_Error )
tt_size_init(FT_Size ttsize)1294   tt_size_init( FT_Size  ttsize )           /* TT_Size */
1295   {
1296     TT_Size   size  = (TT_Size)ttsize;
1297     FT_Error  error = FT_Err_Ok;
1298 
1299 
1300 #ifdef TT_USE_BYTECODE_INTERPRETER
1301     size->bytecode_ready = -1;
1302     size->cvt_ready      = -1;
1303 #endif
1304 
1305     size->ttmetrics.valid = FALSE;
1306     size->strike_index    = 0xFFFFFFFFUL;
1307 
1308     return error;
1309   }
1310 
1311 
1312   /**************************************************************************
1313    *
1314    * @Function:
1315    *   tt_size_done
1316    *
1317    * @Description:
1318    *   The TrueType size object finalizer.
1319    *
1320    * @Input:
1321    *   size ::
1322    *     A handle to the target size object.
1323    */
1324   FT_LOCAL_DEF( void )
tt_size_done(FT_Size ttsize)1325   tt_size_done( FT_Size  ttsize )           /* TT_Size */
1326   {
1327     TT_Size  size = (TT_Size)ttsize;
1328 
1329 
1330 #ifdef TT_USE_BYTECODE_INTERPRETER
1331     tt_size_done_bytecode( ttsize );
1332 #endif
1333 
1334     size->ttmetrics.valid = FALSE;
1335   }
1336 
1337 
1338   /**************************************************************************
1339    *
1340    * @Function:
1341    *   tt_size_reset_height
1342    *
1343    * @Description:
1344    *   Recompute a TrueType size's ascender, descender, and height
1345    *   when resolutions and character dimensions have been changed.
1346    *   Used for variation fonts as an iterator function.
1347    *
1348    * @Input:
1349    *   ft_size ::
1350    *     A handle to the target TT_Size object. This function will be called
1351    *     through a `FT_Size_Reset_Func` pointer which takes `FT_Size`. This
1352    *     function must take `FT_Size` as a result. The passed `FT_Size` is
1353    *     expected to point to a `TT_Size`.
1354    */
1355   FT_LOCAL_DEF( FT_Error )
tt_size_reset_height(FT_Size ft_size)1356   tt_size_reset_height( FT_Size  ft_size )
1357   {
1358     TT_Size           size         = (TT_Size)ft_size;
1359     TT_Face           face         = (TT_Face)size->root.face;
1360     FT_Size_Metrics*  size_metrics = &size->hinted_metrics;
1361 
1362     size->ttmetrics.valid = FALSE;
1363 
1364     /* copy the result from base layer */
1365     *size_metrics = size->root.metrics;
1366 
1367     if ( size_metrics->x_ppem < 1 || size_metrics->y_ppem < 1 )
1368       return FT_THROW( Invalid_PPem );
1369 
1370     /* This bit flag, if set, indicates that the ppems must be       */
1371     /* rounded to integers.  Nearly all TrueType fonts have this bit */
1372     /* set, as hinting won't work really well otherwise.             */
1373     /*                                                               */
1374     if ( face->header.Flags & 8 )
1375     {
1376       /* the TT spec always asks for ROUND, not FLOOR or CEIL */
1377       size_metrics->ascender = FT_PIX_ROUND(
1378                                  FT_MulFix( face->root.ascender,
1379                                             size_metrics->y_scale ) );
1380       size_metrics->descender = FT_PIX_ROUND(
1381                                  FT_MulFix( face->root.descender,
1382                                             size_metrics->y_scale ) );
1383       size_metrics->height = FT_PIX_ROUND(
1384                                FT_MulFix( face->root.height,
1385                                           size_metrics->y_scale ) );
1386     }
1387 
1388     size->ttmetrics.valid = TRUE;
1389 
1390     return FT_Err_Ok;
1391   }
1392 
1393 
1394   /**************************************************************************
1395    *
1396    * @Function:
1397    *   tt_size_reset
1398    *
1399    * @Description:
1400    *   Reset a TrueType size when resolutions and character dimensions
1401    *   have been changed.
1402    *
1403    * @Input:
1404    *   size ::
1405    *     A handle to the target size object.
1406    */
1407   FT_LOCAL_DEF( FT_Error )
tt_size_reset(TT_Size size)1408   tt_size_reset( TT_Size  size )
1409   {
1410     FT_Error          error;
1411     TT_Face           face         = (TT_Face)size->root.face;
1412     FT_Size_Metrics*  size_metrics = &size->hinted_metrics;
1413 
1414 
1415     error = tt_size_reset_height( (FT_Size)size );
1416     if ( error )
1417       return error;
1418 
1419     if ( face->header.Flags & 8 )
1420     {
1421       /* base scaling values on integer ppem values, */
1422       /* as mandated by the TrueType specification   */
1423       size_metrics->x_scale = FT_DivFix( size_metrics->x_ppem << 6,
1424                                          face->root.units_per_EM );
1425       size_metrics->y_scale = FT_DivFix( size_metrics->y_ppem << 6,
1426                                          face->root.units_per_EM );
1427 
1428       size_metrics->max_advance = FT_PIX_ROUND(
1429                                     FT_MulFix( face->root.max_advance_width,
1430                                                size_metrics->x_scale ) );
1431     }
1432 
1433     /* compute new transformation */
1434     if ( size_metrics->x_ppem >= size_metrics->y_ppem )
1435     {
1436       size->ttmetrics.scale   = size_metrics->x_scale;
1437       size->ttmetrics.ppem    = size_metrics->x_ppem;
1438       size->ttmetrics.x_ratio = 0x10000L;
1439       size->ttmetrics.y_ratio = FT_DivFix( size_metrics->y_ppem,
1440                                            size_metrics->x_ppem );
1441     }
1442     else
1443     {
1444       size->ttmetrics.scale   = size_metrics->y_scale;
1445       size->ttmetrics.ppem    = size_metrics->y_ppem;
1446       size->ttmetrics.x_ratio = FT_DivFix( size_metrics->x_ppem,
1447                                            size_metrics->y_ppem );
1448       size->ttmetrics.y_ratio = 0x10000L;
1449     }
1450 
1451     size->widthp = tt_face_get_device_metrics( face, size_metrics->x_ppem, 0 );
1452 
1453     size->metrics = size_metrics;
1454 
1455 #ifdef TT_USE_BYTECODE_INTERPRETER
1456     size->cvt_ready = -1;
1457 #endif /* TT_USE_BYTECODE_INTERPRETER */
1458 
1459     return FT_Err_Ok;
1460   }
1461 
1462 
1463   /**************************************************************************
1464    *
1465    * @Function:
1466    *   tt_driver_init
1467    *
1468    * @Description:
1469    *   Initialize a given TrueType driver object.
1470    *
1471    * @Input:
1472    *   driver ::
1473    *     A handle to the target driver object.
1474    *
1475    * @Return:
1476    *   FreeType error code.  0 means success.
1477    */
1478   FT_LOCAL_DEF( FT_Error )
tt_driver_init(FT_Module ttdriver)1479   tt_driver_init( FT_Module  ttdriver )     /* TT_Driver */
1480   {
1481 
1482 #ifdef TT_USE_BYTECODE_INTERPRETER
1483 
1484     TT_Driver  driver = (TT_Driver)ttdriver;
1485 
1486     driver->interpreter_version = TT_INTERPRETER_VERSION_35;
1487 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
1488     driver->interpreter_version = TT_INTERPRETER_VERSION_38;
1489 #endif
1490 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
1491     driver->interpreter_version = TT_INTERPRETER_VERSION_40;
1492 #endif
1493 
1494 #else /* !TT_USE_BYTECODE_INTERPRETER */
1495 
1496     FT_UNUSED( ttdriver );
1497 
1498 #endif /* !TT_USE_BYTECODE_INTERPRETER */
1499 
1500     return FT_Err_Ok;
1501   }
1502 
1503 
1504   /**************************************************************************
1505    *
1506    * @Function:
1507    *   tt_driver_done
1508    *
1509    * @Description:
1510    *   Finalize a given TrueType driver.
1511    *
1512    * @Input:
1513    *   driver ::
1514    *     A handle to the target TrueType driver.
1515    */
1516   FT_LOCAL_DEF( void )
tt_driver_done(FT_Module ttdriver)1517   tt_driver_done( FT_Module  ttdriver )     /* TT_Driver */
1518   {
1519     FT_UNUSED( ttdriver );
1520   }
1521 
1522 
1523   /**************************************************************************
1524    *
1525    * @Function:
1526    *   tt_slot_init
1527    *
1528    * @Description:
1529    *   Initialize a new slot object.
1530    *
1531    * @InOut:
1532    *   slot ::
1533    *     A handle to the slot object.
1534    *
1535    * @Return:
1536    *   FreeType error code.  0 means success.
1537    */
1538   FT_LOCAL_DEF( FT_Error )
tt_slot_init(FT_GlyphSlot slot)1539   tt_slot_init( FT_GlyphSlot  slot )
1540   {
1541     return FT_GlyphLoader_CreateExtra( slot->internal->loader );
1542   }
1543 
1544 
1545 /* END */
1546