PageRenderTime 40ms CodeModel.GetById 2ms app.highlight 32ms RepoModel.GetById 1ms app.codeStats 0ms

/src/freetype/src/otvalid/otvgpos.c

https://bitbucket.org/cabalistic/ogredeps/
C | 1017 lines | 577 code | 274 blank | 166 comment | 41 complexity | bb615ee5584185d24b3a7f7487bb91db MD5 | raw file
   1/***************************************************************************/
   2/*                                                                         */
   3/*  otvgpos.c                                                              */
   4/*                                                                         */
   5/*    OpenType GPOS table validation (body).                               */
   6/*                                                                         */
   7/*  Copyright 2002, 2004, 2005, 2006, 2007, 2008 by                        */
   8/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
   9/*                                                                         */
  10/*  This file is part of the FreeType project, and may only be used,       */
  11/*  modified, and distributed under the terms of the FreeType project      */
  12/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
  13/*  this file you indicate that you have read the license and              */
  14/*  understand and accept it fully.                                        */
  15/*                                                                         */
  16/***************************************************************************/
  17
  18
  19#include "otvalid.h"
  20#include "otvcommn.h"
  21#include "otvgpos.h"
  22
  23
  24  /*************************************************************************/
  25  /*                                                                       */
  26  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  27  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  28  /* messages during execution.                                            */
  29  /*                                                                       */
  30#undef  FT_COMPONENT
  31#define FT_COMPONENT  trace_otvgpos
  32
  33
  34  static void
  35  otv_Anchor_validate( FT_Bytes       table,
  36                       OTV_Validator  valid );
  37
  38  static void
  39  otv_MarkArray_validate( FT_Bytes       table,
  40                          OTV_Validator  valid );
  41
  42
  43  /*************************************************************************/
  44  /*************************************************************************/
  45  /*****                                                               *****/
  46  /*****                      UTILITY FUNCTIONS                        *****/
  47  /*****                                                               *****/
  48  /*************************************************************************/
  49  /*************************************************************************/
  50
  51#define BaseArrayFunc       otv_x_sxy
  52#define LigatureAttachFunc  otv_x_sxy
  53#define Mark2ArrayFunc      otv_x_sxy
  54
  55  /* uses valid->extra1 (counter)                             */
  56  /* uses valid->extra2 (boolean to handle NULL anchor field) */
  57
  58  static void
  59  otv_x_sxy( FT_Bytes       table,
  60             OTV_Validator  valid )
  61  {
  62    FT_Bytes  p = table;
  63    FT_UInt   Count, count1, table_size;
  64
  65
  66    OTV_ENTER;
  67
  68    OTV_LIMIT_CHECK( 2 );
  69
  70    Count = FT_NEXT_USHORT( p );
  71
  72    OTV_TRACE(( " (Count = %d)\n", Count ));
  73
  74    OTV_LIMIT_CHECK( Count * valid->extra1 * 2 );
  75
  76    table_size = Count * valid->extra1 * 2 + 2;
  77
  78    for ( ; Count > 0; Count-- )
  79      for ( count1 = valid->extra1; count1 > 0; count1-- )
  80      {
  81        OTV_OPTIONAL_TABLE( anchor_offset );
  82
  83
  84        OTV_OPTIONAL_OFFSET( anchor_offset );
  85
  86        if ( valid->extra2 )
  87        {
  88          OTV_SIZE_CHECK( anchor_offset );
  89          if ( anchor_offset )
  90            otv_Anchor_validate( table + anchor_offset, valid );
  91        }
  92        else
  93          otv_Anchor_validate( table + anchor_offset, valid );
  94      }
  95
  96    OTV_EXIT;
  97  }
  98
  99
 100#define MarkBasePosFormat1Func  otv_u_O_O_u_O_O
 101#define MarkLigPosFormat1Func   otv_u_O_O_u_O_O
 102#define MarkMarkPosFormat1Func  otv_u_O_O_u_O_O
 103
 104  /* sets valid->extra1 (class count) */
 105
 106  static void
 107  otv_u_O_O_u_O_O( FT_Bytes       table,
 108                   OTV_Validator  valid )
 109  {
 110    FT_Bytes           p = table;
 111    FT_UInt            Coverage1, Coverage2, ClassCount;
 112    FT_UInt            Array1, Array2;
 113    OTV_Validate_Func  func;
 114
 115
 116    OTV_ENTER;
 117
 118    p += 2;     /* skip PosFormat */
 119
 120    OTV_LIMIT_CHECK( 10 );
 121    Coverage1  = FT_NEXT_USHORT( p );
 122    Coverage2  = FT_NEXT_USHORT( p );
 123    ClassCount = FT_NEXT_USHORT( p );
 124    Array1     = FT_NEXT_USHORT( p );
 125    Array2     = FT_NEXT_USHORT( p );
 126
 127    otv_Coverage_validate( table + Coverage1, valid, -1 );
 128    otv_Coverage_validate( table + Coverage2, valid, -1 );
 129
 130    otv_MarkArray_validate( table + Array1, valid );
 131
 132    valid->nesting_level++;
 133    func          = valid->func[valid->nesting_level];
 134    valid->extra1 = ClassCount;
 135
 136    func( table + Array2, valid );
 137
 138    valid->nesting_level--;
 139
 140    OTV_EXIT;
 141  }
 142
 143
 144  /*************************************************************************/
 145  /*************************************************************************/
 146  /*****                                                               *****/
 147  /*****                        VALUE RECORDS                          *****/
 148  /*****                                                               *****/
 149  /*************************************************************************/
 150  /*************************************************************************/
 151
 152  static FT_UInt
 153  otv_value_length( FT_UInt  format )
 154  {
 155    FT_UInt  count;
 156
 157
 158    count = ( ( format & 0xAA ) >> 1 ) + ( format & 0x55 );
 159    count = ( ( count  & 0xCC ) >> 2 ) + ( count  & 0x33 );
 160    count = ( ( count  & 0xF0 ) >> 4 ) + ( count  & 0x0F );
 161
 162    return count * 2;
 163  }
 164
 165
 166  /* uses valid->extra3 (pointer to base table) */
 167
 168  static void
 169  otv_ValueRecord_validate( FT_Bytes       table,
 170                            FT_UInt        format,
 171                            OTV_Validator  valid )
 172  {
 173    FT_Bytes  p = table;
 174    FT_UInt   count;
 175
 176#ifdef FT_DEBUG_LEVEL_TRACE
 177    FT_Int    loop;
 178    FT_ULong  res = 0;
 179
 180
 181    OTV_NAME_ENTER( "ValueRecord" );
 182
 183    /* display `format' in dual representation */
 184    for ( loop = 7; loop >= 0; loop-- )
 185    {
 186      res <<= 4;
 187      res  += ( format >> loop ) & 1;
 188    }
 189
 190    OTV_TRACE(( " (format 0b%08lx)\n", res ));
 191#endif
 192
 193    if ( format >= 0x100 )
 194      FT_INVALID_FORMAT;
 195
 196    for ( count = 4; count > 0; count-- )
 197    {
 198      if ( format & 1 )
 199      {
 200        /* XPlacement, YPlacement, XAdvance, YAdvance */
 201        OTV_LIMIT_CHECK( 2 );
 202        p += 2;
 203      }
 204
 205      format >>= 1;
 206    }
 207
 208    for ( count = 4; count > 0; count-- )
 209    {
 210      if ( format & 1 )
 211      {
 212        FT_PtrDist  table_size;
 213
 214        OTV_OPTIONAL_TABLE( device );
 215
 216
 217        /* XPlaDevice, YPlaDevice, XAdvDevice, YAdvDevice */
 218        OTV_LIMIT_CHECK( 2 );
 219        OTV_OPTIONAL_OFFSET( device );
 220
 221        /* XXX: this value is usually too small, especially if the current */
 222        /* ValueRecord is part of an array -- getting the correct table    */
 223        /* size is probably not worth the trouble                          */
 224
 225        table_size = p - valid->extra3;
 226
 227        OTV_SIZE_CHECK( device );
 228        if ( device )
 229          otv_Device_validate( valid->extra3 + device, valid );
 230      }
 231      format >>= 1;
 232    }
 233
 234    OTV_EXIT;
 235  }
 236
 237
 238  /*************************************************************************/
 239  /*************************************************************************/
 240  /*****                                                               *****/
 241  /*****                           ANCHORS                             *****/
 242  /*****                                                               *****/
 243  /*************************************************************************/
 244  /*************************************************************************/
 245
 246  static void
 247  otv_Anchor_validate( FT_Bytes       table,
 248                       OTV_Validator  valid )
 249  {
 250    FT_Bytes  p = table;
 251    FT_UInt   AnchorFormat;
 252
 253
 254    OTV_NAME_ENTER( "Anchor");
 255
 256    OTV_LIMIT_CHECK( 6 );
 257    AnchorFormat = FT_NEXT_USHORT( p );
 258
 259    OTV_TRACE(( " (format %d)\n", AnchorFormat ));
 260
 261    p += 4;     /* skip XCoordinate and YCoordinate */
 262
 263    switch ( AnchorFormat )
 264    {
 265    case 1:
 266      break;
 267
 268    case 2:
 269      OTV_LIMIT_CHECK( 2 );  /* AnchorPoint */
 270      break;
 271
 272    case 3:
 273      {
 274        FT_UInt   table_size;
 275
 276        OTV_OPTIONAL_TABLE( XDeviceTable );
 277        OTV_OPTIONAL_TABLE( YDeviceTable );
 278
 279
 280        OTV_LIMIT_CHECK( 4 );
 281        OTV_OPTIONAL_OFFSET( XDeviceTable );
 282        OTV_OPTIONAL_OFFSET( YDeviceTable );
 283
 284        table_size = 6 + 4;
 285
 286        OTV_SIZE_CHECK( XDeviceTable );
 287        if ( XDeviceTable )
 288          otv_Device_validate( table + XDeviceTable, valid );
 289
 290        OTV_SIZE_CHECK( YDeviceTable );
 291        if ( YDeviceTable )
 292          otv_Device_validate( table + YDeviceTable, valid );
 293      }
 294      break;
 295
 296    default:
 297      FT_INVALID_FORMAT;
 298    }
 299
 300    OTV_EXIT;
 301  }
 302
 303
 304  /*************************************************************************/
 305  /*************************************************************************/
 306  /*****                                                               *****/
 307  /*****                         MARK ARRAYS                           *****/
 308  /*****                                                               *****/
 309  /*************************************************************************/
 310  /*************************************************************************/
 311
 312  static void
 313  otv_MarkArray_validate( FT_Bytes       table,
 314                          OTV_Validator  valid )
 315  {
 316    FT_Bytes  p = table;
 317    FT_UInt   MarkCount;
 318
 319
 320    OTV_NAME_ENTER( "MarkArray" );
 321
 322    OTV_LIMIT_CHECK( 2 );
 323    MarkCount = FT_NEXT_USHORT( p );
 324
 325    OTV_TRACE(( " (MarkCount = %d)\n", MarkCount ));
 326
 327    OTV_LIMIT_CHECK( MarkCount * 4 );
 328
 329    /* MarkRecord */
 330    for ( ; MarkCount > 0; MarkCount-- )
 331    {
 332      p += 2;   /* skip Class */
 333      /* MarkAnchor */
 334      otv_Anchor_validate( table + FT_NEXT_USHORT( p ), valid );
 335    }
 336
 337    OTV_EXIT;
 338  }
 339
 340
 341  /*************************************************************************/
 342  /*************************************************************************/
 343  /*****                                                               *****/
 344  /*****                     GPOS LOOKUP TYPE 1                        *****/
 345  /*****                                                               *****/
 346  /*************************************************************************/
 347  /*************************************************************************/
 348
 349  /* sets valid->extra3 (pointer to base table) */
 350
 351  static void
 352  otv_SinglePos_validate( FT_Bytes       table,
 353                          OTV_Validator  valid )
 354  {
 355    FT_Bytes  p = table;
 356    FT_UInt   PosFormat;
 357
 358
 359    OTV_NAME_ENTER( "SinglePos" );
 360
 361    OTV_LIMIT_CHECK( 2 );
 362    PosFormat = FT_NEXT_USHORT( p );
 363
 364    OTV_TRACE(( " (format %d)\n", PosFormat ));
 365
 366    valid->extra3 = table;
 367
 368    switch ( PosFormat )
 369    {
 370    case 1:     /* SinglePosFormat1 */
 371      {
 372        FT_UInt  Coverage, ValueFormat;
 373
 374
 375        OTV_LIMIT_CHECK( 4 );
 376        Coverage    = FT_NEXT_USHORT( p );
 377        ValueFormat = FT_NEXT_USHORT( p );
 378
 379        otv_Coverage_validate( table + Coverage, valid, -1 );
 380        otv_ValueRecord_validate( p, ValueFormat, valid ); /* Value */
 381      }
 382      break;
 383
 384    case 2:     /* SinglePosFormat2 */
 385      {
 386        FT_UInt  Coverage, ValueFormat, ValueCount, len_value;
 387
 388
 389        OTV_LIMIT_CHECK( 6 );
 390        Coverage    = FT_NEXT_USHORT( p );
 391        ValueFormat = FT_NEXT_USHORT( p );
 392        ValueCount  = FT_NEXT_USHORT( p );
 393
 394        OTV_TRACE(( " (ValueCount = %d)\n", ValueCount ));
 395
 396        len_value = otv_value_length( ValueFormat );
 397
 398        otv_Coverage_validate( table + Coverage, valid, ValueCount );
 399
 400        OTV_LIMIT_CHECK( ValueCount * len_value );
 401
 402        /* Value */
 403        for ( ; ValueCount > 0; ValueCount-- )
 404        {
 405          otv_ValueRecord_validate( p, ValueFormat, valid );
 406          p += len_value;
 407        }
 408      }
 409      break;
 410
 411    default:
 412      FT_INVALID_FORMAT;
 413    }
 414
 415    OTV_EXIT;
 416  }
 417
 418
 419  /*************************************************************************/
 420  /*************************************************************************/
 421  /*****                                                               *****/
 422  /*****                     GPOS LOOKUP TYPE 2                        *****/
 423  /*****                                                               *****/
 424  /*************************************************************************/
 425  /*************************************************************************/
 426
 427  static void
 428  otv_PairSet_validate( FT_Bytes       table,
 429                        FT_UInt        format1,
 430                        FT_UInt        format2,
 431                        OTV_Validator  valid )
 432  {
 433    FT_Bytes  p = table;
 434    FT_UInt   value_len1, value_len2, PairValueCount;
 435
 436
 437    OTV_NAME_ENTER( "PairSet" );
 438
 439    OTV_LIMIT_CHECK( 2 );
 440    PairValueCount = FT_NEXT_USHORT( p );
 441
 442    OTV_TRACE(( " (PairValueCount = %d)\n", PairValueCount ));
 443
 444    value_len1 = otv_value_length( format1 );
 445    value_len2 = otv_value_length( format2 );
 446
 447    OTV_LIMIT_CHECK( PairValueCount * ( value_len1 + value_len2 + 2 ) );
 448
 449    /* PairValueRecord */
 450    for ( ; PairValueCount > 0; PairValueCount-- )
 451    {
 452      p += 2;       /* skip SecondGlyph */
 453
 454      if ( format1 )
 455        otv_ValueRecord_validate( p, format1, valid ); /* Value1 */
 456      p += value_len1;
 457
 458      if ( format2 )
 459        otv_ValueRecord_validate( p, format2, valid ); /* Value2 */
 460      p += value_len2;
 461    }
 462
 463    OTV_EXIT;
 464  }
 465
 466
 467  /* sets valid->extra3 (pointer to base table) */
 468
 469  static void
 470  otv_PairPos_validate( FT_Bytes       table,
 471                        OTV_Validator  valid )
 472  {
 473    FT_Bytes  p = table;
 474    FT_UInt   PosFormat;
 475
 476
 477    OTV_NAME_ENTER( "PairPos" );
 478
 479    OTV_LIMIT_CHECK( 2 );
 480    PosFormat = FT_NEXT_USHORT( p );
 481
 482    OTV_TRACE(( " (format %d)\n", PosFormat ));
 483
 484    valid->extra3 = table;
 485
 486    switch ( PosFormat )
 487    {
 488    case 1:     /* PairPosFormat1 */
 489      {
 490        FT_UInt  Coverage, ValueFormat1, ValueFormat2, PairSetCount;
 491
 492
 493        OTV_LIMIT_CHECK( 8 );
 494        Coverage     = FT_NEXT_USHORT( p );
 495        ValueFormat1 = FT_NEXT_USHORT( p );
 496        ValueFormat2 = FT_NEXT_USHORT( p );
 497        PairSetCount = FT_NEXT_USHORT( p );
 498
 499        OTV_TRACE(( " (PairSetCount = %d)\n", PairSetCount ));
 500
 501        otv_Coverage_validate( table + Coverage, valid, -1 );
 502
 503        OTV_LIMIT_CHECK( PairSetCount * 2 );
 504
 505        /* PairSetOffset */
 506        for ( ; PairSetCount > 0; PairSetCount-- )
 507          otv_PairSet_validate( table + FT_NEXT_USHORT( p ),
 508                                ValueFormat1, ValueFormat2, valid );
 509      }
 510      break;
 511
 512    case 2:     /* PairPosFormat2 */
 513      {
 514        FT_UInt  Coverage, ValueFormat1, ValueFormat2, ClassDef1, ClassDef2;
 515        FT_UInt  ClassCount1, ClassCount2, len_value1, len_value2, count;
 516
 517
 518        OTV_LIMIT_CHECK( 14 );
 519        Coverage     = FT_NEXT_USHORT( p );
 520        ValueFormat1 = FT_NEXT_USHORT( p );
 521        ValueFormat2 = FT_NEXT_USHORT( p );
 522        ClassDef1    = FT_NEXT_USHORT( p );
 523        ClassDef2    = FT_NEXT_USHORT( p );
 524        ClassCount1  = FT_NEXT_USHORT( p );
 525        ClassCount2  = FT_NEXT_USHORT( p );
 526
 527        OTV_TRACE(( " (ClassCount1 = %d)\n", ClassCount1 ));
 528        OTV_TRACE(( " (ClassCount2 = %d)\n", ClassCount2 ));
 529
 530        len_value1 = otv_value_length( ValueFormat1 );
 531        len_value2 = otv_value_length( ValueFormat2 );
 532
 533        otv_Coverage_validate( table + Coverage, valid, -1 );
 534        otv_ClassDef_validate( table + ClassDef1, valid );
 535        otv_ClassDef_validate( table + ClassDef2, valid );
 536
 537        OTV_LIMIT_CHECK( ClassCount1 * ClassCount2 *
 538                     ( len_value1 + len_value2 ) );
 539
 540        /* Class1Record */
 541        for ( ; ClassCount1 > 0; ClassCount1-- )
 542        {
 543          /* Class2Record */
 544          for ( count = ClassCount2; count > 0; count-- )
 545          {
 546            if ( ValueFormat1 )
 547              /* Value1 */
 548              otv_ValueRecord_validate( p, ValueFormat1, valid );
 549            p += len_value1;
 550
 551            if ( ValueFormat2 )
 552              /* Value2 */
 553              otv_ValueRecord_validate( p, ValueFormat2, valid );
 554            p += len_value2;
 555          }
 556        }
 557      }
 558      break;
 559
 560    default:
 561      FT_INVALID_FORMAT;
 562    }
 563
 564    OTV_EXIT;
 565  }
 566
 567
 568  /*************************************************************************/
 569  /*************************************************************************/
 570  /*****                                                               *****/
 571  /*****                     GPOS LOOKUP TYPE 3                        *****/
 572  /*****                                                               *****/
 573  /*************************************************************************/
 574  /*************************************************************************/
 575
 576  static void
 577  otv_CursivePos_validate( FT_Bytes       table,
 578                           OTV_Validator  valid )
 579  {
 580    FT_Bytes  p = table;
 581    FT_UInt   PosFormat;
 582
 583
 584    OTV_NAME_ENTER( "CursivePos" );
 585
 586    OTV_LIMIT_CHECK( 2 );
 587    PosFormat = FT_NEXT_USHORT( p );
 588
 589    OTV_TRACE(( " (format %d)\n", PosFormat ));
 590
 591    switch ( PosFormat )
 592    {
 593    case 1:     /* CursivePosFormat1 */
 594      {
 595        FT_UInt   table_size;
 596        FT_UInt   Coverage, EntryExitCount;
 597
 598        OTV_OPTIONAL_TABLE( EntryAnchor );
 599        OTV_OPTIONAL_TABLE( ExitAnchor  );
 600
 601
 602        OTV_LIMIT_CHECK( 4 );
 603        Coverage       = FT_NEXT_USHORT( p );
 604        EntryExitCount = FT_NEXT_USHORT( p );
 605
 606        OTV_TRACE(( " (EntryExitCount = %d)\n", EntryExitCount ));
 607
 608        otv_Coverage_validate( table + Coverage, valid, EntryExitCount );
 609
 610        OTV_LIMIT_CHECK( EntryExitCount * 4 );
 611
 612        table_size = EntryExitCount * 4 + 4;
 613
 614        /* EntryExitRecord */
 615        for ( ; EntryExitCount > 0; EntryExitCount-- )
 616        {
 617          OTV_OPTIONAL_OFFSET( EntryAnchor );
 618          OTV_OPTIONAL_OFFSET( ExitAnchor  );
 619
 620          OTV_SIZE_CHECK( EntryAnchor );
 621          if ( EntryAnchor )
 622            otv_Anchor_validate( table + EntryAnchor, valid );
 623
 624          OTV_SIZE_CHECK( ExitAnchor );
 625          if ( ExitAnchor )
 626            otv_Anchor_validate( table + ExitAnchor, valid );
 627        }
 628      }
 629      break;
 630
 631    default:
 632      FT_INVALID_FORMAT;
 633    }
 634
 635    OTV_EXIT;
 636  }
 637
 638
 639  /*************************************************************************/
 640  /*************************************************************************/
 641  /*****                                                               *****/
 642  /*****                     GPOS LOOKUP TYPE 4                        *****/
 643  /*****                                                               *****/
 644  /*************************************************************************/
 645  /*************************************************************************/
 646
 647  /* UNDOCUMENTED (in OpenType 1.5):              */
 648  /* BaseRecord tables can contain NULL pointers. */
 649
 650  /* sets valid->extra2 (1) */
 651
 652  static void
 653  otv_MarkBasePos_validate( FT_Bytes       table,
 654                            OTV_Validator  valid )
 655  {
 656    FT_Bytes  p = table;
 657    FT_UInt   PosFormat;
 658
 659
 660    OTV_NAME_ENTER( "MarkBasePos" );
 661
 662    OTV_LIMIT_CHECK( 2 );
 663    PosFormat = FT_NEXT_USHORT( p );
 664
 665    OTV_TRACE(( " (format %d)\n", PosFormat ));
 666
 667    switch ( PosFormat )
 668    {
 669    case 1:
 670      valid->extra2 = 1;
 671      OTV_NEST2( MarkBasePosFormat1, BaseArray );
 672      OTV_RUN( table, valid );
 673      break;
 674
 675    default:
 676      FT_INVALID_FORMAT;
 677    }
 678
 679    OTV_EXIT;
 680  }
 681
 682
 683  /*************************************************************************/
 684  /*************************************************************************/
 685  /*****                                                               *****/
 686  /*****                     GPOS LOOKUP TYPE 5                        *****/
 687  /*****                                                               *****/
 688  /*************************************************************************/
 689  /*************************************************************************/
 690
 691  /* sets valid->extra2 (1) */
 692
 693  static void
 694  otv_MarkLigPos_validate( FT_Bytes       table,
 695                           OTV_Validator  valid )
 696  {
 697    FT_Bytes  p = table;
 698    FT_UInt   PosFormat;
 699
 700
 701    OTV_NAME_ENTER( "MarkLigPos" );
 702
 703    OTV_LIMIT_CHECK( 2 );
 704    PosFormat = FT_NEXT_USHORT( p );
 705
 706    OTV_TRACE(( " (format %d)\n", PosFormat ));
 707
 708    switch ( PosFormat )
 709    {
 710    case 1:
 711      valid->extra2 = 1;
 712      OTV_NEST3( MarkLigPosFormat1, LigatureArray, LigatureAttach );
 713      OTV_RUN( table, valid );
 714      break;
 715
 716    default:
 717      FT_INVALID_FORMAT;
 718    }
 719
 720    OTV_EXIT;
 721  }
 722
 723
 724  /*************************************************************************/
 725  /*************************************************************************/
 726  /*****                                                               *****/
 727  /*****                     GPOS LOOKUP TYPE 6                        *****/
 728  /*****                                                               *****/
 729  /*************************************************************************/
 730  /*************************************************************************/
 731
 732  /* sets valid->extra2 (0) */
 733
 734  static void
 735  otv_MarkMarkPos_validate( FT_Bytes       table,
 736                            OTV_Validator  valid )
 737  {
 738    FT_Bytes  p = table;
 739    FT_UInt   PosFormat;
 740
 741
 742    OTV_NAME_ENTER( "MarkMarkPos" );
 743
 744    OTV_LIMIT_CHECK( 2 );
 745    PosFormat = FT_NEXT_USHORT( p );
 746
 747    OTV_TRACE(( " (format %d)\n", PosFormat ));
 748
 749    switch ( PosFormat )
 750    {
 751    case 1:
 752      valid->extra2 = 0;
 753      OTV_NEST2( MarkMarkPosFormat1, Mark2Array );
 754      OTV_RUN( table, valid );
 755      break;
 756
 757    default:
 758      FT_INVALID_FORMAT;
 759    }
 760
 761    OTV_EXIT;
 762  }
 763
 764
 765  /*************************************************************************/
 766  /*************************************************************************/
 767  /*****                                                               *****/
 768  /*****                     GPOS LOOKUP TYPE 7                        *****/
 769  /*****                                                               *****/
 770  /*************************************************************************/
 771  /*************************************************************************/
 772
 773  /* sets valid->extra1 (lookup count) */
 774
 775  static void
 776  otv_ContextPos_validate( FT_Bytes       table,
 777                           OTV_Validator  valid )
 778  {
 779    FT_Bytes  p = table;
 780    FT_UInt   PosFormat;
 781
 782
 783    OTV_NAME_ENTER( "ContextPos" );
 784
 785    OTV_LIMIT_CHECK( 2 );
 786    PosFormat = FT_NEXT_USHORT( p );
 787
 788    OTV_TRACE(( " (format %d)\n", PosFormat ));
 789
 790    switch ( PosFormat )
 791    {
 792    case 1:
 793      /* no need to check glyph indices/classes used as input for these */
 794      /* context rules since even invalid glyph indices/classes return  */
 795      /* meaningful results                                             */
 796
 797      valid->extra1 = valid->lookup_count;
 798      OTV_NEST3( ContextPosFormat1, PosRuleSet, PosRule );
 799      OTV_RUN( table, valid );
 800      break;
 801
 802    case 2:
 803      /* no need to check glyph indices/classes used as input for these */
 804      /* context rules since even invalid glyph indices/classes return  */
 805      /* meaningful results                                             */
 806
 807      OTV_NEST3( ContextPosFormat2, PosClassSet, PosClassRule );
 808      OTV_RUN( table, valid );
 809      break;
 810
 811    case 3:
 812      OTV_NEST1( ContextPosFormat3 );
 813      OTV_RUN( table, valid );
 814      break;
 815
 816    default:
 817      FT_INVALID_FORMAT;
 818    }
 819
 820    OTV_EXIT;
 821  }
 822
 823
 824  /*************************************************************************/
 825  /*************************************************************************/
 826  /*****                                                               *****/
 827  /*****                     GPOS LOOKUP TYPE 8                        *****/
 828  /*****                                                               *****/
 829  /*************************************************************************/
 830  /*************************************************************************/
 831
 832  /* sets valid->extra1 (lookup count) */
 833
 834  static void
 835  otv_ChainContextPos_validate( FT_Bytes       table,
 836                                OTV_Validator  valid )
 837  {
 838    FT_Bytes  p = table;
 839    FT_UInt   PosFormat;
 840
 841
 842    OTV_NAME_ENTER( "ChainContextPos" );
 843
 844    OTV_LIMIT_CHECK( 2 );
 845    PosFormat = FT_NEXT_USHORT( p );
 846
 847    OTV_TRACE(( " (format %d)\n", PosFormat ));
 848
 849    switch ( PosFormat )
 850    {
 851    case 1:
 852      /* no need to check glyph indices/classes used as input for these */
 853      /* context rules since even invalid glyph indices/classes return  */
 854      /* meaningful results                                             */
 855
 856      valid->extra1 = valid->lookup_count;
 857      OTV_NEST3( ChainContextPosFormat1,
 858                 ChainPosRuleSet, ChainPosRule );
 859      OTV_RUN( table, valid );
 860      break;
 861
 862    case 2:
 863      /* no need to check glyph indices/classes used as input for these */
 864      /* context rules since even invalid glyph indices/classes return  */
 865      /* meaningful results                                             */
 866
 867      OTV_NEST3( ChainContextPosFormat2,
 868                 ChainPosClassSet, ChainPosClassRule );
 869      OTV_RUN( table, valid );
 870      break;
 871
 872    case 3:
 873      OTV_NEST1( ChainContextPosFormat3 );
 874      OTV_RUN( table, valid );
 875      break;
 876
 877    default:
 878      FT_INVALID_FORMAT;
 879    }
 880
 881    OTV_EXIT;
 882  }
 883
 884
 885  /*************************************************************************/
 886  /*************************************************************************/
 887  /*****                                                               *****/
 888  /*****                     GPOS LOOKUP TYPE 9                        *****/
 889  /*****                                                               *****/
 890  /*************************************************************************/
 891  /*************************************************************************/
 892
 893  /* uses valid->type_funcs */
 894
 895  static void
 896  otv_ExtensionPos_validate( FT_Bytes       table,
 897                             OTV_Validator  valid )
 898  {
 899    FT_Bytes  p = table;
 900    FT_UInt   PosFormat;
 901
 902
 903    OTV_NAME_ENTER( "ExtensionPos" );
 904
 905    OTV_LIMIT_CHECK( 2 );
 906    PosFormat = FT_NEXT_USHORT( p );
 907
 908    OTV_TRACE(( " (format %d)\n", PosFormat ));
 909
 910    switch ( PosFormat )
 911    {
 912    case 1:     /* ExtensionPosFormat1 */
 913      {
 914        FT_UInt            ExtensionLookupType;
 915        FT_ULong           ExtensionOffset;
 916        OTV_Validate_Func  validate;
 917
 918
 919        OTV_LIMIT_CHECK( 6 );
 920        ExtensionLookupType = FT_NEXT_USHORT( p );
 921        ExtensionOffset     = FT_NEXT_ULONG( p );
 922
 923        if ( ExtensionLookupType == 0 || ExtensionLookupType >= 9 )
 924          FT_INVALID_DATA;
 925
 926        validate = valid->type_funcs[ExtensionLookupType - 1];
 927        validate( table + ExtensionOffset, valid );
 928      }
 929      break;
 930
 931    default:
 932      FT_INVALID_FORMAT;
 933    }
 934
 935    OTV_EXIT;
 936  }
 937
 938
 939  static const OTV_Validate_Func  otv_gpos_validate_funcs[9] =
 940  {
 941    otv_SinglePos_validate,
 942    otv_PairPos_validate,
 943    otv_CursivePos_validate,
 944    otv_MarkBasePos_validate,
 945    otv_MarkLigPos_validate,
 946    otv_MarkMarkPos_validate,
 947    otv_ContextPos_validate,
 948    otv_ChainContextPos_validate,
 949    otv_ExtensionPos_validate
 950  };
 951
 952
 953  /* sets valid->type_count */
 954  /* sets valid->type_funcs */
 955
 956  FT_LOCAL_DEF( void )
 957  otv_GPOS_subtable_validate( FT_Bytes       table,
 958                              OTV_Validator  valid )
 959  {
 960    valid->type_count = 9;
 961    valid->type_funcs = (OTV_Validate_Func*)otv_gpos_validate_funcs;
 962
 963    otv_Lookup_validate( table, valid );
 964  }
 965
 966
 967  /*************************************************************************/
 968  /*************************************************************************/
 969  /*****                                                               *****/
 970  /*****                          GPOS TABLE                           *****/
 971  /*****                                                               *****/
 972  /*************************************************************************/
 973  /*************************************************************************/
 974
 975  /* sets valid->glyph_count */
 976
 977  FT_LOCAL_DEF( void )
 978  otv_GPOS_validate( FT_Bytes      table,
 979                     FT_UInt       glyph_count,
 980                     FT_Validator  ftvalid )
 981  {
 982    OTV_ValidatorRec  validrec;
 983    OTV_Validator     valid = &validrec;
 984    FT_Bytes          p     = table;
 985    FT_UInt           ScriptList, FeatureList, LookupList;
 986
 987
 988    valid->root = ftvalid;
 989
 990    FT_TRACE3(( "validating GPOS table\n" ));
 991    OTV_INIT;
 992
 993    OTV_LIMIT_CHECK( 10 );
 994
 995    if ( FT_NEXT_ULONG( p ) != 0x10000UL )      /* Version */
 996      FT_INVALID_FORMAT;
 997
 998    ScriptList  = FT_NEXT_USHORT( p );
 999    FeatureList = FT_NEXT_USHORT( p );
1000    LookupList  = FT_NEXT_USHORT( p );
1001
1002    valid->type_count  = 9;
1003    valid->type_funcs  = (OTV_Validate_Func*)otv_gpos_validate_funcs;
1004    valid->glyph_count = glyph_count;
1005
1006    otv_LookupList_validate( table + LookupList,
1007                             valid );
1008    otv_FeatureList_validate( table + FeatureList, table + LookupList,
1009                              valid );
1010    otv_ScriptList_validate( table + ScriptList, table + FeatureList,
1011                             valid );
1012
1013    FT_TRACE4(( "\n" ));
1014  }
1015
1016
1017/* END */