/***************************************************************************/

/*                                                                         */

/*  otvbase.c                                                              */

/*                                                                         */

/*    OpenType BASE table validation (body).                               */

/*                                                                         */

/*  Copyright 2004, 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 "otvalid.h"

#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_otvbase





  static void

  otv_BaseCoord_validate( FT_Bytes       table,

                          OTV_Validator  valid )

  {

    FT_Bytes  p = table;

    FT_UInt   BaseCoordFormat;





    OTV_NAME_ENTER( "BaseCoord" );



    OTV_LIMIT_CHECK( 4 );

    BaseCoordFormat = FT_NEXT_USHORT( p );

    p += 2;     /* skip Coordinate */



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



    switch ( BaseCoordFormat )

    {

    case 1:     /* BaseCoordFormat1 */

      break;



    case 2:     /* BaseCoordFormat2 */

      OTV_LIMIT_CHECK( 4 );   /* ReferenceGlyph, BaseCoordPoint */

      break;



    case 3:     /* BaseCoordFormat3 */

      OTV_LIMIT_CHECK( 2 );

      /* DeviceTable */

      otv_Device_validate( table + FT_NEXT_USHORT( p ), valid );

      break;



    default:

      FT_INVALID_FORMAT;

    }



    OTV_EXIT;

  }





  static void

  otv_BaseTagList_validate( FT_Bytes       table,

                            OTV_Validator  valid )

  {

    FT_Bytes  p = table;

    FT_UInt   BaseTagCount;





    OTV_NAME_ENTER( "BaseTagList" );



    OTV_LIMIT_CHECK( 2 );



    BaseTagCount = FT_NEXT_USHORT( p );



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



    OTV_LIMIT_CHECK( BaseTagCount * 4 );          /* BaselineTag */



    OTV_EXIT;

  }





  static void

  otv_BaseValues_validate( FT_Bytes       table,

                           OTV_Validator  valid )

  {

    FT_Bytes  p = table;

    FT_UInt   BaseCoordCount;





    OTV_NAME_ENTER( "BaseValues" );



    OTV_LIMIT_CHECK( 4 );



    p             += 2;                     /* skip DefaultIndex */

    BaseCoordCount = FT_NEXT_USHORT( p );



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



    OTV_LIMIT_CHECK( BaseCoordCount * 2 );



    /* BaseCoord */

    for ( ; BaseCoordCount > 0; BaseCoordCount-- )

      otv_BaseCoord_validate( table + FT_NEXT_USHORT( p ), valid );



    OTV_EXIT;

  }





  static void

  otv_MinMax_validate( FT_Bytes       table,

                       OTV_Validator  valid )

  {

    FT_Bytes  p = table;

    FT_UInt   table_size;

    FT_UInt   FeatMinMaxCount;



    OTV_OPTIONAL_TABLE( MinCoord );

    OTV_OPTIONAL_TABLE( MaxCoord );





    OTV_NAME_ENTER( "MinMax" );



    OTV_LIMIT_CHECK( 6 );



    OTV_OPTIONAL_OFFSET( MinCoord );

    OTV_OPTIONAL_OFFSET( MaxCoord );

    FeatMinMaxCount = FT_NEXT_USHORT( p );



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



    table_size = FeatMinMaxCount * 8 + 6;



    OTV_SIZE_CHECK( MinCoord );

    if ( MinCoord )

      otv_BaseCoord_validate( table + MinCoord, valid );



    OTV_SIZE_CHECK( MaxCoord );

    if ( MaxCoord )

      otv_BaseCoord_validate( table + MaxCoord, valid );



    OTV_LIMIT_CHECK( FeatMinMaxCount * 8 );



    /* FeatMinMaxRecord */

    for ( ; FeatMinMaxCount > 0; FeatMinMaxCount-- )

    {

      p += 4;                           /* skip FeatureTableTag */



      OTV_OPTIONAL_OFFSET( MinCoord );

      OTV_OPTIONAL_OFFSET( MaxCoord );



      OTV_SIZE_CHECK( MinCoord );

      if ( MinCoord )

        otv_BaseCoord_validate( table + MinCoord, valid );



      OTV_SIZE_CHECK( MaxCoord );

      if ( MaxCoord )

        otv_BaseCoord_validate( table + MaxCoord, valid );

    }



    OTV_EXIT;

  }





  static void

  otv_BaseScript_validate( FT_Bytes       table,

                           OTV_Validator  valid )

  {

    FT_Bytes  p = table;

    FT_UInt   table_size;

    FT_UInt   BaseLangSysCount;



    OTV_OPTIONAL_TABLE( BaseValues    );

    OTV_OPTIONAL_TABLE( DefaultMinMax );





    OTV_NAME_ENTER( "BaseScript" );



    OTV_LIMIT_CHECK( 6 );

    OTV_OPTIONAL_OFFSET( BaseValues    );

    OTV_OPTIONAL_OFFSET( DefaultMinMax );

    BaseLangSysCount = FT_NEXT_USHORT( p );



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



    table_size = BaseLangSysCount * 6 + 6;



    OTV_SIZE_CHECK( BaseValues );

    if ( BaseValues )

      otv_BaseValues_validate( table + BaseValues, valid );



    OTV_SIZE_CHECK( DefaultMinMax );

    if ( DefaultMinMax )

      otv_MinMax_validate( table + DefaultMinMax, valid );



    OTV_LIMIT_CHECK( BaseLangSysCount * 6 );



    /* BaseLangSysRecord */

    for ( ; BaseLangSysCount > 0; BaseLangSysCount-- )

    {

      p += 4;       /* skip BaseLangSysTag */



      otv_MinMax_validate( table + FT_NEXT_USHORT( p ), valid );

    }



    OTV_EXIT;

  }





  static void

  otv_BaseScriptList_validate( FT_Bytes       table,

                               OTV_Validator  valid )

  {

    FT_Bytes  p = table;

    FT_UInt   BaseScriptCount;





    OTV_NAME_ENTER( "BaseScriptList" );



    OTV_LIMIT_CHECK( 2 );

    BaseScriptCount = FT_NEXT_USHORT( p );



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



    OTV_LIMIT_CHECK( BaseScriptCount * 6 );



    /* BaseScriptRecord */

    for ( ; BaseScriptCount > 0; BaseScriptCount-- )

    {

      p += 4;       /* skip BaseScriptTag */



      /* BaseScript */

      otv_BaseScript_validate( table + FT_NEXT_USHORT( p ), valid );

    }



    OTV_EXIT;

  }





  static void

  otv_Axis_validate( FT_Bytes       table,

                     OTV_Validator  valid )

  {

    FT_Bytes  p = table;

    FT_UInt   table_size;



    OTV_OPTIONAL_TABLE( BaseTagList );





    OTV_NAME_ENTER( "Axis" );



    OTV_LIMIT_CHECK( 4 );

    OTV_OPTIONAL_OFFSET( BaseTagList );



    table_size = 4;



    OTV_SIZE_CHECK( BaseTagList );

    if ( BaseTagList )

      otv_BaseTagList_validate( table + BaseTagList, valid );



    /* BaseScriptList */

    otv_BaseScriptList_validate( table + FT_NEXT_USHORT( p ), valid );



    OTV_EXIT;

  }





  FT_LOCAL_DEF( void )

  otv_BASE_validate( FT_Bytes      table,

                     FT_Validator  ftvalid )

  {

    OTV_ValidatorRec  validrec;

    OTV_Validator     valid = &validrec;

    FT_Bytes          p     = table;

    FT_UInt           table_size;



    OTV_OPTIONAL_TABLE( HorizAxis );

    OTV_OPTIONAL_TABLE( VertAxis  );





    valid->root = ftvalid;



    FT_TRACE3(( "validating BASE table\n" ));

    OTV_INIT;



    OTV_LIMIT_CHECK( 6 );



    if ( FT_NEXT_ULONG( p ) != 0x10000UL )      /* Version */

      FT_INVALID_FORMAT;



    table_size = 6;



    OTV_OPTIONAL_OFFSET( HorizAxis );

    OTV_SIZE_CHECK( HorizAxis );

    if ( HorizAxis )

      otv_Axis_validate( table + HorizAxis, valid );



    OTV_OPTIONAL_OFFSET( VertAxis );

    OTV_SIZE_CHECK( VertAxis );

    if ( VertAxis )

      otv_Axis_validate( table + VertAxis, valid );



    FT_TRACE4(( "\n" ));

  }





/* END */

