⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ttcmap.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
/***************************************************************************/
/*                                                                         */
/*  ttcmap.c                                                               */
/*                                                                         */
/*    TrueType character mapping table (cmap) support (body).              */
/*                                                                         */
/*  Copyright 2002, 2003, 2004, 2005, 2006, 2007 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 "sferrors.h"           /* must come before FT_INTERNAL_VALIDATE_H */

#include FT_INTERNAL_VALIDATE_H
#include FT_INTERNAL_STREAM_H
#include "ttload.h"
#include "ttcmap.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_ttcmap


#define TT_PEEK_SHORT   FT_PEEK_SHORT
#define TT_PEEK_USHORT  FT_PEEK_USHORT
#define TT_PEEK_LONG    FT_PEEK_LONG
#define TT_PEEK_ULONG   FT_PEEK_ULONG

#define TT_NEXT_SHORT   FT_NEXT_SHORT
#define TT_NEXT_USHORT  FT_NEXT_USHORT
#define TT_NEXT_LONG    FT_NEXT_LONG
#define TT_NEXT_ULONG   FT_NEXT_ULONG


  FT_CALLBACK_DEF( FT_Error )
  tt_cmap_init( TT_CMap   cmap,
                FT_Byte*  table )
  {
    cmap->data = table;
    return SFNT_Err_Ok;
  }


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                           FORMAT 0                            *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  /*************************************************************************/
  /*                                                                       */
  /* TABLE OVERVIEW                                                        */
  /* --------------                                                        */
  /*                                                                       */
  /*   NAME        OFFSET         TYPE          DESCRIPTION                */
  /*                                                                       */
  /*   format      0              USHORT        must be 0                  */
  /*   length      2              USHORT        table length in bytes      */
  /*   language    4              USHORT        Mac language code          */
  /*   glyph_ids   6              BYTE[256]     array of glyph indices     */
  /*               262                                                     */
  /*                                                                       */

#ifdef TT_CONFIG_CMAP_FORMAT_0

  FT_CALLBACK_DEF( FT_Error )
  tt_cmap0_validate( FT_Byte*      table,
                     FT_Validator  valid )
  {
    FT_Byte*  p      = table + 2;
    FT_UInt   length = TT_NEXT_USHORT( p );


    if ( table + length > valid->limit || length < 262 )
      FT_INVALID_TOO_SHORT;

    /* check glyph indices whenever necessary */
    if ( valid->level >= FT_VALIDATE_TIGHT )
    {
      FT_UInt  n, idx;


      p = table + 6;
      for ( n = 0; n < 256; n++ )
      {
        idx = *p++;
        if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
          FT_INVALID_GLYPH_ID;
      }
    }

    return SFNT_Err_Ok;
  }


  FT_CALLBACK_DEF( FT_UInt )
  tt_cmap0_char_index( TT_CMap    cmap,
                       FT_UInt32  char_code )
  {
    FT_Byte*  table = cmap->data;


    return char_code < 256 ? table[6 + char_code] : 0;
  }


  FT_CALLBACK_DEF( FT_UInt )
  tt_cmap0_char_next( TT_CMap     cmap,
                      FT_UInt32  *pchar_code )
  {
    FT_Byte*   table    = cmap->data;
    FT_UInt32  charcode = *pchar_code;
    FT_UInt32  result   = 0;
    FT_UInt    gindex   = 0;


    table += 6;  /* go to glyph ids */
    while ( ++charcode < 256 )
    {
      gindex = table[charcode];
      if ( gindex != 0 )
      {
        result = charcode;
        break;
      }
    }

    *pchar_code = result;
    return gindex;
  }


  FT_CALLBACK_DEF( FT_Error )
  tt_cmap0_get_info( TT_CMap       cmap,
                     TT_CMapInfo  *cmap_info )
  {
    FT_Byte*  p = cmap->data + 4;


    cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );

    return SFNT_Err_Ok;
  }


  FT_CALLBACK_TABLE_DEF
  const TT_CMap_ClassRec  tt_cmap0_class_rec =
  {
    {
      sizeof ( TT_CMapRec ),

      (FT_CMap_InitFunc)     tt_cmap_init,
      (FT_CMap_DoneFunc)     NULL,
      (FT_CMap_CharIndexFunc)tt_cmap0_char_index,
      (FT_CMap_CharNextFunc) tt_cmap0_char_next
    },
    0,
    (TT_CMap_ValidateFunc)   tt_cmap0_validate,
    (TT_CMap_Info_GetFunc)   tt_cmap0_get_info
  };

