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