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