ttmtx.c
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:15k
源码类别:

其他游戏

开发平台:

Visual C++

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ttmtx.c                                                                */
  4. /*                                                                         */
  5. /*    Load the metrics tables common to TTF and OTF fonts (body).          */
  6. /*                                                                         */
  7. /*  Copyright 2006, 2007 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. #include <ft2build.h>
  18. #include FT_INTERNAL_DEBUG_H
  19. #include FT_INTERNAL_STREAM_H
  20. #include FT_TRUETYPE_TAGS_H
  21. #include "ttmtx.h"
  22. #include "sferrors.h"
  23.   /*************************************************************************/
  24.   /*                                                                       */
  25.   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  26.   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  27.   /* messages during execution.                                            */
  28.   /*                                                                       */
  29. #undef  FT_COMPONENT
  30. #define FT_COMPONENT  trace_ttmtx
  31.   /*
  32.    *  Unfortunately, we can't enable our memory optimizations if
  33.    *  FT_CONFIG_OPTION_OLD_INTERNALS is defined.  This is because at least
  34.    *  one rogue client (libXfont in the X.Org XServer) is directly accessing
  35.    *  the metrics.
  36.    */
  37.   /*************************************************************************/
  38.   /*                                                                       */
  39.   /* <Function>                                                            */
  40.   /*    tt_face_load_hmtx                                                  */
  41.   /*                                                                       */
  42.   /* <Description>                                                         */
  43.   /*    Load the `hmtx' or `vmtx' table into a face object.                */
  44.   /*                                                                       */
  45.   /* <Input>                                                               */
  46.   /*    face     :: A handle to the target face object.                    */
  47.   /*                                                                       */
  48.   /*    stream   :: The input stream.                                      */
  49.   /*                                                                       */
  50.   /*    vertical :: A boolean flag.  If set, load `vmtx'.                  */
  51.   /*                                                                       */
  52.   /* <Return>                                                              */
  53.   /*    FreeType error code.  0 means success.                             */
  54.   /*                                                                       */
  55. #if !defined FT_CONFIG_OPTION_OLD_INTERNALS
  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.     if ( vertical )
  66.     {
  67.       tag           = TTAG_vmtx;
  68.       ptable_offset = &face->vert_metrics_offset;
  69.       ptable_size   = &face->vert_metrics_size;
  70.     }
  71.     else
  72.     {
  73.       tag           = TTAG_hmtx;
  74.       ptable_offset = &face->horz_metrics_offset;
  75.       ptable_size   = &face->horz_metrics_size;
  76.     }
  77.     error = face->goto_table( face, tag, stream, &table_size );
  78.     if ( error )
  79.       goto Fail;
  80.     *ptable_size   = table_size;
  81.     *ptable_offset = FT_STREAM_POS();
  82.   Fail:
  83.     return error;
  84.   }
  85. #else /* !OPTIMIZE_MEMORY || OLD_INTERNALS */
  86.   FT_LOCAL_DEF( FT_Error )
  87.   tt_face_load_hmtx( TT_Face    face,
  88.                      FT_Stream  stream,
  89.                      FT_Bool    vertical )
  90.   {
  91.     FT_Error   error;
  92.     FT_Memory  memory = stream->memory;
  93.     FT_ULong   table_len;
  94.     FT_Long    num_shorts, num_longs, num_shorts_checked;
  95.     TT_LongMetrics*    longs;
  96.     TT_ShortMetrics**  shorts;
  97.     FT_Byte*           p;
  98.     if ( vertical )
  99.     {
  100.       void*   lm = &face->vertical.long_metrics;
  101.       void**  sm = &face->vertical.short_metrics;
  102.       error = face->goto_table( face, TTAG_vmtx, stream, &table_len );
  103.       if ( error )
  104.         goto Fail;
  105.       num_longs = face->vertical.number_Of_VMetrics;
  106.       if ( (FT_ULong)num_longs > table_len / 4 )
  107.         num_longs = (FT_Long)( table_len / 4 );
  108.       face->vertical.number_Of_VMetrics = 0;
  109.       longs  = (TT_LongMetrics*)lm;
  110.       shorts = (TT_ShortMetrics**)sm;
  111.     }
  112.     else
  113.     {
  114.       void*   lm = &face->horizontal.long_metrics;
  115.       void**  sm = &face->horizontal.short_metrics;
  116.       error = face->goto_table( face, TTAG_hmtx, stream, &table_len );
  117.       if ( error )
  118.         goto Fail;
  119.       num_longs = face->horizontal.number_Of_HMetrics;
  120.       if ( (FT_ULong)num_longs > table_len / 4 )
  121.         num_longs = (FT_Long)( table_len / 4 );
  122.       face->horizontal.number_Of_HMetrics = 0;
  123.       longs  = (TT_LongMetrics*)lm;
  124.       shorts = (TT_ShortMetrics**)sm;
  125.     }
  126.     /* never trust derived values */
  127.     num_shorts         = face->max_profile.numGlyphs - num_longs;
  128.     num_shorts_checked = ( table_len - num_longs * 4L ) / 2;
  129.     if ( num_shorts < 0 )
  130.     {
  131.       FT_ERROR(( "%cmtx has more metrics than glyphs.n" ));
  132.       /* Adobe simply ignores this problem.  So we shall do the same. */
  133. #if 0
  134.       error = vertical ? SFNT_Err_Invalid_Vert_Metrics
  135.                        : SFNT_Err_Invalid_Horiz_Metrics;
  136.       goto Exit;
  137. #else
  138.       num_shorts = 0;
  139. #endif
  140.     }
  141.     if ( FT_QNEW_ARRAY( *longs,  num_longs  ) ||
  142.          FT_QNEW_ARRAY( *shorts, num_shorts ) )
  143.       goto Fail;
  144.     if ( FT_FRAME_ENTER( table_len ) )
  145.       goto Fail;
  146.     p = stream->cursor;
  147.     {
  148.       TT_LongMetrics  cur   = *longs;
  149.       TT_LongMetrics  limit = cur + num_longs;
  150.       for ( ; cur < limit; cur++ )
  151.       {
  152.         cur->advance = FT_NEXT_USHORT( p );
  153.         cur->bearing = FT_NEXT_SHORT( p );
  154.       }
  155.     }
  156.     /* do we have an inconsistent number of metric values? */
  157.     {
  158.       TT_ShortMetrics*  cur   = *shorts;
  159.       TT_ShortMetrics*  limit = cur +
  160.                                 FT_MIN( num_shorts, num_shorts_checked );
  161.       for ( ; cur < limit; cur++ )
  162.         *cur = FT_NEXT_SHORT( p );
  163.       /* We fill up the missing left side bearings with the     */
  164.       /* last valid value.  Since this will occur for buggy CJK */
  165.       /* fonts usually only, nothing serious will happen.       */
  166.       if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 )
  167.       {
  168.         FT_Short  val = (*shorts)[num_shorts_checked - 1];
  169.         limit = *shorts + num_shorts;
  170.         for ( ; cur < limit; cur++ )
  171.           *cur = val;
  172.       }
  173.     }
  174.     FT_FRAME_EXIT();
  175.     if ( vertical )
  176.       face->vertical.number_Of_VMetrics = (FT_UShort)num_longs;
  177.     else
  178.       face->horizontal.number_Of_HMetrics = (FT_UShort)num_longs;
  179.   Fail:
  180.     return error;
  181.   }
  182. #endif /* !OPTIMIZE_MEMORY || OLD_INTERNALS */
  183.   /*************************************************************************/
  184.   /*                                                                       */
  185.   /* <Function>                                                            */
  186.   /*    tt_face_load_hhea                                                  */
  187.   /*                                                                       */
  188.   /* <Description>                                                         */
  189.   /*    Load the `hhea' or 'vhea' table into a face object.                */
  190.   /*                                                                       */
  191.   /* <Input>                                                               */
  192.   /*    face     :: A handle to the target face object.                    */
  193.   /*                                                                       */
  194.   /*    stream   :: The input stream.                                      */
  195.   /*                                                                       */
  196.   /*    vertical :: A boolean flag.  If set, load `vhea'.                  */
  197.   /*                                                                       */
  198.   /* <Return>                                                              */
  199.   /*    FreeType error code.  0 means success.                             */
  200.   /*                                                                       */
  201.   FT_LOCAL_DEF( FT_Error )
  202.   tt_face_load_hhea( TT_Face    face,
  203.                      FT_Stream  stream,
  204.                      FT_Bool    vertical )
  205.   {
  206.     FT_Error        error;
  207.     TT_HoriHeader*  header;
  208.     const FT_Frame_Field  metrics_header_fields[] =
  209.     {
  210. #undef  FT_STRUCTURE
  211. #define FT_STRUCTURE  TT_HoriHeader
  212.       FT_FRAME_START( 36 ),
  213.         FT_FRAME_ULONG ( Version ),
  214.         FT_FRAME_SHORT ( Ascender ),
  215.         FT_FRAME_SHORT ( Descender ),
  216.         FT_FRAME_SHORT ( Line_Gap ),
  217.         FT_FRAME_USHORT( advance_Width_Max ),
  218.         FT_FRAME_SHORT ( min_Left_Side_Bearing ),
  219.         FT_FRAME_SHORT ( min_Right_Side_Bearing ),
  220.         FT_FRAME_SHORT ( xMax_Extent ),
  221.         FT_FRAME_SHORT ( caret_Slope_Rise ),
  222.         FT_FRAME_SHORT ( caret_Slope_Run ),
  223.         FT_FRAME_SHORT ( caret_Offset ),
  224.         FT_FRAME_SHORT ( Reserved[0] ),
  225.         FT_FRAME_SHORT ( Reserved[1] ),
  226.         FT_FRAME_SHORT ( Reserved[2] ),
  227.         FT_FRAME_SHORT ( Reserved[3] ),
  228.         FT_FRAME_SHORT ( metric_Data_Format ),
  229.         FT_FRAME_USHORT( number_Of_HMetrics ),
  230.       FT_FRAME_END
  231.     };
  232.     if ( vertical )
  233.     {
  234.       void  *v = &face->vertical;
  235.       error = face->goto_table( face, TTAG_vhea, stream, 0 );
  236.       if ( error )
  237.         goto Fail;
  238.       header = (TT_HoriHeader*)v;
  239.     }
  240.     else
  241.     {
  242.       error = face->goto_table( face, TTAG_hhea, stream, 0 );
  243.       if ( error )
  244.         goto Fail;
  245.       header = &face->horizontal;
  246.     }
  247.     if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) )
  248.       goto Fail;
  249.     FT_TRACE3(( "Ascender:          %5dn", header->Ascender ));
  250.     FT_TRACE3(( "Descender:         %5dn", header->Descender ));
  251.     FT_TRACE3(( "number_Of_Metrics: %5un", header->number_Of_HMetrics ));
  252.     header->long_metrics  = NULL;
  253.     header->short_metrics = NULL;
  254.   Fail:
  255.     return error;
  256.   }
  257.   /*************************************************************************/
  258.   /*                                                                       */
  259.   /* <Function>                                                            */
  260.   /*    tt_face_get_metrics                                                */
  261.   /*                                                                       */
  262.   /* <Description>                                                         */
  263.   /*    Returns the horizontal or vertical metrics in font units for a     */
  264.   /*    given glyph.  The metrics are the left side bearing (resp. top     */
  265.   /*    side bearing) and advance width (resp. advance height).            */
  266.   /*                                                                       */
  267.   /* <Input>                                                               */
  268.   /*    header  :: A pointer to either the horizontal or vertical metrics  */
  269.   /*               structure.                                              */
  270.   /*                                                                       */
  271.   /*    idx     :: The glyph index.                                        */
  272.   /*                                                                       */
  273.   /* <Output>                                                              */
  274.   /*    bearing :: The bearing, either left side or top side.              */
  275.   /*                                                                       */
  276.   /*    advance :: The advance width resp. advance height.                 */
  277.   /*                                                                       */
  278. #if !defined FT_CONFIG_OPTION_OLD_INTERNALS
  279.   FT_LOCAL_DEF( FT_Error )
  280.   tt_face_get_metrics( TT_Face     face,
  281.                        FT_Bool     vertical,
  282.                        FT_UInt     gindex,
  283.                        FT_Short   *abearing,
  284.                        FT_UShort  *aadvance )
  285.   {
  286.     FT_Error        error;
  287.     FT_Stream       stream = face->root.stream;
  288.     TT_HoriHeader*  header;
  289.     FT_ULong        table_pos, table_size, table_end;
  290.     FT_UShort       k;
  291.     if ( vertical )
  292.     {
  293.       void*  v = &face->vertical;
  294.       header     = (TT_HoriHeader*)v;
  295.       table_pos  = face->vert_metrics_offset;
  296.       table_size = face->vert_metrics_size;
  297.     }
  298.     else
  299.     {
  300.       header     = &face->horizontal;
  301.       table_pos  = face->horz_metrics_offset;
  302.       table_size = face->horz_metrics_size;
  303.     }
  304.     table_end = table_pos + table_size;
  305.     k = header->number_Of_HMetrics;
  306.     if ( k > 0 )
  307.     {
  308.       if ( gindex < (FT_UInt)k )
  309.       {
  310.         table_pos += 4 * gindex;
  311.         if ( table_pos + 4 > table_end )
  312.           goto NoData;
  313.         if ( FT_STREAM_SEEK( table_pos ) ||
  314.              FT_READ_USHORT( *aadvance ) ||
  315.              FT_READ_SHORT( *abearing )  )
  316.           goto NoData;
  317.       }
  318.       else
  319.       {
  320.         table_pos += 4 * ( k - 1 );
  321.         if ( table_pos + 4 > table_end )
  322.           goto NoData;
  323.         if ( FT_STREAM_SEEK( table_pos ) ||
  324.              FT_READ_USHORT( *aadvance ) )
  325.           goto NoData;
  326.         table_pos += 4 + 2 * ( gindex - k );
  327.         if ( table_pos + 2 > table_end )
  328.           *abearing = 0;
  329.         else
  330.         {
  331.           if ( !FT_STREAM_SEEK( table_pos ) )
  332.             (void)FT_READ_SHORT( *abearing );
  333.         }
  334.       }
  335.     }
  336.     else
  337.     {
  338.     NoData:
  339.       *abearing = 0;
  340.       *aadvance = 0;
  341.     }
  342.     return SFNT_Err_Ok;
  343.   }
  344. #else /* OLD_INTERNALS */
  345.   FT_LOCAL_DEF( FT_Error )
  346.   tt_face_get_metrics( TT_Face     face,
  347.                        FT_Bool     vertical,
  348.                        FT_UInt     gindex,
  349.                        FT_Short*   abearing,
  350.                        FT_UShort*  aadvance )
  351.   {
  352.     void*           v = &face->vertical;
  353.     void*           h = &face->horizontal;
  354.     TT_HoriHeader*  header = vertical ? (TT_HoriHeader*)v : h;
  355.     TT_LongMetrics  longs_m;
  356.     FT_UShort       k = header->number_Of_HMetrics;
  357.     if ( k == 0                                         ||
  358.          !header->long_metrics                          ||
  359.          gindex >= (FT_UInt)face->max_profile.numGlyphs )
  360.     {
  361.       *abearing = *aadvance = 0;
  362.       return SFNT_Err_Ok;
  363.     }
  364.     if ( gindex < (FT_UInt)k )
  365.     {
  366.       longs_m   = (TT_LongMetrics)header->long_metrics + gindex;
  367.       *abearing = longs_m->bearing;
  368.       *aadvance = longs_m->advance;
  369.     }
  370.     else
  371.     {
  372.       *abearing = ((TT_ShortMetrics*)header->short_metrics)[gindex - k];
  373.       *aadvance = ((TT_LongMetrics)header->long_metrics)[k - 1].advance;
  374.     }
  375.     return SFNT_Err_Ok;
  376.   }
  377. #endif /* !OPTIMIZE_MEMORY || OLD_INTERNALS */
  378. /* END */