tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ttmtx.c (8571B)


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