Click here to Skip to main content
15,885,365 members
Articles / Multimedia / OpenGL

OAG Library (OpenGL) Part 2.3 - Drawing 2D Textures Using the Mouse and Programatically

Rate me:
Please Sign up or sign in to vote.
4.29/5 (6 votes)
22 Oct 2010CPOL3 min read 34K   1.3K   17  
This tutorial shows library code for 2D Textures and how to draw them programatically using the mouse in an MFC application.
/***************************************************************************/
/*                                                                         */
/*  otvcommn.c                                                             */
/*                                                                         */
/*    OpenType common tables validation (body).                            */
/*                                                                         */
/*  Copyright 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 "otvcommn.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_otvcommon


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                       COVERAGE TABLE                          *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  FT_LOCAL_DEF( void )
  otv_Coverage_validate( FT_Bytes       table,
                         OTV_Validator  valid,
                         FT_Int         expected_count )
  {
    FT_Bytes  p = table;
    FT_UInt   CoverageFormat;
    FT_UInt   total = 0;


    OTV_NAME_ENTER( "Coverage" );

    OTV_LIMIT_CHECK( 4 );
    CoverageFormat = FT_NEXT_USHORT( p );

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

    switch ( CoverageFormat )
    {
    case 1:     /* CoverageFormat1 */
      {
        FT_UInt  GlyphCount;
        FT_UInt  i;


        GlyphCount = FT_NEXT_USHORT( p );

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

        OTV_LIMIT_CHECK( GlyphCount * 2 );        /* GlyphArray */

        for ( i = 0; i < GlyphCount; ++i )
        {
          FT_UInt  gid;


          gid = FT_NEXT_USHORT( p );
          if ( gid >= valid->glyph_count )
            FT_INVALID_GLYPH_ID;
        }

        total = GlyphCount;
      }
      break;

    case 2:     /* CoverageFormat2 */
      {
        FT_UInt  n, RangeCount;
        FT_UInt  Start, End, StartCoverageIndex, last = 0;


        RangeCount = FT_NEXT_USHORT( p );

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

        OTV_LIMIT_CHECK( RangeCount * 6 );

        /* RangeRecord */
        for ( n = 0; n < RangeCount; n++ )
        {
          Start              = FT_NEXT_USHORT( p );
          End                = FT_NEXT_USHORT( p );
          StartCoverageIndex = FT_NEXT_USHORT( p );

          if ( Start > End || StartCoverageIndex != total )
            FT_INVALID_DATA;

          if ( End >= valid->glyph_count )
            FT_INVALID_GLYPH_ID;

          if ( n > 0 && Start <= last )
            FT_INVALID_DATA;

          total += End - Start + 1;
          last   = End;
        }
      }
      break;

    default:
      FT_INVALID_FORMAT;
    }

    /* Generally, a coverage table offset has an associated count field.  */
    /* The number of glyphs in the table should match this field.  If     */
    /* there is no associated count, a value of -1 tells us not to check. */
    if ( expected_count != -1 && (FT_UInt)expected_count != total )
      FT_INVALID_DATA;

    OTV_EXIT;
  }


  FT_LOCAL_DEF( FT_UInt )
  otv_Coverage_get_first( FT_Bytes  table )
  {
    FT_Bytes  p = table;


    p += 4;     /* skip CoverageFormat and Glyph/RangeCount */

    return FT_NEXT_USHORT( p );
  }


  FT_LOCAL_DEF( FT_UInt )
  otv_Coverage_get_last( FT_Bytes  table )
  {
    FT_Bytes  p = table;
    FT_UInt   CoverageFormat = FT_NEXT_USHORT( p );
    FT_UInt   count          = FT_NEXT_USHORT( p );     /* Glyph/RangeCount */
    FT_UInt   result = 0;


    switch ( CoverageFormat )
    {
    case 1:
      p += ( count - 1 ) * 2;
      result = FT_NEXT_USHORT( p );
      break;

    case 2:
      p += ( count - 1 ) * 6 + 2;
      result = FT_NEXT_USHORT( p );
      break;

    default:
      ;
    }

    return result;
  }


  FT_LOCAL_DEF( FT_UInt )
  otv_Coverage_get_count( FT_Bytes  table )
  {
    FT_Bytes  p              = table;
    FT_UInt   CoverageFormat = FT_NEXT_USHORT( p );
    FT_UInt   count          = FT_NEXT_USHORT( p );     /* Glyph/RangeCount */
    FT_UInt   result         = 0;


    switch ( CoverageFormat )
    {
    case 1:
      return count;

    case 2:
      {
        FT_UInt  Start, End;


        for ( ; count > 0; count-- )
        {
          Start = FT_NEXT_USHORT( p );
          End   = FT_NEXT_USHORT( p );
          p    += 2;                    /* skip StartCoverageIndex */

          result += End - Start + 1;
        }
      }
      break;

    default:
      ;
    }

    return result;
  }


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                   CLASS DEFINITION TABLE                      *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  FT_LOCAL_DEF( void )
  otv_ClassDef_validate( FT_Bytes       table,
                         OTV_Validator  valid )
  {
    FT_Bytes  p = table;
    FT_UInt   ClassFormat;


    OTV_NAME_ENTER( "ClassDef" );

    OTV_LIMIT_CHECK( 4 );
    ClassFormat = FT_NEXT_USHORT( p );

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

    switch ( ClassFormat )
    {
    case 1:     /* ClassDefFormat1 */
      {
        FT_UInt  StartGlyph;
        FT_UInt  GlyphCount;


        OTV_LIMIT_CHECK( 4 );

        StartGlyph = FT_NEXT_USHORT( p );
        GlyphCount = FT_NEXT_USHORT( p );

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

        OTV_LIMIT_CHECK( GlyphCount * 2 );    /* ClassValueArray */

        if ( StartGlyph + GlyphCount - 1 >= valid->glyph_count )
          FT_INVALID_GLYPH_ID;
      }
      break;

    case 2:     /* ClassDefFormat2 */
      {
        FT_UInt  n, ClassRangeCount;
        FT_UInt  Start, End, last = 0;


        ClassRangeCount = FT_NEXT_USHORT( p );

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

        OTV_LIMIT_CHECK( ClassRangeCount * 6 );

        /* ClassRangeRecord */
        for ( n = 0; n < ClassRangeCount; n++ )
        {
          Start = FT_NEXT_USHORT( p );
          End   = FT_NEXT_USHORT( p );
          p    += 2;                        /* skip Class */

          if ( Start > End || ( n > 0 && Start <= last ) )
            FT_INVALID_DATA;

          if ( End >= valid->glyph_count )
            FT_INVALID_GLYPH_ID;

          last = End;
        }
      }
      break;

    default:
      FT_INVALID_FORMAT;
    }

    /* no need to check glyph indices used as input to class definition   */
    /* tables since even invalid glyph indices return a meaningful result */

    OTV_EXIT;
  }


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                      DEVICE TABLE                             *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  FT_LOCAL_DEF( void )
  otv_Device_validate( FT_Bytes       table,
                       OTV_Validator  valid )
  {
    FT_Bytes  p = table;
    FT_UInt   StartSize, EndSize, DeltaFormat, count;


    OTV_NAME_ENTER( "Device" );

    OTV_LIMIT_CHECK( 8 );
    StartSize   = FT_NEXT_USHORT( p );
    EndSize     = FT_NEXT_USHORT( p );
    DeltaFormat = FT_NEXT_USHORT( p );

    if ( DeltaFormat < 1 || DeltaFormat > 3 )
      FT_INVALID_FORMAT;

    if ( EndSize < StartSize )
      FT_INVALID_DATA;

    count = EndSize - StartSize + 1;
    OTV_LIMIT_CHECK( ( 1 << DeltaFormat ) * count / 8 );  /* DeltaValue */

    OTV_EXIT;
  }


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                         LOOKUPS                               *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  /* uses valid->type_count */
  /* uses valid->type_funcs */

  FT_LOCAL_DEF( void )
  otv_Lookup_validate( FT_Bytes       table,
                       OTV_Validator  valid )
  {
    FT_Bytes           p = table;
    FT_UInt            LookupType, SubTableCount;
    OTV_Validate_Func  validate;


    OTV_NAME_ENTER( "Lookup" );

    OTV_LIMIT_CHECK( 6 );
    LookupType    = FT_NEXT_USHORT( p );
    p            += 2;                      /* skip LookupFlag */
    SubTableCount = FT_NEXT_USHORT( p );

    OTV_TRACE(( " (type %d)\n", LookupType ));

    if ( LookupType == 0 || LookupType > valid->type_count )
      FT_INVALID_DATA;

    validate = valid->type_funcs[LookupType - 1];

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

    OTV_LIMIT_CHECK( SubTableCount * 2 );

    /* SubTable */
    for ( ; SubTableCount > 0; SubTableCount-- )
      validate( table + FT_NEXT_USHORT( p ), valid );

    OTV_EXIT;
  }


  /* uses valid->lookup_count */

  FT_LOCAL_DEF( void )
  otv_LookupList_validate( FT_Bytes       table,
                           OTV_Validator  valid )
  {
    FT_Bytes  p = table;
    FT_UInt   LookupCount;


    OTV_NAME_ENTER( "LookupList" );

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

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

    OTV_LIMIT_CHECK( LookupCount * 2 );

    valid->lookup_count = LookupCount;

    /* Lookup */
    for ( ; LookupCount > 0; LookupCount-- )
      otv_Lookup_validate( table + FT_NEXT_USHORT( p ), valid );

    OTV_EXIT;
  }


  static FT_UInt
  otv_LookupList_get_count( FT_Bytes  table )
  {
    return FT_NEXT_USHORT( table );
  }


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                        FEATURES                               *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  /* uses valid->lookup_count */

  FT_LOCAL_DEF( void )
  otv_Feature_validate( FT_Bytes       table,
                        OTV_Validator  valid )
  {
    FT_Bytes  p = table;
    FT_UInt   LookupCount;


    OTV_NAME_ENTER( "Feature" );

    OTV_LIMIT_CHECK( 4 );
    p           += 2;                   /* skip FeatureParams (unused) */
    LookupCount  = FT_NEXT_USHORT( p );

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

    OTV_LIMIT_CHECK( LookupCount * 2 );

    /* LookupListIndex */
    for ( ; LookupCount > 0; LookupCount-- )
      if ( FT_NEXT_USHORT( p ) >= valid->lookup_count )
        FT_INVALID_DATA;

    OTV_EXIT;
  }


  static FT_UInt
  otv_Feature_get_count( FT_Bytes  table )
  {
    return FT_NEXT_USHORT( table );
  }


  /* sets valid->lookup_count */

  FT_LOCAL_DEF( void )
  otv_FeatureList_validate( FT_Bytes       table,
                            FT_Bytes       lookups,
                            OTV_Validator  valid )
  {
    FT_Bytes  p = table;
    FT_UInt   FeatureCount;


    OTV_NAME_ENTER( "FeatureList" );

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

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

    OTV_LIMIT_CHECK( FeatureCount * 2 );

    valid->lookup_count = otv_LookupList_get_count( lookups );

    /* FeatureRecord */
    for ( ; FeatureCount > 0; FeatureCount-- )
    {
      p += 4;       /* skip FeatureTag */

      /* Feature */
      otv_Feature_validate( table + FT_NEXT_USHORT( p ), valid );
    }

    OTV_EXIT;
  }


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                       LANGUAGE SYSTEM                         *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/


  /* uses valid->extra1 (number of features) */

  FT_LOCAL_DEF( void )
  otv_LangSys_validate( FT_Bytes       table,
                        OTV_Validator  valid )
  {
    FT_Bytes  p = table;
    FT_UInt   ReqFeatureIndex;
    FT_UInt   FeatureCount;


    OTV_NAME_ENTER( "LangSys" );

    OTV_LIMIT_CHECK( 6 );
    p              += 2;                    /* skip LookupOrder (unused) */
    ReqFeatureIndex = FT_NEXT_USHORT( p );
    FeatureCount    = FT_NEXT_USHORT( p );

    OTV_TRACE(( " (ReqFeatureIndex = %d)\n", ReqFeatureIndex ));
    OTV_TRACE(( " (FeatureCount = %d)\n",    FeatureCount    ));

    if ( ReqFeatureIndex != 0xFFFFU && ReqFeatureIndex >= valid->extra1 )
      FT_INVALID_DATA;

    OTV_LIMIT_CHECK( FeatureCount * 2 );

    /* FeatureIndex */
    for ( ; FeatureCount > 0; FeatureCount-- )
      if ( FT_NEXT_USHORT( p ) >= valid->extra1 )
        FT_INVALID_DATA;

    OTV_EXIT;
  }


  /*************************************************************************/
  /*************************************************************************/
  /*****                                                               *****/
  /*****                           SCRIPTS                             *****/
  /*****                                                               *****/
  /*************************************************************************/
  /*************************************************************************/

  FT_LOCAL_DEF( void )
  otv_Script_validate( FT_Bytes       table,
                       OTV_Validator  valid )
  {
    FT_UInt   DefaultLangSys, LangSysCount;
    FT_Bytes  p = table;


    OTV_NAME_ENTER( "Script" );

    OTV_LIMIT_CHECK( 4 );
    DefaultLangSys = FT_NEXT_USHORT( p );
    LangSysCount   = FT_NEXT_USHORT( p );

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

    if ( DefaultLangSys != 0 )
      otv_LangSys_validate( table + DefaultLangSys, valid );

    OTV_LIMIT_CHECK( LangSysCount * 6 );

    /* LangSysRecord */
    for ( ; LangSysCount > 0; LangSysCount-- )
    {
      p += 4;       /* skip LangSysTag */

      /* LangSys */
      otv_LangSys_validate( table + FT_NEXT_USHORT( p ), valid );
    }

    OTV_EXIT;
  }


  /* sets valid->extra1 (number of features) */

  FT_LOCAL_DEF( void )
  otv_ScriptList_validate( FT_Bytes       table,
                           FT_Bytes       features,
                           OTV_Validator  valid )
  {
    FT_UInt   ScriptCount;
    FT_Bytes  p = table;


    OTV_NAME_ENTER( "ScriptList" );

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

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

    OTV_LIMIT_CHECK( ScriptCount * 6 );

    valid->extra1 = otv_Feature_get_count( features );

    /* ScriptRecord */
    for ( ; ScriptCount > 0; ScriptCount-- )
    {
      p += 4;       /* skip ScriptTag */

      otv_Script_validate( table + FT_NEXT_USHORT( p ), valid ); /* Script */
    }

    OTV_EXIT;
  }


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

  /*
     u:   uint16
     ux:  unit16 [x]

     s:   struct
     sx:  struct [x]
     sxy: struct [x], using external y count

     x:   uint16 x

     C:   Coverage

     O:   Offset
     On:  Offset (NULL)
     Ox:  Offset [x]
     Onx: Offset (NULL) [x]
  */

  FT_LOCAL_DEF( void )
  otv_x_Ox( FT_Bytes       table,
            OTV_Validator  valid )
  {
    FT_Bytes           p = table;
    FT_UInt            Count;
    OTV_Validate_Func  func;


    OTV_ENTER;

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

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

    OTV_LIMIT_CHECK( Count * 2 );

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

    for ( ; Count > 0; Count-- )
      func( table + FT_NEXT_USHORT( p ), valid );

    valid->nesting_level--;

    OTV_EXIT;
  }


  FT_LOCAL_DEF( void )
  otv_u_C_x_Ox( FT_Bytes       table,
                OTV_Validator  valid )
  {
    FT_Bytes           p = table;
    FT_UInt            Count, Coverage;
    OTV_Validate_Func  func;


    OTV_ENTER;

    p += 2;     /* skip Format */

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

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

    otv_Coverage_validate( table + Coverage, valid, Count );

    OTV_LIMIT_CHECK( Count * 2 );

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

    for ( ; Count > 0; Count-- )
      func( table + FT_NEXT_USHORT( p ), valid );

    valid->nesting_level--;

    OTV_EXIT;
  }


  /* uses valid->extra1 (if > 0: array value limit) */

  FT_LOCAL_DEF( void )
  otv_x_ux( FT_Bytes       table,
            OTV_Validator  valid )
  {
    FT_Bytes  p = table;
    FT_UInt   Count;


    OTV_ENTER;

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

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

    OTV_LIMIT_CHECK( Count * 2 );

    if ( valid->extra1 )
    {
      for ( ; Count > 0; Count-- )
        if ( FT_NEXT_USHORT( p ) >= valid->extra1 )
          FT_INVALID_DATA;
    }

    OTV_EXIT;
  }


  /* `ux' in the function's name is not really correct since only x-1 */
  /* elements are tested                                              */

  /* uses valid->extra1 (array value limit) */

  FT_LOCAL_DEF( void )
  otv_x_y_ux_sy( FT_Bytes       table,
                 OTV_Validator  valid )
  {
    FT_Bytes  p = table;
    FT_UInt   Count1, Count2;


    OTV_ENTER;

    OTV_LIMIT_CHECK( 4 );
    Count1 = FT_NEXT_USHORT( p );
    Count2 = FT_NEXT_USHORT( p );

    OTV_TRACE(( " (Count1 = %d)\n", Count1 ));
    OTV_TRACE(( " (Count2 = %d)\n", Count2 ));

    if ( Count1 == 0 )
      FT_INVALID_DATA;

    OTV_LIMIT_CHECK( ( Count1 - 1 ) * 2 + Count2 * 4 );
    p += ( Count1 - 1 ) * 2;

    for ( ; Count2 > 0; Count2-- )
    {
      if ( FT_NEXT_USHORT( p ) >= Count1 )
        FT_INVALID_DATA;

      if ( FT_NEXT_USHORT( p ) >= valid->extra1 )
        FT_INVALID_DATA;
    }

    OTV_EXIT;
  }


  /* `uy' in the function's name is not really correct since only y-1 */
  /* elements are tested                                              */

  /* uses valid->extra1 (array value limit) */

  FT_LOCAL_DEF( void )
  otv_x_ux_y_uy_z_uz_p_sp( FT_Bytes       table,
                           OTV_Validator  valid )
  {
    FT_Bytes  p = table;
    FT_UInt   BacktrackCount, InputCount, LookaheadCount;
    FT_UInt   Count;


    OTV_ENTER;

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

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

    OTV_LIMIT_CHECK( BacktrackCount * 2 + 2 );
    p += BacktrackCount * 2;

    InputCount = FT_NEXT_USHORT( p );
    if ( InputCount == 0 )
      FT_INVALID_DATA;

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

    OTV_LIMIT_CHECK( InputCount * 2 );
    p += ( InputCount - 1 ) * 2;

    LookaheadCount = FT_NEXT_USHORT( p );

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

    OTV_LIMIT_CHECK( LookaheadCount * 2 + 2 );
    p += LookaheadCount * 2;

    Count = FT_NEXT_USHORT( p );

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

    OTV_LIMIT_CHECK( Count * 4 );

    for ( ; Count > 0; Count-- )
    {
      if ( FT_NEXT_USHORT( p ) >= InputCount )
        FT_INVALID_DATA;

      if ( FT_NEXT_USHORT( p ) >= valid->extra1 )
        FT_INVALID_DATA;
    }

    OTV_EXIT;
  }


  /* sets valid->extra1 (valid->lookup_count) */

  FT_LOCAL_DEF( void )
  otv_u_O_O_x_Onx( FT_Bytes       table,
                   OTV_Validator  valid )
  {
    FT_Bytes           p = table;
    FT_UInt            Coverage, ClassDef, ClassSetCount;
    OTV_Validate_Func  func;


    OTV_ENTER;

    p += 2;     /* skip Format */

    OTV_LIMIT_CHECK( 6 );
    Coverage      = FT_NEXT_USHORT( p );
    ClassDef      = FT_NEXT_USHORT( p );
    ClassSetCount = FT_NEXT_USHORT( p );

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

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

    OTV_LIMIT_CHECK( ClassSetCount * 2 );

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

    for ( ; ClassSetCount > 0; ClassSetCount-- )
    {
      FT_UInt  offset = FT_NEXT_USHORT( p );


      if ( offset )
        func( table + offset, valid );
    }

    valid->nesting_level--;

    OTV_EXIT;
  }


  /* uses valid->lookup_count */

  FT_LOCAL_DEF( void )
  otv_u_x_y_Ox_sy( FT_Bytes       table,
                   OTV_Validator  valid )
  {
    FT_Bytes  p = table;
    FT_UInt   GlyphCount, Count, count1;


    OTV_ENTER;

    p += 2;     /* skip Format */

    OTV_LIMIT_CHECK( 4 );
    GlyphCount = FT_NEXT_USHORT( p );
    Count      = FT_NEXT_USHORT( p );

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

    OTV_LIMIT_CHECK( GlyphCount * 2 + Count * 4 );

    for ( count1 = GlyphCount; count1 > 0; count1-- )
      otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );

    for ( ; Count > 0; Count-- )
    {
      if ( FT_NEXT_USHORT( p ) >= GlyphCount )
        FT_INVALID_DATA;

      if ( FT_NEXT_USHORT( p ) >= valid->lookup_count )
        FT_INVALID_DATA;
    }

    OTV_EXIT;
  }


  /* sets valid->extra1 (valid->lookup_count)    */

  FT_LOCAL_DEF( void )
  otv_u_O_O_O_O_x_Onx( FT_Bytes       table,
                       OTV_Validator  valid )
  {
    FT_Bytes           p = table;
    FT_UInt            Coverage;
    FT_UInt            BacktrackClassDef, InputClassDef, LookaheadClassDef;
    FT_UInt            ChainClassSetCount;
    OTV_Validate_Func  func;


    OTV_ENTER;

    p += 2;     /* skip Format */

    OTV_LIMIT_CHECK( 10 );
    Coverage           = FT_NEXT_USHORT( p );
    BacktrackClassDef  = FT_NEXT_USHORT( p );
    InputClassDef      = FT_NEXT_USHORT( p );
    LookaheadClassDef  = FT_NEXT_USHORT( p );
    ChainClassSetCount = FT_NEXT_USHORT( p );

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

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

    otv_ClassDef_validate( table + BacktrackClassDef,  valid );
    otv_ClassDef_validate( table + InputClassDef, valid );
    otv_ClassDef_validate( table + LookaheadClassDef, valid );

    OTV_LIMIT_CHECK( ChainClassSetCount * 2 );

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

    for ( ; ChainClassSetCount > 0; ChainClassSetCount-- )
    {
      FT_UInt  offset = FT_NEXT_USHORT( p );


      if ( offset )
        func( table + offset, valid );
    }

    valid->nesting_level--;

    OTV_EXIT;
  }


  /* uses valid->lookup_count */

  FT_LOCAL_DEF( void )
  otv_u_x_Ox_y_Oy_z_Oz_p_sp( FT_Bytes       table,
                             OTV_Validator  valid )
  {
    FT_Bytes  p = table;
    FT_UInt   BacktrackGlyphCount, InputGlyphCount, LookaheadGlyphCount;
    FT_UInt   count1, count2;


    OTV_ENTER;

    p += 2;     /* skip Format */

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

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

    OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 );

    for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- )
      otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );

    InputGlyphCount = FT_NEXT_USHORT( p );

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

    OTV_LIMIT_CHECK( InputGlyphCount * 2 + 2 );

    for ( count1 = InputGlyphCount; count1 > 0; count1-- )
      otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );

    LookaheadGlyphCount = FT_NEXT_USHORT( p );

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

    OTV_LIMIT_CHECK( LookaheadGlyphCount * 2 + 2 );

    for ( ; LookaheadGlyphCount > 0; LookaheadGlyphCount-- )
      otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );

    count2 = FT_NEXT_USHORT( p );

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

    OTV_LIMIT_CHECK( count2 * 4 );

    for ( ; count2 > 0; count2-- )
    {
      if ( FT_NEXT_USHORT( p ) >= InputGlyphCount )
        FT_INVALID_DATA;

      if ( FT_NEXT_USHORT( p ) >= valid->lookup_count )
        FT_INVALID_DATA;
    }

    OTV_EXIT;
  }


  FT_LOCAL_DEF( FT_UInt )
  otv_GSUBGPOS_get_Lookup_count( FT_Bytes  table )
  {
    FT_Bytes  p = table + 8;


    return otv_LookupList_get_count( table + FT_NEXT_USHORT( p ) );
  }


  FT_LOCAL_DEF( FT_UInt )
  otv_GSUBGPOS_have_MarkAttachmentType_flag( FT_Bytes  table )
  {
    FT_Bytes  p, lookup;
    FT_UInt   count;


    if ( !table )
      return 0;

    /* LookupList */
    p      = table + 8;
    table += FT_NEXT_USHORT( p );

    /* LookupCount */
    p     = table;
    count = FT_NEXT_USHORT( p );

    for ( ; count > 0; count-- )
    {
      FT_Bytes  oldp;


      /* Lookup */
      lookup = table + FT_NEXT_USHORT( p );

      oldp = p;

      /* LookupFlag */
      p = lookup + 2;
      if ( FT_NEXT_USHORT( p ) & 0xFF00U )
        return 1;

      p = oldp;
    }

    return 0;
  }


/* END */

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Brazil Brazil
I live in Matão, a small city in Brazil. I studied as Programmer in a College for Software Development in Database.
After finishing the College I have been working with java, c# and Computer Graphics with searches for OpenGL.

Comments and Discussions