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

📄 ttcmap.c

📁 一个类似windows
💻 C
📖 第 1 页 / 共 5 页
字号:
  static void
  tt_cmap4_reset( TT_CMap4  cmap,
                  FT_UInt   code,
                  FT_UInt   range_index )
  {
    if ( tt_cmap4_set_range( cmap, range_index ) >= 0 )
    {
      cmap->cur_charcode = code;
      tt_cmap4_next( cmap );
    }
  }

#endif /* OPT_CMAP4 */



  FT_CALLBACK_DEF( FT_Error )
  tt_cmap4_validate( FT_Byte*      table,
                     FT_Validator  valid )
  {
    FT_Byte*  p      = table + 2;               /* skip format */
    FT_UInt   length = TT_NEXT_USHORT( p );
    FT_Byte   *ends, *starts, *offsets, *deltas, *glyph_ids;
    FT_UInt   num_segs;
    FT_Error  error = SFNT_Err_Ok;


    /* in certain fonts, the `length' field is invalid and goes */
    /* out of bound.  We try to correct this here...            */
    if ( length < 16 )
      FT_INVALID_TOO_SHORT;

    if ( table + length > valid->limit )
    {
      if ( valid->level >= FT_VALIDATE_TIGHT )
        FT_INVALID_TOO_SHORT;

      length = (FT_UInt)( valid->limit - table );
    }

    p        = table + 6;
    num_segs = TT_NEXT_USHORT( p );   /* read segCountX2 */

    if ( valid->level >= FT_VALIDATE_PARANOID )
    {
      /* check that we have an even value here */
      if ( num_segs & 1 )
        FT_INVALID_DATA;
    }

    num_segs /= 2;

    /* check the search parameters - even though we never use them */
    /*                                                             */
    if ( valid->level >= FT_VALIDATE_PARANOID )
    {
      /* check the values of 'searchRange', 'entrySelector', 'rangeShift' */
      FT_UInt  search_range   = TT_NEXT_USHORT( p );
      FT_UInt  entry_selector = TT_NEXT_USHORT( p );
      FT_UInt  range_shift    = TT_NEXT_USHORT( p );


      if ( ( search_range | range_shift ) & 1 )  /* must be even values */
        FT_INVALID_DATA;

      search_range /= 2;
      range_shift  /= 2;

      /* `search range' is the greatest power of 2 that is <= num_segs */

      if ( search_range                > num_segs                 ||
           search_range * 2            < num_segs                 ||
           search_range + range_shift != num_segs                 ||
           search_range               != ( 1U << entry_selector ) )
        FT_INVALID_DATA;
    }

    ends      = table   + 14;
    starts    = table   + 16 + num_segs * 2;
    deltas    = starts  + num_segs * 2;
    offsets   = deltas  + num_segs * 2;
    glyph_ids = offsets + num_segs * 2;

    if ( glyph_ids > table + length )
      FT_INVALID_TOO_SHORT;

    /* check last segment, its end count must be FFFF */
    if ( valid->level >= FT_VALIDATE_PARANOID )
    {
      p = ends + ( num_segs - 1 ) * 2;
      if ( TT_PEEK_USHORT( p ) != 0xFFFFU )
        FT_INVALID_DATA;
    }

    /* check that segments are sorted in increasing order and do not */
    /* overlap; check also the offsets                               */
    {
      FT_UInt  start, end, last = 0, offset, n;
      FT_Int   delta;


      for ( n = 0; n < num_segs; n++ )
      {
        p = starts + n * 2;
        start = TT_PEEK_USHORT( p );
        p = ends + n * 2;
        end = TT_PEEK_USHORT( p );
        p = deltas + n * 2;
        delta = TT_PEEK_SHORT( p );
        p = offsets + n * 2;
        offset = TT_PEEK_USHORT( p );

        if ( start > end )
          FT_INVALID_DATA;

        /* this test should be performed at default validation level;  */
        /* unfortunately, some popular Asian fonts present overlapping */
        /* ranges in their charmaps                                    */
        /*                                                             */
        if ( n > 0 && start <= last )
        {
          if ( valid->level >= FT_VALIDATE_TIGHT )
            FT_INVALID_DATA;
          else
            error = SFNT_Err_Invalid_CharMap_Format;
        }

        if ( offset && offset != 0xFFFFU )
        {
          p += offset;  /* start of glyph id array */

          /* check that we point within the glyph ids table only */
          if ( valid->level >= FT_VALIDATE_TIGHT )
          {
            if ( p < glyph_ids                                ||
                 p + ( end - start + 1 ) * 2 > table + length )
              FT_INVALID_DATA;
          }
          else
          {
            if ( p < glyph_ids                              ||
                 p + ( end - start + 1 ) * 2 > valid->limit )
              FT_INVALID_DATA;
          }

          /* check glyph indices within the segment range */
          if ( valid->level >= FT_VALIDATE_TIGHT )
          {
            FT_UInt  i, idx;


            for ( i = start; i < end; i++ )
            {
              idx = FT_NEXT_USHORT( p );
              if ( idx != 0 )
              {
                idx = (FT_UInt)( idx + delta ) & 0xFFFFU;

                if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
                  FT_INVALID_GLYPH_ID;
              }
            }
          }
        }
        else if ( offset == 0xFFFFU )
        {
          /* Some fonts (erroneously?) use a range offset of 0xFFFF */
          /* to mean missing glyph in cmap table                    */
          /*                                                        */
          if ( valid->level >= FT_VALIDATE_PARANOID                     ||
               n != num_segs - 1                                        ||
               !( start == 0xFFFFU && end == 0xFFFFU && delta == 0x1U ) )
            FT_INVALID_DATA;
        }

        last = end;
      }
    }

    return error;
  }


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


    if ( char_code < 0x10000UL )
    {
      FT_UInt   idx, num_segs2;
      FT_Int    delta;
      FT_UInt   code = (FT_UInt)char_code;
      FT_Byte*  p;

      p         = table + 6;
      num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );  /* be paranoid! */

      if ( !cmap->unsorted )
      {
        /* Some fonts have more than 170 segments in their charmaps! */
        /* We changed this function to use a more efficient binary   */
        /* search for improving performance                          */
        FT_UInt  min = 0;
        FT_UInt  max = num_segs2 >> 1;
        FT_UInt  mid, start, end, offset;


        while ( min < max )
        {
          mid   = ( min + max ) >> 1;
          p     = table + 14 + mid * 2;
          end   = TT_NEXT_USHORT( p );
          p    += num_segs2;
          start = TT_PEEK_USHORT( p);

          if ( code < start )
            max = mid;
          else if ( code > end )
            min = mid + 1;
          else
          {
            /* we found the segment */
            idx = code;

            p += num_segs2;
            delta = TT_PEEK_SHORT( p );

            p += num_segs2;
            offset = TT_PEEK_USHORT( p );

            if ( offset == 0xFFFFU )
              goto Exit;

            if ( offset != 0 )
            {
              p  += offset + 2 * ( idx - start );
              idx = TT_PEEK_USHORT( p );
            }

            if ( idx != 0 )
              result = (FT_UInt)( idx + delta ) & 0xFFFFU;

            goto Exit;
          }
        }
      }
      else
      {
        FT_UInt   n;
        FT_Byte*  q;


        p = table + 14;               /* ends table   */
        q = table + 16 + num_segs2;   /* starts table */


        for ( n = 0; n < num_segs2; n += 2 )
        {
          FT_UInt  end   = TT_NEXT_USHORT( p );
          FT_UInt  start = TT_NEXT_USHORT( q );
          FT_UInt  offset;


          if ( code < start )
            break;

          if ( code <= end )
          {
            idx = code;

            p = q + num_segs2 - 2;
            delta = TT_PEEK_SHORT( p );
            p += num_segs2;
            offset = TT_PEEK_USHORT( p );

            if ( offset == 0xFFFFU )
              goto Exit;

            if ( offset != 0 )
            {
              p  += offset + 2 * ( idx - start );
              idx = TT_PEEK_USHORT( p );
            }

            if ( idx != 0 )
              result = (FT_UInt)( idx + delta ) & 0xFFFFU;
          }
        }
      }
    }

  Exit:
    return result;
  }


  FT_CALLBACK_DEF( FT_UInt )
  tt_cmap4_char_next( TT_CMap     cmap,
                      FT_UInt32  *pchar_code )
  {
    FT_Byte*   table     = cmap->data;
    FT_UInt32  result    = 0;
    FT_UInt    gindex    = 0;
    FT_UInt32  char_code = *pchar_code;
    FT_Byte*   p;
    FT_UInt    code, num_segs2;


    if ( char_code >= 0xFFFFUL )
      goto Exit;

#ifdef OPT_CMAP4
      {
        TT_CMap4  cmap4 = (TT_CMap4)cmap;


        if ( char_code == cmap4->old_charcode )
        {
          result = cmap4->cur_charcode;
          gindex = cmap4->cur_gindex;
          if ( result != 0 )
          {
            tt_cmap4_next( cmap4 );
            goto Exit;
          }
        }
      }
#endif /* OPT_CMAP4 */

    code      = (FT_UInt)char_code + 1;
    p         = table + 6;
    num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); /* ensure even-ness */

    if ( !cmap->unsorted )
    {
      for (;;)
      {
        /* Some fonts have more than 170 segments in their charmaps! */
        /* We changed this function to use a more efficient binary   */
        /* search                                                    */
        FT_UInt  offset;
        FT_Int   delta;
        FT_UInt  min = 0;
        FT_UInt  max = num_segs2 >> 1;
        FT_UInt  mid, start, end;
        FT_UInt  hi;


        /* we begin by finding the segment which end is
           closer to our code point */
        hi = max + 1;
        while ( min < max )
        {
          mid = ( min + max ) >> 1;
          p   = table + 14 + mid * 2;
          end = TT_PEEK_USHORT( p );

          if ( end < code )
            min = mid + 1;
          else
          {
            hi  = mid;
            max = mid;
          }
        }

        if ( hi > max )
        {
          /* the point is behind the last segment;
             we will exit right now */
          goto Exit;
        }

        p   = table + 14 + hi * 2;
        end = TT_PEEK_USHORT( p );

        p    += 2 + num_segs2;
        start = TT_PEEK_USHORT( p );

        if ( code < start )
          code = start;

        p    += num_segs2;
        delta = TT_PEEK_USHORT( p );

        p     += num_segs2;
        offset = TT_PEEK_USHORT( p );

⌨️ 快捷键说明

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