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