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