Blame src/sfnt/ttmtx.c

Packit cf904d
/***************************************************************************/
Packit cf904d
/*                                                                         */
Packit cf904d
/*  ttmtx.c                                                                */
Packit cf904d
/*                                                                         */
Packit cf904d
/*    Load the metrics tables common to TTF and OTF fonts (body).          */
Packit cf904d
/*                                                                         */
Packit cf904d
/*  Copyright 2006-2017 by                                                 */
Packit cf904d
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
Packit cf904d
/*                                                                         */
Packit cf904d
/*  This file is part of the FreeType project, and may only be used,       */
Packit cf904d
/*  modified, and distributed under the terms of the FreeType project      */
Packit cf904d
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
Packit cf904d
/*  this file you indicate that you have read the license and              */
Packit cf904d
/*  understand and accept it fully.                                        */
Packit cf904d
/*                                                                         */
Packit cf904d
/***************************************************************************/
Packit cf904d
Packit cf904d
Packit cf904d
#include <ft2build.h>
Packit cf904d
#include FT_INTERNAL_DEBUG_H
Packit cf904d
#include FT_INTERNAL_STREAM_H
Packit cf904d
#include FT_TRUETYPE_TAGS_H
Packit cf904d
Packit cf904d
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
Packit cf904d
#include FT_SERVICE_METRICS_VARIATIONS_H
Packit cf904d
#endif
Packit cf904d
Packit cf904d
#include "ttmtx.h"
Packit cf904d
Packit cf904d
#include "sferrors.h"
Packit cf904d
Packit cf904d
Packit cf904d
  /* IMPORTANT: The TT_HoriHeader and TT_VertHeader structures should   */
Packit cf904d
  /*            be identical except for the names of their fields,      */
Packit cf904d
  /*            which are different.                                    */
Packit cf904d
  /*                                                                    */
Packit cf904d
  /*            This ensures that `tt_face_load_hmtx' is able to read   */
Packit cf904d
  /*            both the horizontal and vertical headers.               */
Packit cf904d
Packit cf904d
Packit cf904d
  /*************************************************************************/
Packit cf904d
  /*                                                                       */
Packit cf904d
  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
Packit cf904d
  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
Packit cf904d
  /* messages during execution.                                            */
Packit cf904d
  /*                                                                       */
Packit cf904d
#undef  FT_COMPONENT
Packit cf904d
#define FT_COMPONENT  trace_ttmtx
Packit cf904d
Packit cf904d
Packit cf904d
  /*************************************************************************/
Packit cf904d
  /*                                                                       */
Packit cf904d
  /* <Function>                                                            */
Packit cf904d
  /*    tt_face_load_hmtx                                                  */
Packit cf904d
  /*                                                                       */
Packit cf904d
  /* <Description>                                                         */
Packit cf904d
  /*    Load the `hmtx' or `vmtx' table into a face object.                */
Packit cf904d
  /*                                                                       */
Packit cf904d
  /* <Input>                                                               */
Packit cf904d
  /*    face     :: A handle to the target face object.                    */
Packit cf904d
  /*                                                                       */
Packit cf904d
  /*    stream   :: The input stream.                                      */
Packit cf904d
  /*                                                                       */
Packit cf904d
  /*    vertical :: A boolean flag.  If set, load `vmtx'.                  */
Packit cf904d
  /*                                                                       */
Packit cf904d
  /* <Return>                                                              */
Packit cf904d
  /*    FreeType error code.  0 means success.                             */
Packit cf904d
  /*                                                                       */
Packit cf904d
  FT_LOCAL_DEF( FT_Error )
Packit cf904d
  tt_face_load_hmtx( TT_Face    face,
Packit cf904d
                     FT_Stream  stream,
Packit cf904d
                     FT_Bool    vertical )
