otvgpos.c

来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· C语言 代码 · 共 1,017 行 · 第 1/3 页

C
1,017
字号
/***************************************************************************/
/*                                                                         */
/*  otvgpos.c                                                              */
/*                                                                         */
/*    OpenType GPOS table validation (body).                               */
/*                                                                         */
/*  Copyright 2002, 2004, 2005, 2006, 2007, 2008 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 "otvalid.h"
#include "otvcommn.h"
#include "otvgpos.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_otvgpos


  static void
  otv_Anchor_validate( FT_Bytes       table,
                       OTV_Validator  valid );

  static void
  otv_MarkArray_validate( FT_Bytes       table,
                          OTV_Validator  valid );


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                      UTILITY FUNCTIONS                        *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

#define BaseArrayFunc       otv_x_sxy
#define LigatureAttachFunc  otv_x_sxy
#define Mark2ArrayFunc      otv_x_sxy

  /* uses valid->extra1 (counter)                             */
  /* uses valid->extra2 (boolean to handle NULL anchor field) */

  static void
  otv_x_sxy( FT_Bytes       table,
             OTV_Validator  valid )
  {
    FT_Bytes  p = table;
    FT_UInt   Count, count1, table_size;


    OTV_ENTER;

    OTV_LIMIT_CHECK( 2 );

    Count = FT_NEXT_USHORT( p );

    OTV_TRACE(( " (Count = %d)\n", Count ));

    OTV_LIMIT_CHECK( Count * valid->extra1 * 2 );

    table_size = Count * valid->extra1 * 2 + 2;

    for ( ; Count > 0; Count-- )
      for ( count1 = valid->extra1; count1 > 0; count1-- )
      {
        OTV_OPTIONAL_TABLE( anchor_offset );


        OTV_OPTIONAL_OFFSET( anchor_offset );

        if ( valid->extra2 )
        {
          OTV_SIZE_CHECK( anchor_offset );
          if ( anchor_offset )
            otv_Anchor_validate( table + anchor_offset, valid );
        }
        else
          otv_Anchor_validate( table + anchor_offset, valid );
      }

    OTV_EXIT;
  }


