otvgpos.c

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

C
1,017
字号

  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                     GPOS LOOKUP TYPE 1                        *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

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

  static void
  otv_SinglePos_validate( FT_Bytes       table,
                          OTV_Validator  valid )
  {
    FT_Bytes  p = table;
    FT_UInt   PosFormat;


    OTV_NAME_ENTER( "SinglePos" );

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

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

    valid->extra3 = table;

    switch ( PosFormat )
    {
    case 1:     /* SinglePosFormat1 */
      {
        FT_UInt  Coverage, ValueFormat;


        OTV_LIMIT_CHECK( 4 );
        Coverage    = FT_NEXT_USHORT( p );
        ValueFormat = FT_NEXT_USHORT( p );

        otv_Coverage_validate( table + Coverage, valid, -1 );
        otv_ValueRecord_validate( p, ValueFormat, valid ); /* Value */
      }
      break;

    case 2:     /* SinglePosFormat2 */
      {
        FT_UInt  Coverage, ValueFormat, ValueCount, len_value;


        OTV_LIMIT_CHECK( 6 );
        Coverage    = FT_NEXT_USHORT( p );
        ValueFormat = FT_NEXT_USHORT( p );
        ValueCount  = FT_NEXT_USHORT( p );

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

        len_value = otv_value_length( ValueFormat );

        otv_Coverage_validate( table + Coverage, valid, ValueCount );

        OTV_LIMIT_CHECK( ValueCount * len_value );

        /* Value */
        for ( ; ValueCount > 0; ValueCount-- )
        {
          otv_ValueRecord_validate( p, ValueFormat, valid );
          p += len_value;
        }
      }
      break;

    default:
      FT_INVALID_FORMAT;
    }

    OTV_EXIT;
  }


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                     GPOS LOOKUP TYPE 2                        *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  static void
  otv_PairSet_validate( FT_Bytes       table,
                        FT_UInt        format1,
                        FT_UInt        format2,
                        OTV_Validator  valid )
  {
    FT_Bytes  p = table;
    FT_UInt   value_len1, value_len2, PairValueCount;


    OTV_NAME_ENTER( "PairSet" );

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

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

    value_len1 = otv_value_length( format1 );
    value_len2 = otv_value_length( format2 );

    OTV_LIMIT_CHECK( PairValueCount * ( value_len1 + value_len2 + 2 ) );

    /* PairValueRecord */
    for ( ; PairValueCount > 0; PairValueCount-- )
    {
      p += 2;       /* skip SecondGlyph */

      if ( format1 )
        otv_ValueRecord_validate( p, format1, valid ); /* Value1 */
      p += value_len1;

      if ( format2 )
        otv_ValueRecord_validate( p, format2, valid ); /* Value2 */
      p += value_len2;
    }

    OTV_EXIT;
  }


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

  static void
  otv_PairPos_validate( FT_Bytes       table,
                        OTV_Validator  valid )
  {
    FT_Bytes  p = table;
    FT_UInt   PosFormat;


    OTV_NAME_ENTER( "PairPos" );

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

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

    valid->extra3 = table;

    switch ( PosFormat )
    {
    case 1:     /* PairPosFormat1 */
      {
        FT_UInt  Coverage, ValueFormat1, ValueFormat2, PairSetCount;


        OTV_LIMIT_CHECK( 8 );
        Coverage     = FT_NEXT_USHORT( p );
        ValueFormat1 = FT_NEXT_USHORT( p );
        ValueFormat2 = FT_NEXT_USHORT( p );
        PairSetCount = FT_NEXT_USHORT( p );

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

        otv_Coverage_validate( table + Coverage, valid, -1 );

        OTV_LIMIT_CHECK( PairSetCount * 2 );

        /* PairSetOffset */
        for ( ; PairSetCount > 0; PairSetCount-- )
          otv_PairSet_validate( table + FT_NEXT_USHORT( p ),
                                ValueFormat1, ValueFormat2, valid );
      }
      break;

    case 2:     /* PairPosFormat2 */
      {
        FT_UInt  Coverage, ValueFormat1, ValueFormat2, ClassDef1, ClassDef2;
        FT_UInt  ClassCount1, ClassCount2, len_value1, len_value2, count;


        OTV_LIMIT_CHECK( 14 );
        Coverage     = FT_NEXT_USHORT( p );
        ValueFormat1 = FT_NEXT_USHORT( p );
        ValueFormat2 = FT_NEXT_USHORT( p );
        ClassDef1    = FT_NEXT_USHORT( p );
        ClassDef2    = FT_NEXT_USHORT( p );
        ClassCount1  = FT_NEXT_USHORT( p );
        ClassCount2  = FT_NEXT_USHORT( p );

        OTV_TRACE(( " (ClassCount1 = %d)\n", ClassCount1 ));
        OTV_TRACE(( " (ClassCount2 = %d)\n", ClassCount2 ));

        len_value1 = otv_value_length( ValueFormat1 );
        len_value2 = otv_value_length( ValueFormat2 );

        otv_Coverage_validate( table + Coverage, valid, -1 );
        otv_ClassDef_validate( table + ClassDef1, valid );
        otv_ClassDef_validate( table + ClassDef2, valid );

        OTV_LIMIT_CHECK( ClassCount1 * ClassCount2 *
                     ( len_value1 + len_value2 ) );

        /* Class1Record */
        for ( ; ClassCount1 > 0; ClassCount1-- )
        {
          /* Class2Record */
          for ( count = ClassCount2; count > 0; count-- )
          {
            if ( ValueFormat1 )
              /* Value1 */
              otv_ValueRecord_validate( p, ValueFormat1, valid );
            p += len_value1;

            if ( ValueFormat2 )
              /* Value2 */
              otv_ValueRecord_validate( p, ValueFormat2, valid );
            p += len_value2;
          }
        }
      }
      break;

    default:
      FT_INVALID_FORMAT;
    }

    OTV_EXIT;
  }


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                     GPOS LOOKUP TYPE 3                        *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  static void
  otv_CursivePos_validate( FT_Bytes       table,
                           OTV_Validator  valid )
  {
    FT_Bytes  p = table;
    FT_UInt   PosFormat;


    OTV_NAME_ENTER( "CursivePos" );

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

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

    switch ( PosFormat )
    {
    case 1:     /* CursivePosFormat1 */
      {
        FT_UInt   table_size;
        FT_UInt   Coverage, EntryExitCount;

        OTV_OPTIONAL_TABLE( EntryAnchor );
        OTV_OPTIONAL_TABLE( ExitAnchor  );


        OTV_LIMIT_CHECK( 4 );
        Coverage       = FT_NEXT_USHORT( p );
        EntryExitCount = FT_NEXT_USHORT( p );

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

        otv_Coverage_validate( table + Coverage, valid, EntryExitCount );

        OTV_LIMIT_CHECK( EntryExitCount * 4 );

        table_size = EntryExitCount * 4 + 4;

        /* EntryExitRecord */
        for ( ; EntryExitCount > 0; EntryExitCount-- )
        {
          OTV_OPTIONAL_OFFSET( EntryAnchor );
          OTV_OPTIONAL_OFFSET( ExitAnchor  );

          OTV_SIZE_CHECK( EntryAnchor );
          if ( EntryAnchor )
            otv_Anchor_validate( table + EntryAnchor, valid );

          OTV_SIZE_CHECK( ExitAnchor );
          if ( ExitAnchor )
            otv_Anchor_validate( table + ExitAnchor, valid );
        }
      }
      break;

    default:
      FT_INVALID_FORMAT;
    }

    OTV_EXIT;
  }


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                     GPOS LOOKUP TYPE 4                        *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  /* UNDOCUMENTED (in OpenType 1.5):              */
  /* BaseRecord tables can contain NULL pointers. */

  /* sets valid->extra2 (1) */

  static void
  otv_MarkBasePos_validate( FT_Bytes       table,
                            OTV_Validator  valid )
  {
    FT_Bytes  p = table;
    FT_UInt   PosFormat;


    OTV_NAME_ENTER( "MarkBasePos" );

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

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

    switch ( PosFormat )
    {
    case 1:
      valid->extra2 = 1;
      OTV_NEST2( MarkBasePosFormat1, BaseArray );
      OTV_RUN( table, valid );
      break;

    default:
      FT_INVALID_FORMAT;
    }

⌨️ 快捷键说明

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