• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  *
3  * ttobjs.c
4  *
5  *   Objects manager (body).
6  *
7  * Copyright 1996-2018 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  trace_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(FT_String * name)151   tt_check_trickyness_family( 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 
941 
942     exec = size->context;
943 
944     error = TT_Load_Context( exec, face, size );
945     if ( error )
946       return error;
947 
948     exec->callTop = 0;
949     exec->top     = 0;
950 
951     exec->instruction_trap = FALSE;
952 
953     exec->pedantic_hinting = pedantic;
954 
955     TT_Set_CodeRange( exec,
956                       tt_coderange_cvt,
957                       face->cvt_program,
958                       (FT_Long)face->cvt_program_size );
959 
960     TT_Clear_CodeRange( exec, tt_coderange_glyph );
961 
962     if ( face->cvt_program_size > 0 )
963     {
964       TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 );
965 
966       FT_TRACE4(( "Executing `prep' table.\n" ));
967       error = face->interpreter( exec );
968 #ifdef FT_DEBUG_LEVEL_TRACE
969       if ( error )
970         FT_TRACE4(( "  interpretation failed with error code 0x%x\n",
971                     error ));
972 #endif
973     }
974     else
975       error = FT_Err_Ok;
976 
977     size->cvt_ready = error;
978 
979     /* UNDOCUMENTED!  The MS rasterizer doesn't allow the following */
980     /* graphics state variables to be modified by the CVT program.  */
981 
982     exec->GS.dualVector.x = 0x4000;
983     exec->GS.dualVector.y = 0;
984     exec->GS.projVector.x = 0x4000;
985     exec->GS.projVector.y = 0x0;
986     exec->GS.freeVector.x = 0x4000;
987     exec->GS.freeVector.y = 0x0;
988 
989     exec->GS.rp0 = 0;
990     exec->GS.rp1 = 0;
991     exec->GS.rp2 = 0;
992 
993     exec->GS.gep0 = 1;
994     exec->GS.gep1 = 1;
995     exec->GS.gep2 = 1;
996 
997     exec->GS.loop = 1;
998 
999     /* save as default graphics state */
1000     size->GS = exec->GS;
1001 
1002     TT_Save_Context( exec, size );
1003 
1004     return error;
1005   }
1006 
1007 
1008   static void
tt_size_done_bytecode(FT_Size ftsize)1009   tt_size_done_bytecode( FT_Size  ftsize )
1010   {
1011     TT_Size    size   = (TT_Size)ftsize;
1012     TT_Face    face   = (TT_Face)ftsize->face;
1013     FT_Memory  memory = face->root.memory;
1014 
1015     if ( size->context )
1016     {
1017       TT_Done_Context( size->context );
1018       size->context = NULL;
1019     }
1020 
1021     FT_FREE( size->cvt );
1022     size->cvt_size = 0;
1023 
1024     /* free storage area */
1025     FT_FREE( size->storage );
1026     size->storage_size = 0;
1027 
1028     /* twilight zone */
1029     tt_glyphzone_done( &size->twilight );
1030 
1031     FT_FREE( size->function_defs );
1032     FT_FREE( size->instruction_defs );
1033 
1034     size->num_function_defs    = 0;
1035     size->max_function_defs    = 0;
1036     size->num_instruction_defs = 0;
1037     size->max_instruction_defs = 0;
1038 
1039     size->max_func = 0;
1040     size->max_ins  = 0;
1041 
1042     size->bytecode_ready = -1;
1043     size->cvt_ready      = -1;
1044   }
1045 
1046 
1047   /* Initialize bytecode-related fields in the size object.       */
1048   /* We do this only if bytecode interpretation is really needed. */
1049   static FT_Error
tt_size_init_bytecode(FT_Size ftsize,FT_Bool pedantic)1050   tt_size_init_bytecode( FT_Size  ftsize,
1051                          FT_Bool  pedantic )
1052   {
1053     FT_Error   error;
1054     TT_Size    size = (TT_Size)ftsize;
1055     TT_Face    face = (TT_Face)ftsize->face;
1056     FT_Memory  memory = face->root.memory;
1057 
1058     FT_UShort       n_twilight;
1059     TT_MaxProfile*  maxp = &face->max_profile;
1060 
1061 
1062     /* clean up bytecode related data */
1063     FT_FREE( size->function_defs );
1064     FT_FREE( size->instruction_defs );
1065     FT_FREE( size->cvt );
1066     FT_FREE( size->storage );
1067 
1068     if ( size->context )
1069       TT_Done_Context( size->context );
1070     tt_glyphzone_done( &size->twilight );
1071 
1072     size->bytecode_ready = -1;
1073     size->cvt_ready      = -1;
1074 
1075     size->context = TT_New_Context( (TT_Driver)face->root.driver );
1076 
1077     size->max_function_defs    = maxp->maxFunctionDefs;
1078     size->max_instruction_defs = maxp->maxInstructionDefs;
1079 
1080     size->num_function_defs    = 0;
1081     size->num_instruction_defs = 0;
1082 
1083     size->max_func = 0;
1084     size->max_ins  = 0;
1085 
1086     size->cvt_size     = face->cvt_size;
1087     size->storage_size = maxp->maxStorage;
1088 
1089     /* Set default metrics */
1090     {
1091       TT_Size_Metrics*  tt_metrics = &size->ttmetrics;
1092 
1093 
1094       tt_metrics->rotated   = FALSE;
1095       tt_metrics->stretched = FALSE;
1096 
1097       /* set default engine compensation */
1098       tt_metrics->compensations[0] = 0;   /* gray     */
1099       tt_metrics->compensations[1] = 0;   /* black    */
1100       tt_metrics->compensations[2] = 0;   /* white    */
1101       tt_metrics->compensations[3] = 0;   /* reserved */
1102     }
1103 
1104     /* allocate function defs, instruction defs, cvt, and storage area */
1105     if ( FT_NEW_ARRAY( size->function_defs,    size->max_function_defs    ) ||
1106          FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) ||
1107          FT_NEW_ARRAY( size->cvt,              size->cvt_size             ) ||
1108          FT_NEW_ARRAY( size->storage,          size->storage_size         ) )
1109       goto Exit;
1110 
1111     /* reserve twilight zone */
1112     n_twilight = maxp->maxTwilightPoints;
1113 
1114     /* there are 4 phantom points (do we need this?) */
1115     n_twilight += 4;
1116 
1117     error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight );
1118     if ( error )
1119       goto Exit;
1120 
1121     size->twilight.n_points = n_twilight;
1122 
1123     size->GS = tt_default_graphics_state;
1124 
1125     /* set `face->interpreter' according to the debug hook present */
1126     {
1127       FT_Library  library = face->root.driver->root.library;
1128 
1129 
1130       face->interpreter = (TT_Interpreter)
1131                             library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE];
1132       if ( !face->interpreter )
1133         face->interpreter = (TT_Interpreter)TT_RunIns;
1134     }
1135 
1136     /* Fine, now run the font program! */
1137 
1138     /* In case of an error while executing `fpgm', we intentionally don't */
1139     /* clean up immediately – bugs in the `fpgm' are so fundamental that  */
1140     /* all following hinting calls should fail.  Additionally, `fpgm' is  */
1141     /* to be executed just once; calling it again is completely useless   */
1142     /* and might even lead to extremely slow behaviour if it is malformed */
1143     /* (containing an infinite loop, for example).                        */
1144     error = tt_size_run_fpgm( size, pedantic );
1145     return error;
1146 
1147   Exit:
1148     if ( error )
1149       tt_size_done_bytecode( ftsize );
1150 
1151     return error;
1152   }
1153 
1154 
1155   FT_LOCAL_DEF( FT_Error )
tt_size_ready_bytecode(TT_Size size,FT_Bool pedantic)1156   tt_size_ready_bytecode( TT_Size  size,
1157                           FT_Bool  pedantic )
1158   {
1159     FT_Error  error = FT_Err_Ok;
1160 
1161 
1162     if ( size->bytecode_ready < 0 )
1163       error = tt_size_init_bytecode( (FT_Size)size, pedantic );
1164     else
1165       error = size->bytecode_ready;
1166 
1167     if ( error )
1168       goto Exit;
1169 
1170     /* rescale CVT when needed */
1171     if ( size->cvt_ready < 0 )
1172     {
1173       FT_UInt  i;
1174       TT_Face  face = (TT_Face)size->root.face;
1175 
1176 
1177       /* Scale the cvt values to the new ppem.          */
1178       /* We use by default the y ppem to scale the CVT. */
1179       for ( i = 0; i < size->cvt_size; i++ )
1180         size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
1181 
1182       /* all twilight points are originally zero */
1183       for ( i = 0; i < (FT_UInt)size->twilight.n_points; i++ )
1184       {
1185         size->twilight.org[i].x = 0;
1186         size->twilight.org[i].y = 0;
1187         size->twilight.cur[i].x = 0;
1188         size->twilight.cur[i].y = 0;
1189       }
1190 
1191       /* clear storage area */
1192       for ( i = 0; i < (FT_UInt)size->storage_size; i++ )
1193         size->storage[i] = 0;
1194 
1195       size->GS = tt_default_graphics_state;
1196 
1197       error = tt_size_run_prep( size, pedantic );
1198     }
1199     else
1200       error = size->cvt_ready;
1201 
1202   Exit:
1203     return error;
1204   }
1205 
1206 #endif /* TT_USE_BYTECODE_INTERPRETER */
1207 
1208 
1209   /**************************************************************************
1210    *
1211    * @Function:
1212    *   tt_size_init
1213    *
1214    * @Description:
1215    *   Initialize a new TrueType size object.
1216    *
1217    * @InOut:
1218    *   size ::
1219    *     A handle to the size object.
1220    *
1221    * @Return:
1222    *   FreeType error code.  0 means success.
1223    */
1224   FT_LOCAL_DEF( FT_Error )
tt_size_init(FT_Size ttsize)1225   tt_size_init( FT_Size  ttsize )           /* TT_Size */
1226   {
1227     TT_Size   size  = (TT_Size)ttsize;
1228     FT_Error  error = FT_Err_Ok;
1229 
1230 
1231 #ifdef TT_USE_BYTECODE_INTERPRETER
1232     size->bytecode_ready = -1;
1233     size->cvt_ready      = -1;
1234 #endif
1235 
1236     size->ttmetrics.valid = FALSE;
1237     size->strike_index    = 0xFFFFFFFFUL;
1238 
1239     return error;
1240   }
1241 
1242 
1243   /**************************************************************************
1244    *
1245    * @Function:
1246    *   tt_size_done
1247    *
1248    * @Description:
1249    *   The TrueType size object finalizer.
1250    *
1251    * @Input:
1252    *   size ::
1253    *     A handle to the target size object.
1254    */
1255   FT_LOCAL_DEF( void )
tt_size_done(FT_Size ttsize)1256   tt_size_done( FT_Size  ttsize )           /* TT_Size */
1257   {
1258     TT_Size  size = (TT_Size)ttsize;
1259 
1260 
1261 #ifdef TT_USE_BYTECODE_INTERPRETER
1262     tt_size_done_bytecode( ttsize );
1263 #endif
1264 
1265     size->ttmetrics.valid = FALSE;
1266   }
1267 
1268 
1269   /**************************************************************************
1270    *
1271    * @Function:
1272    *   tt_size_reset
1273    *
1274    * @Description:
1275    *   Reset a TrueType size when resolutions and character dimensions
1276    *   have been changed.
1277    *
1278    * @Input:
1279    *   size ::
1280    *     A handle to the target size object.
1281    *
1282    *   only_height ::
1283    *     Only recompute ascender, descender, and height;
1284    *     this flag is used for variation fonts where
1285    *     `tt_size_reset' is used as an iterator function.
1286    */
1287   FT_LOCAL_DEF( FT_Error )
tt_size_reset(TT_Size size,FT_Bool only_height)1288   tt_size_reset( TT_Size  size,
1289                  FT_Bool  only_height )
1290   {
1291     TT_Face           face;
1292     FT_Size_Metrics*  size_metrics;
1293 
1294 
1295     face = (TT_Face)size->root.face;
1296 
1297     /* nothing to do for CFF2 */
1298     if ( face->is_cff2 )
1299       return FT_Err_Ok;
1300 
1301     size->ttmetrics.valid = FALSE;
1302 
1303     size_metrics = &size->hinted_metrics;
1304 
1305     /* copy the result from base layer */
1306     *size_metrics = size->root.metrics;
1307 
1308     if ( size_metrics->x_ppem < 1 || size_metrics->y_ppem < 1 )
1309       return FT_THROW( Invalid_PPem );
1310 
1311     /* This bit flag, if set, indicates that the ppems must be       */
1312     /* rounded to integers.  Nearly all TrueType fonts have this bit */
1313     /* set, as hinting won't work really well otherwise.             */
1314     /*                                                               */
1315     if ( face->header.Flags & 8 )
1316     {
1317       /* the TT spec always asks for ROUND, not FLOOR or CEIL */
1318       size_metrics->ascender = FT_PIX_ROUND(
1319                                  FT_MulFix( face->root.ascender,
1320                                             size_metrics->y_scale ) );
1321       size_metrics->descender = FT_PIX_ROUND(
1322                                  FT_MulFix( face->root.descender,
1323                                             size_metrics->y_scale ) );
1324       size_metrics->height = FT_PIX_ROUND(
1325                                FT_MulFix( face->root.height,
1326                                           size_metrics->y_scale ) );
1327     }
1328 
1329     size->ttmetrics.valid = TRUE;
1330 
1331     if ( only_height )
1332     {
1333       /* we must not recompute the scaling values here since       */
1334       /* `tt_size_reset' was already called (with only_height = 0) */
1335       return FT_Err_Ok;
1336     }
1337 
1338     if ( face->header.Flags & 8 )
1339     {
1340       /* base scaling values on integer ppem values, */
1341       /* as mandated by the TrueType specification   */
1342       size_metrics->x_scale = FT_DivFix( size_metrics->x_ppem << 6,
1343                                          face->root.units_per_EM );
1344       size_metrics->y_scale = FT_DivFix( size_metrics->y_ppem << 6,
1345                                          face->root.units_per_EM );
1346 
1347       size_metrics->max_advance = FT_PIX_ROUND(
1348                                     FT_MulFix( face->root.max_advance_width,
1349                                                size_metrics->x_scale ) );
1350     }
1351 
1352     /* compute new transformation */
1353     if ( size_metrics->x_ppem >= size_metrics->y_ppem )
1354     {
1355       size->ttmetrics.scale   = size_metrics->x_scale;
1356       size->ttmetrics.ppem    = size_metrics->x_ppem;
1357       size->ttmetrics.x_ratio = 0x10000L;
1358       size->ttmetrics.y_ratio = FT_DivFix( size_metrics->y_ppem,
1359                                            size_metrics->x_ppem );
1360     }
1361     else
1362     {
1363       size->ttmetrics.scale   = size_metrics->y_scale;
1364       size->ttmetrics.ppem    = size_metrics->y_ppem;
1365       size->ttmetrics.x_ratio = FT_DivFix( size_metrics->x_ppem,
1366                                            size_metrics->y_ppem );
1367       size->ttmetrics.y_ratio = 0x10000L;
1368     }
1369 
1370     size->metrics = size_metrics;
1371 
1372 #ifdef TT_USE_BYTECODE_INTERPRETER
1373     size->cvt_ready = -1;
1374 #endif /* TT_USE_BYTECODE_INTERPRETER */
1375 
1376     return FT_Err_Ok;
1377   }
1378 
1379 
1380   /**************************************************************************
1381    *
1382    * @Function:
1383    *   tt_driver_init
1384    *
1385    * @Description:
1386    *   Initialize a given TrueType driver object.
1387    *
1388    * @Input:
1389    *   driver ::
1390    *     A handle to the target driver object.
1391    *
1392    * @Return:
1393    *   FreeType error code.  0 means success.
1394    */
1395   FT_LOCAL_DEF( FT_Error )
tt_driver_init(FT_Module ttdriver)1396   tt_driver_init( FT_Module  ttdriver )     /* TT_Driver */
1397   {
1398 
1399 #ifdef TT_USE_BYTECODE_INTERPRETER
1400 
1401     TT_Driver  driver = (TT_Driver)ttdriver;
1402 
1403     driver->interpreter_version = TT_INTERPRETER_VERSION_35;
1404 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
1405     driver->interpreter_version = TT_INTERPRETER_VERSION_38;
1406 #endif
1407 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
1408     driver->interpreter_version = TT_INTERPRETER_VERSION_40;
1409 #endif
1410 
1411 #else /* !TT_USE_BYTECODE_INTERPRETER */
1412 
1413     FT_UNUSED( ttdriver );
1414 
1415 #endif /* !TT_USE_BYTECODE_INTERPRETER */
1416 
1417     return FT_Err_Ok;
1418   }
1419 
1420 
1421   /**************************************************************************
1422    *
1423    * @Function:
1424    *   tt_driver_done
1425    *
1426    * @Description:
1427    *   Finalize a given TrueType driver.
1428    *
1429    * @Input:
1430    *   driver ::
1431    *     A handle to the target TrueType driver.
1432    */
1433   FT_LOCAL_DEF( void )
tt_driver_done(FT_Module ttdriver)1434   tt_driver_done( FT_Module  ttdriver )     /* TT_Driver */
1435   {
1436     FT_UNUSED( ttdriver );
1437   }
1438 
1439 
1440   /**************************************************************************
1441    *
1442    * @Function:
1443    *   tt_slot_init
1444    *
1445    * @Description:
1446    *   Initialize a new slot object.
1447    *
1448    * @InOut:
1449    *   slot ::
1450    *     A handle to the slot object.
1451    *
1452    * @Return:
1453    *   FreeType error code.  0 means success.
1454    */
1455   FT_LOCAL_DEF( FT_Error )
tt_slot_init(FT_GlyphSlot slot)1456   tt_slot_init( FT_GlyphSlot  slot )
1457   {
1458     return FT_GlyphLoader_CreateExtra( slot->internal->loader );
1459   }
1460 
1461 
1462 /* END */
1463