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