Home | History | Annotate | Line # | Download | only in truetype
      1 /****************************************************************************
      2  *
      3  * ttpload.c
      4  *
      5  *   TrueType-specific tables loader (body).
      6  *
      7  * Copyright (C) 1996-2020 by
      8  * David Turner, Robert Wilhelm, and Werner Lemberg.
      9  *
     10  * This file is part of the FreeType project, and may only be used,
     11  * modified, and distributed under the terms of the FreeType project
     12  * license, LICENSE.TXT.  By continuing to use, modify, or distribute
     13  * this file you indicate that you have read the license and
     14  * understand and accept it fully.
     15  *
     16  */
     17 
     18 
     19 #include <freetype/internal/ftdebug.h>
     20 #include <freetype/internal/ftobjs.h>
     21 #include <freetype/internal/ftstream.h>
     22 #include <freetype/tttags.h>
     23 
     24 #include "ttpload.h"
     25 
     26 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
     27 #include "ttgxvar.h"
     28 #endif
     29 
     30 #include "tterrors.h"
     31 
     32 
     33   /**************************************************************************
     34    *
     35    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
     36    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
     37    * messages during execution.
     38    */
     39 #undef  FT_COMPONENT
     40 #define FT_COMPONENT  ttpload
     41 
     42 
     43   /**************************************************************************
     44    *
     45    * @Function:
     46    *   tt_face_load_loca
     47    *
     48    * @Description:
     49    *   Load the locations table.
     50    *
     51    * @InOut:
     52    *   face ::
     53    *     A handle to the target face object.
     54    *
     55    * @Input:
     56    *   stream ::
     57    *     The input stream.
     58    *
     59    * @Return:
     60    *   FreeType error code.  0 means success.
     61    */
     62   FT_LOCAL_DEF( FT_Error )
     63   tt_face_load_loca( TT_Face    face,
     64                      FT_Stream  stream )
     65   {
     66     FT_Error  error;
     67     FT_ULong  table_len;
     68     FT_Int    shift;
     69 
     70 
     71     /* we need the size of the `glyf' table for malformed `loca' tables */
     72     error = face->goto_table( face, TTAG_glyf, stream, &face->glyf_len );
     73 
     74     /* it is possible that a font doesn't have a glyf table at all */
     75     /* or its size is zero                                         */
     76     if ( FT_ERR_EQ( error, Table_Missing ) )
     77     {
     78       face->glyf_len    = 0;
     79       face->glyf_offset = 0;
     80     }
     81     else if ( error )
     82       goto Exit;
     83     else
     84     {
     85 #ifdef FT_CONFIG_OPTION_INCREMENTAL
     86       if ( face->root.internal->incremental_interface )
     87         face->glyf_offset = 0;
     88       else
     89 #endif
     90         face->glyf_offset = FT_STREAM_POS();
     91     }
     92 
     93     FT_TRACE2(( "Locations " ));
     94     error = face->goto_table( face, TTAG_loca, stream, &table_len );
     95     if ( error )
     96     {
     97       error = FT_THROW( Locations_Missing );
     98       goto Exit;
     99     }
    100 
    101     if ( face->header.Index_To_Loc_Format != 0 )
    102     {
    103       shift = 2;
    104 
    105       if ( table_len >= 0x40000L )
    106       {
    107         FT_TRACE2(( "table too large\n" ));
    108         table_len = 0x3FFFFL;
    109       }
    110       face->num_locations = table_len >> shift;
    111     }
    112     else
    113     {
    114       shift = 1;
    115 
    116       if ( table_len >= 0x20000L )
    117       {
    118         FT_TRACE2(( "table too large\n" ));
    119         table_len = 0x1FFFFL;
    120       }
    121       face->num_locations = table_len >> shift;
    122     }
    123 
    124     if ( face->num_locations != (FT_ULong)face->root.num_glyphs + 1 )
    125     {
    126       FT_TRACE2(( "glyph count mismatch!  loca: %ld, maxp: %ld\n",
    127                   face->num_locations - 1, face->root.num_glyphs ));
    128 
    129       /* we only handle the case where `maxp' gives a larger value */
    130       if ( face->num_locations <= (FT_ULong)face->root.num_glyphs )
    131       {
    132         FT_ULong  new_loca_len =
    133                     ( (FT_ULong)face->root.num_glyphs + 1 ) << shift;
    134 
    135         TT_Table  entry = face->dir_tables;
    136         TT_Table  limit = entry + face->num_tables;
    137 
    138         FT_Long  pos   = (FT_Long)FT_STREAM_POS();
    139         FT_Long  dist  = 0x7FFFFFFFL;
    140         FT_Bool  found = 0;
    141 
    142 
    143         /* compute the distance to next table in font file */
    144         for ( ; entry < limit; entry++ )
    145         {
    146           FT_Long  diff = (FT_Long)entry->Offset - pos;
    147 
    148 
    149           if ( diff > 0 && diff < dist )
    150           {
    151             dist  = diff;
    152             found = 1;
    153           }
    154         }
    155 
    156         if ( !found )
    157         {
    158           /* `loca' is the last table */
    159           dist = (FT_Long)stream->size - pos;
    160         }
    161 
    162         if ( new_loca_len <= (FT_ULong)dist )
    163         {
    164           face->num_locations = (FT_ULong)face->root.num_glyphs + 1;
    165           table_len           = new_loca_len;
    166 
    167           FT_TRACE2(( "adjusting num_locations to %ld\n",
    168                       face->num_locations ));
    169         }
    170         else
    171         {
    172           face->root.num_glyphs = face->num_locations
    173                                     ? (FT_Long)face->num_locations - 1 : 0;
    174 
    175           FT_TRACE2(( "adjusting num_glyphs to %ld\n",
    176                       face->root.num_glyphs ));
    177         }
    178       }
    179     }
    180 
    181     /*
    182      * Extract the frame.  We don't need to decompress it since
    183      * we are able to parse it directly.
    184      */
    185     if ( FT_FRAME_EXTRACT( table_len, face->glyph_locations ) )
    186       goto Exit;
    187 
    188     FT_TRACE2(( "loaded\n" ));
    189 
    190   Exit:
    191     return error;
    192   }
    193 
    194 
    195   FT_LOCAL_DEF( FT_ULong )
    196   tt_face_get_location( TT_Face   face,
    197                         FT_UInt   gindex,
    198                         FT_UInt  *asize )
    199   {
    200     FT_ULong  pos1, pos2;
    201     FT_Byte*  p;
    202     FT_Byte*  p_limit;
    203 
    204 
    205     pos1 = pos2 = 0;
    206 
    207     if ( gindex < face->num_locations )
    208     {
    209       if ( face->header.Index_To_Loc_Format != 0 )
    210       {
    211         p       = face->glyph_locations + gindex * 4;
    212         p_limit = face->glyph_locations + face->num_locations * 4;
    213 
    214         pos1 = FT_NEXT_ULONG( p );
    215         pos2 = pos1;
    216 
    217         if ( p + 4 <= p_limit )
    218           pos2 = FT_NEXT_ULONG( p );
    219       }
    220       else
    221       {
    222         p       = face->glyph_locations + gindex * 2;
    223         p_limit = face->glyph_locations + face->num_locations * 2;
    224 
    225         pos1 = FT_NEXT_USHORT( p );
    226         pos2 = pos1;
    227 
    228         if ( p + 2 <= p_limit )
    229           pos2 = FT_NEXT_USHORT( p );
    230 
    231         pos1 <<= 1;
    232         pos2 <<= 1;
    233       }
    234     }
    235 
    236     /* Check broken location data. */
    237     if ( pos1 > face->glyf_len )
    238     {
    239       FT_TRACE1(( "tt_face_get_location:"
    240                   " too large offset (0x%08lx) found for glyph index %d,\n"
    241                   "                     "
    242                   " exceeding the end of `glyf' table (0x%08lx)\n",
    243                   pos1, gindex, face->glyf_len ));
    244       *asize = 0;
    245       return 0;
    246     }
    247 
    248     if ( pos2 > face->glyf_len )
    249     {
    250       /* We try to sanitize the last `loca' entry. */
    251       if ( gindex == face->num_locations - 2 )
    252       {
    253         FT_TRACE1(( "tt_face_get_location:"
    254                     " too large size (%ld bytes) found for glyph index %d,\n"
    255                     "                     "
    256                     " truncating at the end of `glyf' table to %ld bytes\n",
    257                     pos2 - pos1, gindex, face->glyf_len - pos1 ));
    258         pos2 = face->glyf_len;
    259       }
    260       else
    261       {
    262         FT_TRACE1(( "tt_face_get_location:"
    263                     " too large offset (0x%08lx) found for glyph index %d,\n"
    264                     "                     "
    265                     " exceeding the end of `glyf' table (0x%08lx)\n",
    266                     pos2, gindex + 1, face->glyf_len ));
    267         *asize = 0;
    268         return 0;
    269       }
    270     }
    271 
    272     /* The `loca' table must be ordered; it refers to the length of */
    273     /* an entry as the difference between the current and the next  */
    274     /* position.  However, there do exist (malformed) fonts which   */
    275     /* don't obey this rule, so we are only able to provide an      */
    276     /* upper bound for the size.                                    */
    277     /*                                                              */
    278     /* We get (intentionally) a wrong, non-zero result in case the  */
    279     /* `glyf' table is missing.                                     */
    280     if ( pos2 >= pos1 )
    281       *asize = (FT_UInt)( pos2 - pos1 );
    282     else
    283       *asize = (FT_UInt)( face->glyf_len - pos1 );
    284 
    285     return pos1;
    286   }
    287 
    288 
    289   FT_LOCAL_DEF( void )
    290   tt_face_done_loca( TT_Face  face )
    291   {
    292     FT_Stream  stream = face->root.stream;
    293 
    294 
    295     FT_FRAME_RELEASE( face->glyph_locations );
    296     face->num_locations = 0;
    297   }
    298 
    299 
    300 
    301   /**************************************************************************
    302    *
    303    * @Function:
    304    *   tt_face_load_cvt
    305    *
    306    * @Description:
    307    *   Load the control value table into a face object.
    308    *
    309    * @InOut:
    310    *   face ::
    311    *     A handle to the target face object.
    312    *
    313    * @Input:
    314    *   stream ::
    315    *     A handle to the input stream.
    316    *
    317    * @Return:
    318    *   FreeType error code.  0 means success.
    319    */
    320   FT_LOCAL_DEF( FT_Error )
    321   tt_face_load_cvt( TT_Face    face,
    322                     FT_Stream  stream )
    323   {
    324 #ifdef TT_USE_BYTECODE_INTERPRETER
    325 
    326     FT_Error   error;
    327     FT_Memory  memory = stream->memory;
    328     FT_ULong   table_len;
    329 
    330 
    331     FT_TRACE2(( "CVT " ));
    332 
    333     error = face->goto_table( face, TTAG_cvt, stream, &table_len );
    334     if ( error )
    335     {
    336       FT_TRACE2(( "is missing\n" ));
    337 
    338       face->cvt_size = 0;
    339       face->cvt      = NULL;
    340       error          = FT_Err_Ok;
    341 
    342       goto Exit;
    343     }
    344 
    345     face->cvt_size = table_len / 2;
    346 
    347     if ( FT_NEW_ARRAY( face->cvt, face->cvt_size ) )
    348       goto Exit;
    349 
    350     if ( FT_FRAME_ENTER( face->cvt_size * 2L ) )
    351       goto Exit;
    352 
    353     {
    354       FT_Int32*  cur   = face->cvt;
    355       FT_Int32*  limit = cur + face->cvt_size;
    356 
    357 
    358       for ( ; cur < limit; cur++ )
    359         *cur = FT_GET_SHORT() * 64;
    360     }
    361 
    362     FT_FRAME_EXIT();
    363     FT_TRACE2(( "loaded\n" ));
    364 
    365 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    366     if ( face->doblend )
    367       error = tt_face_vary_cvt( face, stream );
    368 #endif
    369 
    370   Exit:
    371     return error;
    372 
    373 #else /* !TT_USE_BYTECODE_INTERPRETER */
    374 
    375     FT_UNUSED( face   );
    376     FT_UNUSED( stream );
    377 
    378     return FT_Err_Ok;
    379 
    380 #endif
    381   }
    382 
    383 
    384   /**************************************************************************
    385    *
    386    * @Function:
    387    *   tt_face_load_fpgm
    388    *
    389    * @Description:
    390    *   Load the font program.
    391    *
    392    * @InOut:
    393    *   face ::
    394    *     A handle to the target face object.
    395    *
    396    * @Input:
    397    *   stream ::
    398    *     A handle to the input stream.
    399    *
    400    * @Return:
    401    *   FreeType error code.  0 means success.
    402    */
    403   FT_LOCAL_DEF( FT_Error )
    404   tt_face_load_fpgm( TT_Face    face,
    405                      FT_Stream  stream )
    406   {
    407 #ifdef TT_USE_BYTECODE_INTERPRETER
    408 
    409     FT_Error  error;
    410     FT_ULong  table_len;
    411 
    412 
    413     FT_TRACE2(( "Font program " ));
    414 
    415     /* The font program is optional */
    416     error = face->goto_table( face, TTAG_fpgm, stream, &table_len );
    417     if ( error )
    418     {
    419       face->font_program      = NULL;
    420       face->font_program_size = 0;
    421       error                   = FT_Err_Ok;
    422 
    423       FT_TRACE2(( "is missing\n" ));
    424     }
    425     else
    426     {
    427       face->font_program_size = table_len;
    428       if ( FT_FRAME_EXTRACT( table_len, face->font_program ) )
    429         goto Exit;
    430 
    431       FT_TRACE2(( "loaded, %12ld bytes\n", face->font_program_size ));
    432     }
    433 
    434   Exit:
    435     return error;
    436 
    437 #else /* !TT_USE_BYTECODE_INTERPRETER */
    438 
    439     FT_UNUSED( face   );
    440     FT_UNUSED( stream );
    441 
    442     return FT_Err_Ok;
    443 
    444 #endif
    445   }
    446 
    447 
    448   /**************************************************************************
    449    *
    450    * @Function:
    451    *   tt_face_load_prep
    452    *
    453    * @Description:
    454    *   Load the cvt program.
    455    *
    456    * @InOut:
    457    *   face ::
    458    *     A handle to the target face object.
    459    *
    460    * @Input:
    461    *   stream ::
    462    *     A handle to the input stream.
    463    *
    464    * @Return:
    465    *   FreeType error code.  0 means success.
    466    */
    467   FT_LOCAL_DEF( FT_Error )
    468   tt_face_load_prep( TT_Face    face,
    469                      FT_Stream  stream )
    470   {
    471 #ifdef TT_USE_BYTECODE_INTERPRETER
    472 
    473     FT_Error  error;
    474     FT_ULong  table_len;
    475 
    476 
    477     FT_TRACE2(( "Prep program " ));
    478 
    479     error = face->goto_table( face, TTAG_prep, stream, &table_len );
    480     if ( error )
    481     {
    482       face->cvt_program      = NULL;
    483       face->cvt_program_size = 0;
    484       error                  = FT_Err_Ok;
    485 
    486       FT_TRACE2(( "is missing\n" ));
    487     }
    488     else
    489     {
    490       face->cvt_program_size = table_len;
    491       if ( FT_FRAME_EXTRACT( table_len, face->cvt_program ) )
    492         goto Exit;
    493 
    494       FT_TRACE2(( "loaded, %12ld bytes\n", face->cvt_program_size ));
    495     }
    496 
    497   Exit:
    498     return error;
    499 
    500 #else /* !TT_USE_BYTECODE_INTERPRETER */
    501 
    502     FT_UNUSED( face   );
    503     FT_UNUSED( stream );
    504 
    505     return FT_Err_Ok;
    506 
    507 #endif
    508   }
    509 
    510 
    511   /**************************************************************************
    512    *
    513    * @Function:
    514    *   tt_face_load_hdmx
    515    *
    516    * @Description:
    517    *   Load the `hdmx' table into the face object.
    518    *
    519    * @Input:
    520    *   face ::
    521    *     A handle to the target face object.
    522    *
    523    *   stream ::
    524    *     A handle to the input stream.
    525    *
    526    * @Return:
    527    *   FreeType error code.  0 means success.
    528    */
    529 
    530   FT_LOCAL_DEF( FT_Error )
    531   tt_face_load_hdmx( TT_Face    face,
    532                      FT_Stream  stream )
    533   {
    534     FT_Error   error;
    535     FT_Memory  memory = stream->memory;
    536     FT_UInt    nn, num_records;
    537     FT_ULong   table_size, record_size;
    538     FT_Byte*   p;
    539     FT_Byte*   limit;
    540 
    541 
    542     /* this table is optional */
    543     error = face->goto_table( face, TTAG_hdmx, stream, &table_size );
    544     if ( error || table_size < 8 )
    545       return FT_Err_Ok;
    546 
    547     if ( FT_FRAME_EXTRACT( table_size, face->hdmx_table ) )
    548       goto Exit;
    549 
    550     p     = face->hdmx_table;
    551     limit = p + table_size;
    552 
    553     /* Given that `hdmx' tables are losing its importance (for example, */
    554     /* variation fonts introduced in OpenType 1.8 must not have this    */
    555     /* table) we no longer test for a correct `version' field.          */
    556     p          += 2;
    557     num_records = FT_NEXT_USHORT( p );
    558     record_size = FT_NEXT_ULONG( p );
    559 
    560     /* The maximum number of bytes in an hdmx device record is the */
    561     /* maximum number of glyphs + 2; this is 0xFFFF + 2, thus      */
    562     /* explaining why `record_size' is a long (which we read as    */
    563     /* unsigned long for convenience).  In practice, two bytes are */
    564     /* sufficient to hold the size value.                          */
    565     /*                                                             */
    566     /* There are at least two fonts, HANNOM-A and HANNOM-B version */
    567     /* 2.0 (2005), which get this wrong: The upper two bytes of    */
    568     /* the size value are set to 0xFF instead of 0x00.  We catch   */
    569     /* and fix this.                                               */
    570 
    571     if ( record_size >= 0xFFFF0000UL )
    572       record_size &= 0xFFFFU;
    573 
    574     /* The limit for `num_records' is a heuristic value. */
    575     if ( num_records > 255              ||
    576          ( num_records > 0            &&
    577            ( record_size > 0x10001L ||
    578              record_size < 4        ) ) )
    579     {
    580       error = FT_THROW( Invalid_File_Format );
    581       goto Fail;
    582     }
    583 
    584     if ( FT_NEW_ARRAY( face->hdmx_record_sizes, num_records ) )
    585       goto Fail;
    586 
    587     for ( nn = 0; nn < num_records; nn++ )
    588     {
    589       if ( p + record_size > limit )
    590         break;
    591 
    592       face->hdmx_record_sizes[nn] = p[0];
    593       p                          += record_size;
    594     }
    595 
    596     face->hdmx_record_count = nn;
    597     face->hdmx_table_size   = table_size;
    598     face->hdmx_record_size  = record_size;
    599 
    600   Exit:
    601     return error;
    602 
    603   Fail:
    604     FT_FRAME_RELEASE( face->hdmx_table );
    605     face->hdmx_table_size = 0;
    606     goto Exit;
    607   }
    608 
    609 
    610   FT_LOCAL_DEF( void )
    611   tt_face_free_hdmx( TT_Face  face )
    612   {
    613     FT_Stream  stream = face->root.stream;
    614     FT_Memory  memory = stream->memory;
    615 
    616 
    617     FT_FREE( face->hdmx_record_sizes );
    618     FT_FRAME_RELEASE( face->hdmx_table );
    619   }
    620 
    621 
    622   /**************************************************************************
    623    *
    624    * Return the advance width table for a given pixel size if it is found
    625    * in the font's `hdmx' table (if any).
    626    */
    627   FT_LOCAL_DEF( FT_Byte* )
    628   tt_face_get_device_metrics( TT_Face  face,
    629                               FT_UInt  ppem,
    630                               FT_UInt  gindex )
    631   {
    632     FT_UInt   nn;
    633     FT_Byte*  result      = NULL;
    634     FT_ULong  record_size = face->hdmx_record_size;
    635     FT_Byte*  record      = FT_OFFSET( face->hdmx_table, 8 );
    636 
    637 
    638     for ( nn = 0; nn < face->hdmx_record_count; nn++ )
    639       if ( face->hdmx_record_sizes[nn] == ppem )
    640       {
    641         gindex += 2;
    642         if ( gindex < record_size )
    643           result = record + nn * record_size + gindex;
    644         break;
    645       }
    646 
    647     return result;
    648   }
    649 
    650 
    651 /* END */
    652