(root)/
freetype-2.13.2/
src/
sfnt/
ttmtx.c
       1  /****************************************************************************
       2   *
       3   * ttmtx.c
       4   *
       5   *   Load the metrics tables common to TTF and OTF fonts (body).
       6   *
       7   * Copyright (C) 2006-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  
      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 && face->blend )
     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 */