#endif /* TT_CONFIG_CMAP_FORMAT_0 */


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                          FORMAT 2                             *****/
  /*****                                                               *****/
  /***** This is used for certain CJK encodings that encode text in a  *****/
  /***** mixed 8/16 bits encoding along the following lines:           *****/
  /*****                                                               *****/
  /***** * Certain byte values correspond to an 8-bit character code   *****/
  /*****   (typically in the range 0..127 for ASCII compatibility).    *****/
  /*****                                                               *****/
  /***** * Certain byte values signal the first byte of a 2-byte       *****/
  /*****   character code (but these values are also valid as the      *****/
  /*****   second byte of a 2-byte character).                         *****/
  /*****                                                               *****/
  /***** The following charmap lookup and iteration functions all      *****/
  /***** assume that the value "charcode" correspond to following:     *****/
  /*****                                                               *****/
  /*****   - For one byte characters, "charcode" is simply the         *****/
  /*****     character code.                                           *****/
  /*****                                                               *****/
  /*****   - For two byte characters, "charcode" is the 2-byte         *****/
  /*****     character code in big endian format.  More exactly:       *****/
  /*****                                                               *****/
  /*****       (charcode >> 8)    is the first byte value              *****/
  /*****       (charcode & 0xFF)  is the second byte value             *****/
  /*****                                                               *****/
  /***** Note that not all values of "charcode" are valid according    *****/
  /***** to these rules, and the function moderately check the         *****/
  /***** arguments.                                                    *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  /*************************************************************************/
  /*                                                                       */
  /* TABLE OVERVIEW                                                        */
  /* --------------                                                        */
  /*                                                                       */
  /*   NAME        OFFSET         TYPE            DESCRIPTION              */
  /*                                                                       */
  /*   format      0              USHORT          must be 2                */
  /*   length      2              USHORT          table length in bytes    */
  /*   language    4              USHORT          Mac language code        */
  /*   keys        6              USHORT[256]     sub-header keys          */
  /*   subs        518            SUBHEAD[NSUBS]  sub-headers array        */
  /*   glyph_ids   518+NSUB*8     USHORT[]        glyph id array           */
  /*                                                                       */
  /* The `keys' table is used to map charcode high-bytes to sub-headers.   */
  /* The value of `NSUBS' is the number of sub-headers defined in the      */
  /* table and is computed by finding the maximum of the `keys' table.     */
  /*                                                                       */
  /* Note that for any n, `keys[n]' is a byte offset within the `subs'     */
  /* table, i.e., it is the corresponding sub-header index multiplied      */
  /* by 8.                                                                 */
  /*                                                                       */
  /* Each sub-header has the following format:                             */
  /*                                                                       */
  /*   NAME        OFFSET      TYPE            DESCRIPTION                 */
  /*                                                                       */
  /*   first       0           USHORT          first valid low-byte        */
  /*   count       2           USHORT          number of valid low-bytes   */
  /*   delta       4           SHORT           see below                   */
  /*   offset      6           USHORT          see below                   */
  /*                                                                       */
  /* A sub-header defines, for each high-byte, the range of valid          */
  /* low-bytes within the charmap.  Note that the range defined by `first' */
  /* and `count' must be completely included in the interval [0..255]      */
  /* according to the specification.                                       */
  /*                                                                       */
  /* If a character code is contained within a given sub-header, then      */
  /* mapping it to a glyph index is done as follows:                       */
  /*                                                                       */
  /* * The value of `offset' is read.  This is a _byte_ distance from the  */
  /*   location of the `offset' field itself into a slice of the           */
  /*   `glyph_ids' table.  Let's call it `slice' (it's a USHORT[] too).    */
  /*                                                                       */
  /* * The value `slice[char.lo - first]' is read.  If it is 0, there is   */
  /*   no glyph for the charcode.  Otherwise, the value of `delta' is      */
  /*   added to it (modulo 65536) to form a new glyph index.               */
  /*                                                                       */
  /* It is up to the validation routine to check that all offsets fall     */
  /* within the glyph ids table (and not within the `subs' table itself or */
  /* outside of the CMap).                                                 */
  /*                                                                       */

