Edit

kc3-lang/freetype/src/sfnt/ttmtx.c

Branch :

  • Show log

    Commit

  • Author : Werner Lemberg
    Date : 2011-01-30 16:38:09
    Hash : 0682251e
    Message : * src/sfnt/ttmtx.c (tt_face_load_hmtx): Fix tracing message.

  • src/sfnt/ttmtx.c
  • /***************************************************************************/
    /*                                                                         */
    /*  ttmtx.c                                                                */
    /*                                                                         */
    /*    Load the metrics tables common to TTF and OTF fonts (body).          */
    /*                                                                         */
    /*  Copyright 2006-2009, 2011 by                                           */
    /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
    /*                                                                         */
    /*  This file is part of the FreeType project, and may only be used,       */
    /*  modified, and distributed under the terms of the FreeType project      */
    /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
    /*  this file you indicate that you have read the license and              */
    /*  understand and accept it fully.                                        */
    /*                                                                         */
    /***************************************************************************/
    
    
    #include <ft2build.h>
    #include FT_INTERNAL_DEBUG_H
    #include FT_INTERNAL_STREAM_H
    #include FT_TRUETYPE_TAGS_H
    #include "ttmtx.h"
    
    #include "sferrors.h"
    
    
      /*************************************************************************/
      /*                                                                       */
      /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
      /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
      /* messages during execution.                                            */
      /*                                                                       */
    #undef  FT_COMPONENT
    #define FT_COMPONENT  trace_ttmtx
    
    
      /*
       *  Unfortunately, we can't enable our memory optimizations if
       *  FT_CONFIG_OPTION_OLD_INTERNALS is defined.  This is because at least
       *  one rogue client (libXfont in the X.Org XServer) is directly accessing
       *  the metrics.
       */
    
      /*************************************************************************/
      /*                                                                       */
      /* <Function>                                                            */
      /*    tt_face_load_hmtx                                                  */
      /*                                                                       */
      /* <Description>                                                         */
      /*    Load the `hmtx' or `vmtx' table into a face object.                */
      /*                                                                       */
      /* <Input>                                                               */
      /*    face     :: A handle to the target face object.                    */
      /*                                                                       */
      /*    stream   :: The input stream.                                      */
      /*                                                                       */
      /*    vertical :: A boolean flag.  If set, load `vmtx'.                  */
      /*                                                                       */
      /* <Return>                                                              */
      /*    FreeType error code.  0 means success.                             */
      /*                                                                       */
    #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
    
      FT_LOCAL_DEF( FT_Error )
      tt_face_load_hmtx( TT_Face    face,
                         FT_Stream  stream,
                         FT_Bool    vertical )
      {
        FT_Error   error;
        FT_ULong   tag, table_size;
        FT_ULong*  ptable_offset;
        FT_ULong*  ptable_size;
    
    
        if ( vertical )
        {
          tag           = TTAG_vmtx;
          ptable_offset = &face->vert_metrics_offset;
          ptable_size   = &face->vert_metrics_size;
        }
        else
        {
          tag           = TTAG_hmtx;
          ptable_offset = &face->horz_metrics_offset;
          ptable_size   = &face->horz_metrics_size;
        }
    
        error = face->goto_table( face, tag, stream, &table_size );
        if ( error )
          goto Fail;
    
        *ptable_size   = table_size;
        *ptable_offset = FT_STREAM_POS();
    
      Fail:
        return error;
      }
    
    #else /* !FT_CONFIG_OPTION_OLD_INTERNALS */
    
      FT_LOCAL_DEF( FT_Error )
      tt_face_load_hmtx( TT_Face    face,
                         FT_Stream  stream,
                         FT_Bool    vertical )
      {
        FT_Error   error;
        FT_Memory  memory = stream->memory;
    
        FT_ULong   table_len;
        FT_Long    num_shorts, num_longs, num_shorts_checked;
    
        TT_LongMetrics*    longs;
        TT_ShortMetrics**  shorts;
        FT_Byte*           p;
    
    
        if ( vertical )
        {
          void*   lm = &face->vertical.long_metrics;
          void**  sm = &face->vertical.short_metrics;
    
    
          error = face->goto_table( face, TTAG_vmtx, stream, &table_len );
          if ( error )
            goto Fail;
    
          num_longs = face->vertical.number_Of_VMetrics;
          if ( (FT_ULong)num_longs > table_len / 4 )
            num_longs = (FT_Long)( table_len / 4 );
    
          face->vertical.number_Of_VMetrics = 0;
    
          longs  = (TT_LongMetrics*)lm;
          shorts = (TT_ShortMetrics**)sm;
        }
        else
        {
          void*   lm = &face->horizontal.long_metrics;
          void**  sm = &face->horizontal.short_metrics;
    
    
          error = face->goto_table( face, TTAG_hmtx, stream, &table_len );
          if ( error )
            goto Fail;
    
          num_longs = face->horizontal.number_Of_HMetrics;
          if ( (FT_ULong)num_longs > table_len / 4 )
            num_longs = (FT_Long)( table_len / 4 );
    
          face->horizontal.number_Of_HMetrics = 0;
    
          longs  = (TT_LongMetrics*)lm;
          shorts = (TT_ShortMetrics**)sm;
        }
    
        /* never trust derived values */
    
        num_shorts         = face->max_profile.numGlyphs - num_longs;
        num_shorts_checked = ( table_len - num_longs * 4L ) / 2;
    
        if ( num_shorts < 0 )
        {
          FT_TRACE0(( "tt_face_load_hmtx:"
                      " %cmtx has more metrics than glyphs.\n",
                      vertical ? 'v' : 'h' ));
    
          /* Adobe simply ignores this problem.  So we shall do the same. */
    #if 0
          error = vertical ? SFNT_Err_Invalid_Vert_Metrics
                           : SFNT_Err_Invalid_Horiz_Metrics;
          goto Exit;
    #else
          num_shorts = 0;
    #endif
        }
    
        if ( FT_QNEW_ARRAY( *longs,  num_longs  ) ||
             FT_QNEW_ARRAY( *shorts, num_shorts ) )
          goto Fail;
    
        if ( FT_FRAME_ENTER( table_len ) )
          goto Fail;
    
        p = stream->cursor;
    
        {
          TT_LongMetrics  cur   = *longs;
          TT_LongMetrics  limit = cur + num_longs;
    
    
          for ( ; cur < limit; cur++ )
          {
            cur->advance = FT_NEXT_USHORT( p );
            cur->bearing = FT_NEXT_SHORT( p );
          }
        }
    
        /* do we have an inconsistent number of metric values? */
        {
          TT_ShortMetrics*  cur   = *shorts;
          TT_ShortMetrics*  limit = cur +
                                    FT_MIN( num_shorts, num_shorts_checked );
    
    
          for ( ; cur < limit; cur++ )
            *cur = FT_NEXT_SHORT( p );
    
          /* We fill up the missing left side bearings with the     */
          /* last valid value.  Since this will occur for buggy CJK */
          /* fonts usually only, nothing serious will happen.       */
          if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 )
          {
            FT_Short  val = (*shorts)[num_shorts_checked - 1];
    
    
            limit = *shorts + num_shorts;
            for ( ; cur < limit; cur++ )
              *cur = val;
          }
        }
    
        FT_FRAME_EXIT();
    
        if ( vertical )
          face->vertical.number_Of_VMetrics = (FT_UShort)num_longs;
        else
          face->horizontal.number_Of_HMetrics = (FT_UShort)num_longs;
    
      Fail:
        return error;
      }
    
    #endif /* !FT_CONFIG_OPTION_OLD_INTERNALS */
    
    
      /*************************************************************************/
      /*                                                                       */
      /* <Function>                                                            */
      /*    tt_face_load_hhea                                                  */
      /*                                                                       */
      /* <Description>                                                         */
      /*    Load the `hhea' or 'vhea' table into a face object.                */
      /*                                                                       */
      /* <Input>                                                               */
      /*    face     :: A handle to the target face object.                    */
      /*                                                                       */
      /*    stream   :: The input stream.                                      */
      /*                                                                       */
      /*    vertical :: A boolean flag.  If set, load `vhea'.                  */
      /*                                                                       */
      /* <Return>                                                              */
      /*    FreeType error code.  0 means success.                             */
      /*                                                                       */
      FT_LOCAL_DEF( FT_Error )
      tt_face_load_hhea( TT_Face    face,
                         FT_Stream  stream,
                         FT_Bool    vertical )
      {
        FT_Error        error;
        TT_HoriHeader*  header;
    
        const FT_Frame_Field  metrics_header_fields[] =
        {
    #undef  FT_STRUCTURE
    #define FT_STRUCTURE  TT_HoriHeader
    
          FT_FRAME_START( 36 ),
            FT_FRAME_ULONG ( Version ),
            FT_FRAME_SHORT ( Ascender ),
            FT_FRAME_SHORT ( Descender ),
            FT_FRAME_SHORT ( Line_Gap ),
            FT_FRAME_USHORT( advance_Width_Max ),
            FT_FRAME_SHORT ( min_Left_Side_Bearing ),
            FT_FRAME_SHORT ( min_Right_Side_Bearing ),
            FT_FRAME_SHORT ( xMax_Extent ),
            FT_FRAME_SHORT ( caret_Slope_Rise ),
            FT_FRAME_SHORT ( caret_Slope_Run ),
            FT_FRAME_SHORT ( caret_Offset ),
            FT_FRAME_SHORT ( Reserved[0] ),
            FT_FRAME_SHORT ( Reserved[1] ),
            FT_FRAME_SHORT ( Reserved[2] ),
            FT_FRAME_SHORT ( Reserved[3] ),
            FT_FRAME_SHORT ( metric_Data_Format ),
            FT_FRAME_USHORT( number_Of_HMetrics ),
          FT_FRAME_END
        };
    
    
        if ( vertical )
        {
          void  *v = &face->vertical;
    
    
          error = face->goto_table( face, TTAG_vhea, stream, 0 );
          if ( error )
            goto Fail;
    
          header = (TT_HoriHeader*)v;
        }
        else
        {
          error = face->goto_table( face, TTAG_hhea, stream, 0 );
          if ( error )
            goto Fail;
    
          header = &face->horizontal;
        }
    
        if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) )
          goto Fail;
    
        FT_TRACE3(( "Ascender:          %5d\n", header->Ascender ));
        FT_TRACE3(( "Descender:         %5d\n", header->Descender ));
        FT_TRACE3(( "number_Of_Metrics: %5u\n", header->number_Of_HMetrics ));
    
        header->long_metrics  = NULL;
        header->short_metrics = NULL;
    
      Fail:
        return error;
      }
    
    
      /*************************************************************************/
      /*                                                                       */
      /* <Function>                                                            */
      /*    tt_face_get_metrics                                                */
      /*                                                                       */
      /* <Description>                                                         */
      /*    Returns the horizontal or vertical metrics in font units for a     */
      /*    given glyph.  The metrics are the left side bearing (resp. top     */
      /*    side bearing) and advance width (resp. advance height).            */
      /*                                                                       */
      /* <Input>                                                               */
      /*    header  :: A pointer to either the horizontal or vertical metrics  */
      /*               structure.                                              */
      /*                                                                       */
      /*    idx     :: The glyph index.                                        */
      /*                                                                       */
      /* <Output>                                                              */
      /*    bearing :: The bearing, either left side or top side.              */
      /*                                                                       */
      /*    advance :: The advance width resp. advance height.                 */
      /*                                                                       */
    #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
    
      FT_LOCAL_DEF( FT_Error )
      tt_face_get_metrics( TT_Face     face,
                           FT_Bool     vertical,
                           FT_UInt     gindex,
                           FT_Short   *abearing,
                           FT_UShort  *aadvance )
      {
        FT_Error        error;
        FT_Stream       stream = face->root.stream;
        TT_HoriHeader*  header;
        FT_ULong        table_pos, table_size, table_end;
        FT_UShort       k;
    
    
        if ( vertical )
        {
          void*  v = &face->vertical;
    
    
          header     = (TT_HoriHeader*)v;
          table_pos  = face->vert_metrics_offset;
          table_size = face->vert_metrics_size;
        }
        else
        {
          header     = &face->horizontal;
          table_pos  = face->horz_metrics_offset;
          table_size = face->horz_metrics_size;
        }
    
        table_end = table_pos + table_size;
    
        k = header->number_Of_HMetrics;
    
        if ( k > 0 )
        {
          if ( gindex < (FT_UInt)k )
          {
            table_pos += 4 * gindex;
            if ( table_pos + 4 > table_end )
              goto NoData;
    
            if ( FT_STREAM_SEEK( table_pos ) ||
                 FT_READ_USHORT( *aadvance ) ||
                 FT_READ_SHORT( *abearing )  )
              goto NoData;
          }
          else
          {
            table_pos += 4 * ( k - 1 );
            if ( table_pos + 4 > table_end )
              goto NoData;
    
            if ( FT_STREAM_SEEK( table_pos ) ||
                 FT_READ_USHORT( *aadvance ) )
              goto NoData;
    
            table_pos += 4 + 2 * ( gindex - k );
            if ( table_pos + 2 > table_end )
              *abearing = 0;
            else
            {
              if ( !FT_STREAM_SEEK( table_pos ) )
                (void)FT_READ_SHORT( *abearing );
            }
          }
        }
        else
        {
        NoData:
          *abearing = 0;
          *aadvance = 0;
        }
    
        return SFNT_Err_Ok;
      }
    
    #else /* !FT_CONFIG_OPTION_OLD_INTERNALS */
    
      FT_LOCAL_DEF( FT_Error )
      tt_face_get_metrics( TT_Face     face,
                           FT_Bool     vertical,
                           FT_UInt     gindex,
                           FT_Short*   abearing,
                           FT_UShort*  aadvance )
      {
        void*           v = &face->vertical;
        void*           h = &face->horizontal;
        TT_HoriHeader*  header = vertical ? (TT_HoriHeader*)v
                                          : (TT_HoriHeader*)h;
        TT_LongMetrics  longs_m;
        FT_UShort       k = header->number_Of_HMetrics;
    
    
        if ( k == 0                                         ||
             !header->long_metrics                          ||
             gindex >= (FT_UInt)face->max_profile.numGlyphs )
        {
          *abearing = *aadvance = 0;
          return SFNT_Err_Ok;
        }
    
        if ( gindex < (FT_UInt)k )
        {
          longs_m   = (TT_LongMetrics)header->long_metrics + gindex;
          *abearing = longs_m->bearing;
          *aadvance = longs_m->advance;
        }
        else
        {
          *abearing = ((TT_ShortMetrics*)header->short_metrics)[gindex - k];
          *aadvance = ((TT_LongMetrics)header->long_metrics)[k - 1].advance;
        }
    
        return SFNT_Err_Ok;
      }
    
    #endif /* !FT_CONFIG_OPTION_OLD_INTERNALS */
    
    
    /* END */