#define MarkBasePosFormat1Func  otv_u_O_O_u_O_O
#define MarkLigPosFormat1Func   otv_u_O_O_u_O_O
#define MarkMarkPosFormat1Func  otv_u_O_O_u_O_O

  /* sets valid->extra1 (class count) */

  static void
  otv_u_O_O_u_O_O( FT_Bytes       table,
                   OTV_Validator  valid )
  {
    FT_Bytes           p = table;
    FT_UInt            Coverage1, Coverage2, ClassCount;
    FT_UInt            Array1, Array2;
    OTV_Validate_Func  func;


    OTV_ENTER;

    p += 2;     /* skip PosFormat */

    OTV_LIMIT_CHECK( 10 );
    Coverage1  = FT_NEXT_USHORT( p );
    Coverage2  = FT_NEXT_USHORT( p );
    ClassCount = FT_NEXT_USHORT( p );
    Array1     = FT_NEXT_USHORT( p );
    Array2     = FT_NEXT_USHORT( p );

    otv_Coverage_validate( table + Coverage1, valid, -1 );
    otv_Coverage_validate( table + Coverage2, valid, -1 );

    otv_MarkArray_validate( table + Array1, valid );

    valid->nesting_level++;
    func          = valid->func[valid->nesting_level];
    valid->extra1 = ClassCount;

    func( table + Array2, valid );

    valid->nesting_level--;

    OTV_EXIT;
  }


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                        VALUE RECORDS                          *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  static FT_UInt
  otv_value_length( FT_UInt  format )
  {
    FT_UInt  count;


    count = ( ( format & 0xAA ) >> 1 ) + ( format & 0x55 );
    count = ( ( count  & 0xCC ) >> 2 ) + ( count  & 0x33 );
    count = ( ( count  & 0xF0 ) >> 4 ) + ( count  & 0x0F );

    return count * 2;
  }


  /* uses valid->extra3 (pointer to base table) */

  static void
  otv_ValueRecord_validate( FT_Bytes       table,
                            FT_UInt        format,
                            OTV_Validator  valid )
  {
    FT_Bytes  p = table;
    FT_UInt   count;

#ifdef FT_DEBUG_LEVEL_TRACE
    FT_Int    loop;
    FT_ULong  res = 0;


    OTV_NAME_ENTER( "ValueRecord" );

    /* display `format' in dual representation */
    for ( loop = 7; loop >= 0; loop-- )
    {
      res <<= 4;
      res  += ( format >> loop ) & 1;
    }

    OTV_TRACE(( " (format 0b%08lx)\n", res ));
#endif

    if ( format >= 0x100 )
      FT_INVALID_FORMAT;

    for ( count = 4; count > 0; count-- )
    {
      if ( format & 1 )
      {
        /* XPlacement, YPlacement, XAdvance, YAdvance */
        OTV_LIMIT_CHECK( 2 );
        p += 2;
      }

      format >>= 1;
    }

    for ( count = 4; count > 0; count-- )
    {
      if ( format & 1 )
      {
        FT_UInt   table_size;

        OTV_OPTIONAL_TABLE( device );


        /* XPlaDevice, YPlaDevice, XAdvDevice, YAdvDevice */
        OTV_LIMIT_CHECK( 2 );
        OTV_OPTIONAL_OFFSET( device );

        /* XXX: this value is usually too small, especially if the current */
        /* ValueRecord is part of an array -- getting the correct table    */
        /* size is probably not worth the trouble                          */

        table_size = p - valid->extra3;

        OTV_SIZE_CHECK( device );
        if ( device )
          otv_Device_validate( valid->extra3 + device, valid );
      }
      format >>= 1;
    }

    OTV_EXIT;
  }


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                           ANCHORS                             *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  static void
  otv_Anchor_validate( FT_Bytes       table,
                       OTV_Validator  valid )
  {
    FT_Bytes  p = table;
    FT_UInt   AnchorFormat;


    OTV_NAME_ENTER( "Anchor");

    OTV_LIMIT_CHECK( 6 );
    AnchorFormat = FT_NEXT_USHORT( p );

    OTV_TRACE(( " (format %d)\n", AnchorFormat ));

    p += 4;     /* skip XCoordinate and YCoordinate */

    switch ( AnchorFormat )
    {
    case 1:
      break;

    case 2:
      OTV_LIMIT_CHECK( 2 );  /* AnchorPoint */
      break;

    case 3:
      {
        FT_UInt   table_size;

        OTV_OPTIONAL_TABLE( XDeviceTable );
        OTV_OPTIONAL_TABLE( YDeviceTable );


        OTV_LIMIT_CHECK( 4 );
        OTV_OPTIONAL_OFFSET( XDeviceTable );
        OTV_OPTIONAL_OFFSET( YDeviceTable );

        table_size = 6 + 4;

        OTV_SIZE_CHECK( XDeviceTable );
        if ( XDeviceTable )
          otv_Device_validate( table + XDeviceTable, valid );

        OTV_SIZE_CHECK( YDeviceTable );
        if ( YDeviceTable )
          otv_Device_validate( table + YDeviceTable, valid );
      }
      break;

    default:
      FT_INVALID_FORMAT;
    }

    OTV_EXIT;
  }


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                         MARK ARRAYS                           *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  static void
  otv_MarkArray_validate( FT_Bytes       table,
                          OTV_Validator  valid )
  {
    FT_Bytes  p = table;
    FT_UInt   MarkCount;


    OTV_NAME_ENTER( "MarkArray" );

    OTV_LIMIT_CHECK( 2 );
    MarkCount = FT_NEXT_USHORT( p );

    OTV_TRACE(( " (MarkCount = %d)\n", MarkCount ));

    OTV_LIMIT_CHECK( MarkCount * 4 );

    /* MarkRecord */
    for ( ; MarkCount > 0; MarkCount-- )
    {
      p += 2;   /* skip Class */
      /* MarkAnchor */
      otv_Anchor_validate( table + FT_NEXT_USHORT( p ), valid );
    }

    OTV_EXIT;
  }

⌨️ 快捷键说明

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