Packit cf904d
  {
Packit cf904d
    FT_Error   error;
Packit cf904d
    FT_ULong   tag, table_size;
Packit cf904d
    FT_ULong*  ptable_offset;
Packit cf904d
    FT_ULong*  ptable_size;
Packit cf904d
Packit cf904d
Packit cf904d
    if ( vertical )
Packit cf904d
    {
Packit cf904d
      tag           = TTAG_vmtx;
Packit cf904d
      ptable_offset = &face->vert_metrics_offset;
Packit cf904d
      ptable_size   = &face->vert_metrics_size;
Packit cf904d
    }
Packit cf904d
    else
Packit cf904d
    {
Packit cf904d
      tag           = TTAG_hmtx;
Packit cf904d
      ptable_offset = &face->horz_metrics_offset;
Packit cf904d
      ptable_size   = &face->horz_metrics_size;
Packit cf904d
    }
Packit cf904d
Packit cf904d
    error = face->goto_table( face, tag, stream, &table_size );
Packit cf904d
    if ( error )
Packit cf904d
      goto Fail;
Packit cf904d
Packit cf904d
    *ptable_size   = table_size;
Packit cf904d
    *ptable_offset = FT_STREAM_POS();
Packit cf904d
Packit cf904d
  Fail:
Packit cf904d
    return error;
Packit cf904d
  }
Packit cf904d
Packit cf904d
Packit cf904d
  /*************************************************************************/
Packit cf904d
  /*                                                                       */
Packit cf904d
  /* <Function>                                                            */
Packit cf904d
  /*    tt_face_load_hhea                                                  */
Packit cf904d
  /*                                                                       */
Packit cf904d
  /* <Description>                                                         */
Packit cf904d
  /*    Load the `hhea' or 'vhea' table into a face object.                */
Packit cf904d
  /*                                                                       */
Packit cf904d
  /* <Input>                                                               */
Packit cf904d
  /*    face     :: A handle to the target face object.                    */
Packit cf904d
  /*                                                                       */
Packit cf904d
  /*    stream   :: The input stream.                                      */
Packit cf904d
  /*                                                                       */
Packit cf904d
  /*    vertical :: A boolean flag.  If set, load `vhea'.                  */
Packit cf904d
  /*                                                                       */
Packit cf904d
  /* <Return>                                                              */
Packit cf904d
  /*    FreeType error code.  0 means success.                             */
Packit cf904d
  /*                                                                       */
Packit cf904d
  FT_LOCAL_DEF( FT_Error )
Packit cf904d
  tt_face_load_hhea( TT_Face    face,
Packit cf904d
                     FT_Stream  stream,
Packit cf904d
                     FT_Bool    vertical )
Packit cf904d
  {
Packit cf904d
    FT_Error        error;
Packit cf904d
    TT_HoriHeader*  header;
Packit cf904d
Packit cf904d
    static const FT_Frame_Field  metrics_header_fields[] =
Packit cf904d
    {
Packit cf904d
#undef  FT_STRUCTURE
Packit cf904d
#define FT_STRUCTURE  TT_HoriHeader
Packit cf904d
Packit cf904d
      FT_FRAME_START( 36 ),
Packit cf904d
        FT_FRAME_ULONG ( Version ),
Packit cf904d
        FT_FRAME_SHORT ( Ascender ),
Packit cf904d
        FT_FRAME_SHORT ( Descender ),
Packit cf904d
        FT_FRAME_SHORT ( Line_Gap ),
Packit cf904d
        FT_FRAME_USHORT( advance_Width_Max ),
Packit cf904d
        FT_FRAME_SHORT ( min_Left_Side_Bearing ),
Packit cf904d
        FT_FRAME_SHORT ( min_Right_Side_Bearing ),
Packit cf904d
        FT_FRAME_SHORT ( xMax_Extent ),
Packit cf904d
        FT_FRAME_SHORT ( caret_Slope_Rise ),
Packit cf904d
        FT_FRAME_SHORT ( caret_Slope_Run ),
Packit cf904d
        FT_FRAME_SHORT ( caret_Offset ),
Packit cf904d
        FT_FRAME_SHORT ( Reserved[0] ),
Packit cf904d
        FT_FRAME_SHORT ( Reserved[1] ),
Packit cf904d
        FT_FRAME_SHORT ( Reserved[2] ),
Packit cf904d
        FT_FRAME_SHORT ( Reserved[3] ),
Packit cf904d
        FT_FRAME_SHORT ( metric_Data_Format ),
Packit cf904d
        FT_FRAME_USHORT( number_Of_HMetrics ),
Packit cf904d
      FT_FRAME_END
Packit cf904d
    };
Packit cf904d
Packit cf904d
Packit cf904d
    if ( vertical )
Packit cf904d
    {
Packit cf904d
      void  *v = &face->vertical;
Packit cf904d
Packit cf904d
Packit cf904d
      error = face->goto_table( face, TTAG_vhea, stream, 0 );
Packit cf904d
      if ( error )
Packit cf904d
        goto Fail;
Packit cf904d
Packit cf904d
      header = (TT_HoriHeader*)v;
Packit cf904d
    }
Packit cf904d
    else
Packit cf904d
    {
Packit cf904d
      error = face->goto_table( face, TTAG_hhea, stream, 0 );
Packit cf904d
      if ( error )
Packit cf904d
        goto Fail;
Packit cf904d
Packit cf904d
      header = &face->horizontal;
Packit cf904d
    }
Packit cf904d
Packit cf904d
    if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) )
Packit cf904d
      goto Fail;
Packit cf904d
Packit cf904d
    FT_TRACE3(( "Ascender:          %5d\n", header->Ascender ));
Packit cf904d
    FT_TRACE3(( "Descender:         %5d\n", header->Descender ));
Packit cf904d
    FT_TRACE3(( "number_Of_Metrics: %5u\n", header->number_Of_HMetrics ));
Packit cf904d
Packit cf904d
    header->long_metrics  = NULL;
Packit cf904d
    header->short_metrics = NULL;
Packit cf904d
Packit cf904d
  Fail:
Packit cf904d
    return error;
Packit cf904d
  }
Packit cf904d
Packit cf904d
Packit cf904d
  /*************************************************************************/
Packit cf904d
  /*                                                                       */
Packit cf904d
  /* <Function>                                                            */
Packit cf904d
  /*    tt_face_get_metrics                                                */
Packit cf904d
  /*                                                                       */
Packit cf904d
  /* <Description>                                                         */
Packit cf904d
  /*    Return the horizontal or vertical metrics in font units for a      */
Packit cf904d
  /*    given glyph.  The values are the left side bearing (top side       */
Packit cf904d
  /*    bearing for vertical metrics) and advance width (advance height    */
Packit cf904d
  /*    for vertical metrics).                                             */
Packit cf904d
  /*                                                                       */
Packit cf904d
  /* <Input>                                                               */
Packit cf904d
  /*    face     :: A pointer to the TrueType face structure.              */
Packit cf904d
  /*                                                                       */
Packit cf904d
  /*    vertical :: If set to TRUE, get vertical metrics.                  */
Packit cf904d
  /*                                                                       */
Packit cf904d
  /*    gindex   :: The glyph index.                                       */
Packit cf904d
  /*                                                                       */
Packit cf904d
  /* <Output>                                                              */
Packit cf904d
  /*    abearing :: The bearing, either left side or top side.             */
Packit cf904d
  /*                                                                       */
Packit cf904d
  /*    aadvance :: The advance width or advance height, depending on      */
Packit cf904d
  /*                the `vertical' flag.                                   */
Packit cf904d
  /*                                                                       */
Packit cf904d
  FT_LOCAL_DEF( void )
Packit cf904d
  tt_face_get_metrics( TT_Face     face,
Packit cf904d
                       FT_Bool     vertical,
Packit cf904d
                       FT_UInt     gindex,
Packit cf904d
                       FT_Short   *abearing,
Packit cf904d
                       FT_UShort  *aadvance )