#ifdef TT_CONFIG_CMAP_FORMAT_2

  FT_CALLBACK_DEF( FT_Error )
  tt_cmap2_validate( FT_Byte*      table,
                     FT_Validator  valid )
  {
    FT_Byte*  p      = table + 2;           /* skip format */
    FT_UInt   length = TT_PEEK_USHORT( p );
    FT_UInt   n, max_subs;
    FT_Byte*  keys;                         /* keys table */
    FT_Byte*  subs;                         /* sub-headers */
    FT_Byte*  glyph_ids;                    /* glyph id array */


    if ( table + length > valid->limit || length < 6 + 512 )
      FT_INVALID_TOO_SHORT;

    keys = table + 6;

    /* parse keys to compute sub-headers count */
    p        = keys;
    max_subs = 0;
    for ( n = 0; n < 256; n++ )
    {
      FT_UInt  idx = TT_NEXT_USHORT( p );


      /* value must be multiple of 8 */
      if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 )
        FT_INVALID_DATA;

      idx >>= 3;

      if ( idx > max_subs )
        max_subs = idx;
    }

    FT_ASSERT( p == table + 518 );

    subs      = p;
    glyph_ids = subs + (max_subs + 1) * 8;
    if ( glyph_ids > valid->limit )
      FT_INVALID_TOO_SHORT;

    /* parse sub-headers */
    for ( n = 0; n <= max_subs; n++ )
    {
      FT_UInt   first_code, code_count, offset;
      FT_Int    delta;
      FT_Byte*  ids;


      first_code = TT_NEXT_USHORT( p );
      code_count = TT_NEXT_USHORT( p );
      delta      = TT_NEXT_SHORT( p );
      offset     = TT_NEXT_USHORT( p );

      /* check range within 0..255 */
      if ( valid->level >= FT_VALIDATE_PARANOID )
      {
        if ( first_code >= 256 || first_code + code_count > 256 )
          FT_INVALID_DATA;
      }

      /* check offset */
      if ( offset != 0 )
      {
        ids = p - 2 + offset;
        if ( ids < glyph_ids || ids + code_count*2 > table + length )
          FT_INVALID_OFFSET;

        /* check glyph ids */
        if ( valid->level >= FT_VALIDATE_TIGHT )
        {
          FT_Byte*  limit = p + code_count * 2;
          FT_UInt   idx;


          for ( ; p < limit; )
          {
            idx = TT_NEXT_USHORT( p );
            if ( idx != 0 )
            {
              idx = ( idx + delta ) & 0xFFFFU;
              if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
                FT_INVALID_GLYPH_ID;
            }
          }
        }
      }
    }

    return SFNT_Err_Ok;
  }


  /* return sub header corresponding to a given character code */
  /* NULL on invalid charcode                                  */
  static FT_Byte*
  tt_cmap2_get_subheader( FT_Byte*   table,
                          FT_UInt32  char_code )
  {
    FT_Byte*  result = NULL;


    if ( char_code < 0x10000UL )
    {
      FT_UInt   char_lo = (FT_UInt)( char_code & 0xFF );
      FT_UInt   char_hi = (FT_UInt)( char_code >> 8 );
      FT_Byte*  p       = table + 6;    /* keys table */
      FT_Byte*  subs    = table + 518;  /* subheaders table */
      FT_Byte*  sub;


      if ( char_hi == 0 )
      {
        /* an 8-bit character code -- we use subHeader 0 in this case */
        /* to test whether the character code is in the charmap       */
        /*                                                            */
        sub = subs;  /* jump to first sub-header */

        /* check that the sub-header for this byte is 0, which */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -