Home | History | Annotate | Download | only in sfnt
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  ttmtx.c                                                                */
      4 /*                                                                         */
      5 /*    Load the metrics tables common to TTF and OTF fonts (body).          */
      6 /*                                                                         */
      7 /*  Copyright 2006-2017 by                                                 */
      8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
      9 /*                                                                         */
     10 /*  This file is part of the FreeType project, and may only be used,       */
     11 /*  modified, and distributed under the terms of the FreeType project      */
     12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
     13 /*  this file you indicate that you have read the license and              */
     14 /*  understand and accept it fully.                                        */
     15 /*                                                                         */
     16 /***************************************************************************/
     17 
     18 
     19 #include <ft2build.h>
     20 #include FT_INTERNAL_DEBUG_H
     21 #include FT_INTERNAL_STREAM_H
     22 #include FT_TRUETYPE_TAGS_H
     23 
     24 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
     25 #include FT_SERVICE_METRICS_VARIATIONS_H
     26 #endif
     27 
     28 #include "ttmtx.h"
     29 
     30 #include "sferrors.h"
     31 
     32 
     33   /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should   */
     34   /*            be identical except for the names of their fields,      */
     35   /*            which are different.                                    */
     36   /*                                                                    */
     37   /*            This ensures that `tt_face_load_hmtx' is able to read   */
     38   /*            both the horizontal and vertical headers.               */
     39 
     40 
     41   /*************************************************************************/
     42   /*                                                                       */
     43   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
     44   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
     45   /* messages during execution.                                            */
     46   /*                                                                       */
     47 #undef  FT_COMPONENT
     48 #define FT_COMPONENT  trace_ttmtx
     49 
     50 
     51   /*************************************************************************/
     52   /*                                                                       */
     53   /* <Function>                                                            */
     54   /*    tt_face_load_hmtx                                                  */
     55   /*                                                                       */
     56   /* <Description>                                                         */
     57   /*    Load the `hmtx' or `vmtx' table into a face object.                */
     58   /*                                                                       */
     59   /* <Input>                                                               */
     60   /*    face     :: A handle to the target face object.                    */
     61   /*                                                                       */
     62   /*    stream   :: The input stream.                                      */
     63   /*                                                                       */
     64   /*    vertical :: A boolean flag.  If set, load `vmtx'.                  */
     65   /*                                                                       */
     66   /* <Return>                                                              */
     67   /*    FreeType error code.  0 means success.                             */
     68   /*                                                                       */
     69   FT_LOCAL_DEF( FT_Error )
     70   tt_face_load_hmtx( TT_Face    face,
     71                      FT_Stream  stream,
     72                      FT_Bool    vertical )
     73   {
     74     FT_Error   error;
     75     FT_ULong   tag, table_size;
     76     FT_ULong*  ptable_offset;
     77     FT_ULong*  ptable_size;
     78 
     79 
     80     if ( vertical )
     81     {
     82       tag           = TTAG_vmtx;
     83       ptable_offset = &face->vert_metrics_offset;
     84       ptable_size   = &face->vert_metrics_size;
     85     }
     86     else
     87     {
     88       tag           = TTAG_hmtx;
     89       ptable_offset = &face->horz_metrics_offset;
     90       ptable_size   = &face->horz_metrics_size;
     91     }
     92 
     93     error = face->goto_table( face, tag, stream, &table_size );
     94     if ( error )
     95       goto Fail;
     96 
     97     *ptable_size   = table_size;
     98     *ptable_offset = FT_STREAM_POS();
     99 
    100   Fail:
    101     return error;
    102   }
    103 
    104 
    105   /*************************************************************************/
    106   /*                                                                       */
    107   /* <Function>                                                            */
    108   /*    tt_face_load_hhea                                                  */
    109   /*                                                                       */
    110   /* <Description>                                                         */
    111   /*    Load the `hhea' or 'vhea' table into a face object.                */
    112   /*                                                                       */
    113   /* <Input>                                                               */
    114   /*    face     :: A handle to the target face object.                    */
    115   /*                                                                       */
    116   /*    stream   :: The input stream.                                      */
    117   /*                                                                       */
    118   /*    vertical :: A boolean flag.  If set, load `vhea'.                  */
    119   /*                                                                       */
    120   /* <Return>                                                              */
    121   /*    FreeType error code.  0 means success.                             */
    122   /*                                                                       */
    123   FT_LOCAL_DEF( FT_Error )
    124   tt_face_load_hhea( TT_Face    face,
    125                      FT_Stream  stream,
    126                      FT_Bool    vertical )
    127   {
    128     FT_Error        error;
    129     TT_HoriHeader*  header;
    130 
    131     static const FT_Frame_Field  metrics_header_fields[] =
    132     {
    133 #undef  FT_STRUCTURE
    134 #define FT_STRUCTURE  TT_HoriHeader
    135 
    136       FT_FRAME_START( 36 ),
    137         FT_FRAME_ULONG ( Version ),
    138         FT_FRAME_SHORT ( Ascender ),
    139         FT_FRAME_SHORT ( Descender ),
    140         FT_FRAME_SHORT ( Line_Gap ),
    141         FT_FRAME_USHORT( advance_Width_Max ),
    142         FT_FRAME_SHORT ( min_Left_Side_Bearing ),
    143         FT_FRAME_SHORT ( min_Right_Side_Bearing ),
    144         FT_FRAME_SHORT ( xMax_Extent ),
    145         FT_FRAME_SHORT ( caret_Slope_Rise ),
    146         FT_FRAME_SHORT ( caret_Slope_Run ),
    147         FT_FRAME_SHORT ( caret_Offset ),
    148         FT_FRAME_SHORT ( Reserved[0] ),
    149         FT_FRAME_SHORT ( Reserved[1] ),
    150         FT_FRAME_SHORT ( Reserved[2] ),
    151         FT_FRAME_SHORT ( Reserved[3] ),
    152         FT_FRAME_SHORT ( metric_Data_Format ),
    153         FT_FRAME_USHORT( number_Of_HMetrics ),
    154       FT_FRAME_END
    155     };
    156 
    157 
    158     if ( vertical )
    159     {
    160       void  *v = &face->vertical;
    161 
    162 
    163       error = face->goto_table( face, TTAG_vhea, stream, 0 );
    164       if ( error )
    165         goto Fail;
    166 
    167       header = (TT_HoriHeader*)v;
    168     }
    169     else
    170     {
    171       error = face->goto_table( face, TTAG_hhea, stream, 0 );
    172       if ( error )
    173         goto Fail;
    174 
    175       header = &face->horizontal;
    176     }
    177 
    178     if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) )
    179       goto Fail;
    180 
    181     FT_TRACE3(( "Ascender:          %5d\n", header->Ascender ));
    182     FT_TRACE3(( "Descender:         %5d\n", header->Descender ));
    183     FT_TRACE3(( "number_Of_Metrics: %5u\n", header->number_Of_HMetrics ));
    184 
    185     header->long_metrics  = NULL;
    186     header->short_metrics = NULL;
    187 
    188   Fail:
    189     return error;
    190   }
    191 
    192 
    193   /*************************************************************************/
    194   /*                                                                       */
    195   /* <Function>                                                            */
    196   /*    tt_face_get_metrics                                                */
    197   /*                                                                       */
    198   /* <Description>                                                         */
    199   /*    Return the horizontal or vertical metrics in font units for a      */
    200   /*    given glyph.  The values are the left side bearing (top side       */
    201   /*    bearing for vertical metrics) and advance width (advance height    */
    202   /*    for vertical metrics).                                             */
    203   /*                                                                       */
    204   /* <Input>                                                               */
    205   /*    face     :: A pointer to the TrueType face structure.              */
    206   /*                                                                       */
    207   /*    vertical :: If set to TRUE, get vertical metrics.                  */
    208   /*                                                                       */
    209   /*    gindex   :: The glyph index.                                       */
    210   /*                                                                       */
    211   /* <Output>                                                              */
    212   /*    abearing :: The bearing, either left side or top side.             */
    213   /*                                                                       */
    214   /*    aadvance :: The advance width or advance height, depending on      */
    215   /*                the `vertical' flag.                                   */
    216   /*                                                                       */
    217   FT_LOCAL_DEF( void )
    218   tt_face_get_metrics( TT_Face     face,
    219                        FT_Bool     vertical,
    220                        FT_UInt     gindex,
    221                        FT_Short   *abearing,
    222                        FT_UShort  *aadvance )
    223   {
    224     FT_Error        error;
    225     FT_Stream       stream = face->root.stream;
    226     TT_HoriHeader*  header;
    227     FT_ULong        table_pos, table_size, table_end;
    228     FT_UShort       k;
    229 
    230 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    231     FT_Service_MetricsVariations  var =
    232       (FT_Service_MetricsVariations)face->var;
    233 #endif
    234 
    235 
    236     if ( vertical )
    237     {
    238       void*  v = &face->vertical;
    239 
    240 
    241       header     = (TT_HoriHeader*)v;
    242       table_pos  = face->vert_metrics_offset;
    243       table_size = face->vert_metrics_size;
    244     }
    245     else
    246     {
    247       header     = &face->horizontal;
    248       table_pos  = face->horz_metrics_offset;
    249       table_size = face->horz_metrics_size;
    250     }
    251 
    252     table_end = table_pos + table_size;
    253 
    254     k = header->number_Of_HMetrics;
    255 
    256     if ( k > 0 )
    257     {
    258       if ( gindex < (FT_UInt)k )
    259       {
    260         table_pos += 4 * gindex;
    261         if ( table_pos + 4 > table_end )
    262           goto NoData;
    263 
    264         if ( FT_STREAM_SEEK( table_pos ) ||
    265              FT_READ_USHORT( *aadvance ) ||
    266              FT_READ_SHORT( *abearing )  )
    267           goto NoData;
    268       }
    269       else
    270       {
    271         table_pos += 4 * ( k - 1 );
    272         if ( table_pos + 4 > table_end )
    273           goto NoData;
    274 
    275         if ( FT_STREAM_SEEK( table_pos ) ||
    276              FT_READ_USHORT( *aadvance ) )
    277           goto NoData;
    278 
    279         table_pos += 4 + 2 * ( gindex - k );
    280         if ( table_pos + 2 > table_end )
    281           *abearing = 0;
    282         else
    283         {
    284           if ( !FT_STREAM_SEEK( table_pos ) )
    285             (void)FT_READ_SHORT( *abearing );
    286         }
    287       }
    288     }
    289     else
    290     {
    291     NoData:
    292       *abearing = 0;
    293       *aadvance = 0;
    294     }
    295 
    296 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    297     if ( var )
    298     {
    299       FT_Face  f = FT_FACE( face );
    300       FT_Int   a = (FT_Int)*aadvance;
    301       FT_Int   b = (FT_Int)*abearing;
    302 
    303 
    304       if ( vertical )
    305       {
    306         if ( var->vadvance_adjust )
    307           var->vadvance_adjust( f, gindex, &a );
    308         if ( var->tsb_adjust )
    309           var->tsb_adjust( f, gindex, &b );
    310       }
    311       else
    312       {
    313         if ( var->hadvance_adjust )
    314           var->hadvance_adjust( f, gindex, &a );
    315         if ( var->lsb_adjust )
    316           var->lsb_adjust( f, gindex, &b );
    317       }
    318 
    319       *aadvance = (FT_UShort)a;
    320       *abearing = (FT_Short)b;
    321     }
    322 #endif
    323   }
    324 
    325 
    326 /* END */
    327