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

其他游戏

开发平台:

Visual C++

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ttpload.c                                                              */
  4. /*                                                                         */
  5. /*    TrueType-specific tables loader (body).                              */
  6. /*                                                                         */
  7. /*  Copyright 1996-2001, 2002, 2004, 2005, 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_OBJECTS_H
  20. #include FT_INTERNAL_STREAM_H
  21. #include FT_TRUETYPE_TAGS_H
  22. #include "ttpload.h"
  23. #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
  24. #include "ttgxvar.h"
  25. #endif
  26. #include "tterrors.h"
  27.   /*************************************************************************/
  28.   /*                                                                       */
  29.   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  30.   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  31.   /* messages during execution.                                            */
  32.   /*                                                                       */
  33. #undef  FT_COMPONENT
  34. #define FT_COMPONENT  trace_ttpload
  35.   /*************************************************************************/
  36.   /*                                                                       */
  37.   /* <Function>                                                            */
  38.   /*    tt_face_load_loca                                                  */
  39.   /*                                                                       */
  40.   /* <Description>                                                         */
  41.   /*    Load the locations table.                                          */
  42.   /*                                                                       */
  43.   /* <InOut>                                                               */
  44.   /*    face   :: A handle to the target face object.                      */
  45.   /*                                                                       */
  46.   /* <Input>                                                               */
  47.   /*    stream :: The input stream.                                        */
  48.   /*                                                                       */
  49.   /* <Return>                                                              */
  50.   /*    FreeType error code.  0 means success.                             */
  51.   /*                                                                       */
  52.   FT_LOCAL_DEF( FT_Error )
  53.   tt_face_load_loca( TT_Face    face,
  54.                      FT_Stream  stream )
  55.   {
  56.     FT_Error  error;
  57.     FT_ULong  table_len;
  58.     /* we need the size of the `glyf' table for malformed `loca' tables */
  59.     error = face->goto_table( face, TTAG_glyf, stream, &face->glyf_len );
  60.     if ( error )
  61.       goto Exit;
  62.     FT_TRACE2(( "Locations " ));
  63.     error = face->goto_table( face, TTAG_loca, stream, &table_len );
  64.     if ( error )
  65.     {
  66.       error = TT_Err_Locations_Missing;
  67.       goto Exit;
  68.     }
  69.     if ( face->header.Index_To_Loc_Format != 0 )
  70.     {
  71.       if ( table_len >= 0x40000L )
  72.       {
  73.         FT_TRACE2(( "table too large!n" ));
  74.         error = TT_Err_Invalid_Table;
  75.         goto Exit;
  76.       }
  77.       face->num_locations = (FT_UInt)( table_len >> 2 );
  78.     }
  79.     else
  80.     {
  81.       if ( table_len >= 0x20000L )
  82.       {
  83.         FT_TRACE2(( "table too large!n" ));
  84.         error = TT_Err_Invalid_Table;
  85.         goto Exit;
  86.       }
  87.       face->num_locations = (FT_UInt)( table_len >> 1 );
  88.     }
  89.     /*
  90.      * Extract the frame.  We don't need to decompress it since
  91.      * we are able to parse it directly.
  92.      */
  93.     if ( FT_FRAME_EXTRACT( table_len, face->glyph_locations ) )
  94.       goto Exit;
  95.     FT_TRACE2(( "loadedn" ));
  96.   Exit:
  97.     return error;
  98.   }
  99.   FT_LOCAL_DEF( FT_ULong )
  100.   tt_face_get_location( TT_Face   face,
  101.                         FT_UInt   gindex,
  102.                         FT_UInt  *asize )
  103.   {
  104.     FT_ULong  pos1, pos2;
  105.     FT_Byte*  p;
  106.     FT_Byte*  p_limit;
  107.     pos1 = pos2 = 0;
  108.     if ( gindex < face->num_locations )
  109.     {
  110.       if ( face->header.Index_To_Loc_Format != 0 )
  111.       {
  112.         p       = face->glyph_locations + gindex * 4;
  113.         p_limit = face->glyph_locations + face->num_locations * 4;
  114.         pos1 = FT_NEXT_ULONG( p );
  115.         pos2 = pos1;
  116.         if ( p + 4 <= p_limit )
  117.           pos2 = FT_NEXT_ULONG( p );
  118.       }
  119.       else
  120.       {
  121.         p       = face->glyph_locations + gindex * 2;
  122.         p_limit = face->glyph_locations + face->num_locations * 2;
  123.         pos1 = FT_NEXT_USHORT( p );
  124.         pos2 = pos1;
  125.         if ( p + 2 <= p_limit )
  126.           pos2 = FT_NEXT_USHORT( p );
  127.         pos1 <<= 1;
  128.         pos2 <<= 1;
  129.       }
  130.     }
  131.     /* It isn't mentioned explicitly that the `loca' table must be  */
  132.     /* ordered, but implicitly it refers to the length of an entry  */
  133.     /* as the difference between the current and the next position. */
  134.     /* Anyway, there do exist (malformed) fonts which don't obey    */
  135.     /* this rule, so we are only able to provide an upper bound for */
  136.     /* the size.                                                    */
  137.     if ( pos2 >= pos1 )
  138.       *asize = (FT_UInt)( pos2 - pos1 );
  139.     else
  140.       *asize = (FT_UInt)( face->glyf_len - pos1 );
  141.     return pos1;
  142.   }
  143.   FT_LOCAL_DEF( void )
  144.   tt_face_done_loca( TT_Face  face )
  145.   {
  146.     FT_Stream  stream = face->root.stream;
  147.     FT_FRAME_RELEASE( face->glyph_locations );
  148.     face->num_locations = 0;
  149.   }
  150.   /*************************************************************************/
  151.   /*                                                                       */
  152.   /* <Function>                                                            */
  153.   /*    tt_face_load_cvt                                                   */
  154.   /*                                                                       */
  155.   /* <Description>                                                         */
  156.   /*    Load the control value table into a face object.                   */
  157.   /*                                                                       */
  158.   /* <InOut>                                                               */
  159.   /*    face   :: A handle to the target face object.                      */
  160.   /*                                                                       */
  161.   /* <Input>                                                               */
  162.   /*    stream :: A handle to the input stream.                            */
  163.   /*                                                                       */
  164.   /* <Return>                                                              */
  165.   /*    FreeType error code.  0 means success.                             */
  166.   /*                                                                       */
  167.   FT_LOCAL_DEF( FT_Error )
  168.   tt_face_load_cvt( TT_Face    face,
  169.                     FT_Stream  stream )
  170.   {
  171. #ifdef TT_USE_BYTECODE_INTERPRETER
  172.     FT_Error   error;
  173.     FT_Memory  memory = stream->memory;
  174.     FT_ULong   table_len;
  175.     FT_TRACE2(( "CVT " ));
  176.     error = face->goto_table( face, TTAG_cvt, stream, &table_len );
  177.     if ( error )
  178.     {
  179.       FT_TRACE2(( "is missing!n" ));
  180.       face->cvt_size = 0;
  181.       face->cvt      = NULL;
  182.       error          = TT_Err_Ok;
  183.       goto Exit;
  184.     }
  185.     face->cvt_size = table_len / 2;
  186.     if ( FT_NEW_ARRAY( face->cvt, face->cvt_size ) )
  187.       goto Exit;
  188.     if ( FT_FRAME_ENTER( face->cvt_size * 2L ) )
  189.       goto Exit;
  190.     {
  191.       FT_Short*  cur   = face->cvt;
  192.       FT_Short*  limit = cur + face->cvt_size;
  193.       for ( ; cur <  limit; cur++ )
  194.         *cur = FT_GET_SHORT();
  195.     }
  196.     FT_FRAME_EXIT();
  197.     FT_TRACE2(( "loadedn" ));
  198. #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
  199.     if ( face->doblend )
  200.       error = tt_face_vary_cvt( face, stream );
  201. #endif
  202.   Exit:
  203.     return error;
  204. #else /* !TT_USE_BYTECODE_INTERPRETER */
  205.     FT_UNUSED( face   );
  206.     FT_UNUSED( stream );
  207.     return TT_Err_Ok;
  208. #endif
  209.   }
  210.   /*************************************************************************/
  211.   /*                                                                       */
  212.   /* <Function>                                                            */
  213.   /*    tt_face_load_fpgm                                                  */
  214.   /*                                                                       */
  215.   /* <Description>                                                         */
  216.   /*    Load the font program.                                             */
  217.   /*                                                                       */
  218.   /* <InOut>                                                               */
  219.   /*    face   :: A handle to the target face object.                      */
  220.   /*                                                                       */
  221.   /* <Input>                                                               */
  222.   /*    stream :: A handle to the input stream.                            */
  223.   /*                                                                       */
  224.   /* <Return>                                                              */
  225.   /*    FreeType error code.  0 means success.                             */
  226.   /*                                                                       */
  227.   FT_LOCAL_DEF( FT_Error )
  228.   tt_face_load_fpgm( TT_Face    face,
  229.                      FT_Stream  stream )
  230.   {
  231. #ifdef TT_USE_BYTECODE_INTERPRETER
  232.     FT_Error  error;
  233.     FT_ULong  table_len;
  234.     FT_TRACE2(( "Font program " ));
  235.     /* The font program is optional */
  236.     error = face->goto_table( face, TTAG_fpgm, stream, &table_len );
  237.     if ( error )
  238.     {
  239.       face->font_program      = NULL;
  240.       face->font_program_size = 0;
  241.       error                   = TT_Err_Ok;
  242.       FT_TRACE2(( "is missing!n" ));
  243.     }
  244.     else
  245.     {
  246.       face->font_program_size = table_len;
  247.       if ( FT_FRAME_EXTRACT( table_len, face->font_program ) )
  248.         goto Exit;
  249.       FT_TRACE2(( "loaded, %12d bytesn", face->font_program_size ));
  250.     }
  251.   Exit:
  252.     return error;
  253. #else /* !TT_USE_BYTECODE_INTERPRETER */
  254.     FT_UNUSED( face   );
  255.     FT_UNUSED( stream );
  256.     return TT_Err_Ok;
  257. #endif
  258.   }
  259.   /*************************************************************************/
  260.   /*                                                                       */
  261.   /* <Function>                                                            */
  262.   /*    tt_face_load_prep                                                  */
  263.   /*                                                                       */
  264.   /* <Description>                                                         */
  265.   /*    Load the cvt program.                                              */
  266.   /*                                                                       */
  267.   /* <InOut>                                                               */
  268.   /*    face   :: A handle to the target face object.                      */
  269.   /*                                                                       */
  270.   /* <Input>                                                               */
  271.   /*    stream :: A handle to the input stream.                            */
  272.   /*                                                                       */
  273.   /* <Return>                                                              */
  274.   /*    FreeType error code.  0 means success.                             */
  275.   /*                                                                       */
  276.   FT_LOCAL_DEF( FT_Error )
  277.   tt_face_load_prep( TT_Face    face,
  278.                      FT_Stream  stream )
  279.   {
  280. #ifdef TT_USE_BYTECODE_INTERPRETER
  281.     FT_Error  error;
  282.     FT_ULong  table_len;
  283.     FT_TRACE2(( "Prep program " ));
  284.     error = face->goto_table( face, TTAG_prep, stream, &table_len );
  285.     if ( error )
  286.     {
  287.       face->cvt_program      = NULL;
  288.       face->cvt_program_size = 0;
  289.       error                  = TT_Err_Ok;
  290.       FT_TRACE2(( "is missing!n" ));
  291.     }
  292.     else
  293.     {
  294.       face->cvt_program_size = table_len;
  295.       if ( FT_FRAME_EXTRACT( table_len, face->cvt_program ) )
  296.         goto Exit;
  297.       FT_TRACE2(( "loaded, %12d bytesn", face->cvt_program_size ));
  298.     }
  299.   Exit:
  300.     return error;
  301. #else /* !TT_USE_BYTECODE_INTERPRETER */
  302.     FT_UNUSED( face   );
  303.     FT_UNUSED( stream );
  304.     return TT_Err_Ok;
  305. #endif
  306.   }
  307.   /*************************************************************************/
  308.   /*                                                                       */
  309.   /* <Function>                                                            */
  310.   /*    tt_face_load_hdmx                                                  */
  311.   /*                                                                       */
  312.   /* <Description>                                                         */
  313.   /*    Load the `hdmx' table into the face object.                        */
  314.   /*                                                                       */
  315.   /* <Input>                                                               */
  316.   /*    face   :: A handle to the target face object.                      */
  317.   /*                                                                       */
  318.   /*    stream :: A handle to the input stream.                            */
  319.   /*                                                                       */
  320.   /* <Return>                                                              */
  321.   /*    FreeType error code.  0 means success.                             */
  322.   /*                                                                       */
  323.   FT_LOCAL_DEF( FT_Error )
  324.   tt_face_load_hdmx( TT_Face    face,
  325.                      FT_Stream  stream )
  326.   {
  327.     FT_Error   error;
  328.     FT_Memory  memory = stream->memory;
  329.     FT_UInt    version, nn, num_records;
  330.     FT_ULong   table_size, record_size;
  331.     FT_Byte*   p;
  332.     FT_Byte*   limit;
  333.     /* this table is optional */
  334.     error = face->goto_table( face, TTAG_hdmx, stream, &table_size );
  335.     if ( error || table_size < 8 )
  336.       return TT_Err_Ok;
  337.     if ( FT_FRAME_EXTRACT( table_size, face->hdmx_table ) )
  338.       goto Exit;
  339.     p     = face->hdmx_table;
  340.     limit = p + table_size;
  341.     version     = FT_NEXT_USHORT( p );
  342.     num_records = FT_NEXT_USHORT( p );
  343.     record_size = FT_NEXT_ULONG( p );
  344.     /* The maximum number of bytes in an hdmx device record is the */
  345.     /* maximum number of glyphs + 2; this is 0xFFFF + 2; this is   */
  346.     /* the reason why `record_size' is a long (which we read as    */
  347.     /* unsigned long for convenience).  In practice, two bytes     */
  348.     /* sufficient to hold the size value.                          */
  349.     /*                                                             */
  350.     /* There are at least two fonts, HANNOM-A and HANNOM-B version */
  351.     /* 2.0 (2005), which get this wrong: The upper two bytes of    */
  352.     /* the size value are set to 0xFF instead of 0x00.  We catch   */
  353.     /* and fix this.                                               */
  354.     if ( record_size >= 0xFFFF0000UL )
  355.       record_size &= 0xFFFFU;
  356.     /* The limit for `num_records' is a heuristic value. */
  357.     if ( version != 0 || num_records > 255 || record_size > 0x10001L )
  358.     {
  359.       error = TT_Err_Invalid_File_Format;
  360.       goto Fail;
  361.     }
  362.     if ( FT_NEW_ARRAY( face->hdmx_record_sizes, num_records ) )
  363.       goto Fail;
  364.     for ( nn = 0; nn < num_records; nn++ )
  365.     {
  366.       if ( p + record_size > limit )
  367.         break;
  368.       face->hdmx_record_sizes[nn] = p[0];
  369.       p                          += record_size;
  370.     }
  371.     face->hdmx_record_count = nn;
  372.     face->hdmx_table_size   = table_size;
  373.     face->hdmx_record_size  = record_size;
  374.   Exit:
  375.     return error;
  376.   Fail:
  377.     FT_FRAME_RELEASE( face->hdmx_table );
  378.     face->hdmx_table_size = 0;
  379.     goto Exit;
  380.   }
  381.   FT_LOCAL_DEF( void )
  382.   tt_face_free_hdmx( TT_Face  face )
  383.   {
  384.     FT_Stream  stream = face->root.stream;
  385.     FT_Memory  memory = stream->memory;
  386.     FT_FREE( face->hdmx_record_sizes );
  387.     FT_FRAME_RELEASE( face->hdmx_table );
  388.   }
  389.   /*************************************************************************/
  390.   /*                                                                       */
  391.   /* Return the advance width table for a given pixel size if it is found  */
  392.   /* in the font's `hdmx' table (if any).                                  */
  393.   /*                                                                       */
  394.   FT_LOCAL_DEF( FT_Byte* )
  395.   tt_face_get_device_metrics( TT_Face  face,
  396.                               FT_UInt  ppem,
  397.                               FT_UInt  gindex )
  398.   {
  399.     FT_UInt   nn;
  400.     FT_Byte*  result      = NULL;
  401.     FT_ULong  record_size = face->hdmx_record_size;
  402.     FT_Byte*  record      = face->hdmx_table + 8;
  403.     for ( nn = 0; nn < face->hdmx_record_count; nn++ )
  404.       if ( face->hdmx_record_sizes[nn] == ppem )
  405.       {
  406.         gindex += 2;
  407.         if ( gindex < record_size )
  408.           result = record + nn * record_size + gindex;
  409.         break;
  410.       }
  411.     return result;
  412.   }
  413. /* END */