Packit cf904d
  {
Packit cf904d
    FT_Error        error;
Packit cf904d
    FT_Stream       stream = face->root.stream;
Packit cf904d
    TT_HoriHeader*  header;
Packit cf904d
    FT_ULong        table_pos, table_size, table_end;
Packit cf904d
    FT_UShort       k;
Packit cf904d
Packit cf904d
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
Packit cf904d
    FT_Service_MetricsVariations  var =
Packit cf904d
      (FT_Service_MetricsVariations)face->var;
Packit cf904d
#endif
Packit cf904d
Packit cf904d
Packit cf904d
    if ( vertical )
Packit cf904d
    {
Packit cf904d
      void*  v = &face->vertical;
Packit cf904d
Packit cf904d
Packit cf904d
      header     = (TT_HoriHeader*)v;
Packit cf904d
      table_pos  = face->vert_metrics_offset;
Packit cf904d
      table_size = face->vert_metrics_size;
Packit cf904d
    }
Packit cf904d
    else
Packit cf904d
    {
Packit cf904d
      header     = &face->horizontal;
Packit cf904d
      table_pos  = face->horz_metrics_offset;
Packit cf904d
      table_size = face->horz_metrics_size;
Packit cf904d
    }
Packit cf904d
Packit cf904d
    table_end = table_pos + table_size;
Packit cf904d
Packit cf904d
    k = header->number_Of_HMetrics;
Packit cf904d
Packit cf904d
    if ( k > 0 )
Packit cf904d
    {
Packit cf904d
      if ( gindex < (FT_UInt)k )
Packit cf904d
      {
Packit cf904d
        table_pos += 4 * gindex;
Packit cf904d
        if ( table_pos + 4 > table_end )
Packit cf904d
          goto NoData;
Packit cf904d
Packit cf904d
        if ( FT_STREAM_SEEK( table_pos ) ||
Packit cf904d
             FT_READ_USHORT( *aadvance ) ||
Packit cf904d
             FT_READ_SHORT( *abearing )  )
Packit cf904d
          goto NoData;
Packit cf904d
      }
Packit cf904d
      else
Packit cf904d
      {
Packit cf904d
        table_pos += 4 * ( k - 1 );
Packit cf904d
        if ( table_pos + 4 > table_end )
Packit cf904d
          goto NoData;
Packit cf904d
Packit cf904d
        if ( FT_STREAM_SEEK( table_pos ) ||
Packit cf904d
             FT_READ_USHORT( *aadvance ) )
Packit cf904d
          goto NoData;
Packit cf904d
Packit cf904d
        table_pos += 4 + 2 * ( gindex - k );
Packit cf904d
        if ( table_pos + 2 > table_end )
Packit cf904d
          *abearing = 0;
Packit cf904d
        else
Packit cf904d
        {
Packit cf904d
          if ( !FT_STREAM_SEEK( table_pos ) )
Packit cf904d
            (void)FT_READ_SHORT( *abearing );
Packit cf904d
        }
Packit cf904d
      }
Packit cf904d
    }
Packit cf904d
    else
Packit cf904d
    {
Packit cf904d
    NoData:
Packit cf904d
      *abearing = 0;
Packit cf904d
      *aadvance = 0;
Packit cf904d
    }
Packit cf904d
Packit cf904d
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
Packit cf904d
    if ( var )
Packit cf904d
    {
Packit cf904d
      FT_Face  f = FT_FACE( face );
Packit cf904d
      FT_Int   a = (FT_Int)*aadvance;
Packit cf904d
      FT_Int   b = (FT_Int)*abearing;
Packit cf904d
Packit cf904d
Packit cf904d
      if ( vertical )
Packit cf904d
      {
Packit cf904d
        if ( var->vadvance_adjust )
Packit cf904d
          var->vadvance_adjust( f, gindex, &a );
Packit cf904d
        if ( var->tsb_adjust )
Packit cf904d
          var->tsb_adjust( f, gindex, &b );
Packit cf904d
      }
Packit cf904d
      else
Packit cf904d
      {
Packit cf904d
        if ( var->hadvance_adjust )
Packit cf904d
          var->hadvance_adjust( f, gindex, &a );
Packit cf904d
        if ( var->lsb_adjust )
Packit cf904d
          var->lsb_adjust( f, gindex, &b );
Packit cf904d
      }
Packit cf904d
Packit cf904d
      *aadvance = (FT_UShort)a;
Packit cf904d
      *abearing = (FT_Short)b;
Packit cf904d
    }
Packit cf904d
#endif
Packit cf904d
  }
Packit cf904d
Packit cf904d
Packit cf904d
/* END */