Visualization Library 2.0.0-b5

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
gxvcommn.c
Go to the documentation of this file.
1 /***************************************************************************/
2 /* */
3 /* gxvcommn.c */
4 /* */
5 /* TrueTypeGX/AAT common tables validation (body). */
6 /* */
7 /* Copyright 2004, 2005, 2009, 2010, 2013 */
8 /* by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
9 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
10 /* */
11 /* This file is part of the FreeType project, and may only be used, */
12 /* modified, and distributed under the terms of the FreeType project */
13 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
14 /* this file you indicate that you have read the license and */
15 /* understand and accept it fully. */
16 /* */
17 /***************************************************************************/
18 
19 /***************************************************************************/
20 /* */
21 /* gxvalid is derived from both gxlayout module and otvalid module. */
22 /* Development of gxlayout is supported by the Information-technology */
23 /* Promotion Agency(IPA), Japan. */
24 /* */
25 /***************************************************************************/
26 
27 
28 #include "gxvcommn.h"
29 
30 
31  /*************************************************************************/
32  /* */
33  /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
34  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
35  /* messages during execution. */
36  /* */
37 #undef FT_COMPONENT
38 #define FT_COMPONENT trace_gxvcommon
39 
40 
41  /*************************************************************************/
42  /*************************************************************************/
43  /***** *****/
44  /***** 16bit offset sorter *****/
45  /***** *****/
46  /*************************************************************************/
47  /*************************************************************************/
48 
49  static int
50  gxv_compare_ushort_offset( FT_UShort* a,
51  FT_UShort* b )
52  {
53  if ( *a < *b )
54  return -1;
55  else if ( *a > *b )
56  return 1;
57  else
58  return 0;
59  }
60 
61 
62  FT_LOCAL_DEF( void )
64  FT_UShort** length,
65  FT_UShort* buff,
66  FT_UInt nmemb,
68  GXV_Validator valid )
69  {
70  FT_UInt i;
71 
72 
73  for ( i = 0; i < nmemb; i++ )
74  *(length[i]) = 0;
75 
76  for ( i = 0; i < nmemb; i++ )
77  buff[i] = offset[i];
78  buff[nmemb] = limit;
79 
80  ft_qsort( buff, ( nmemb + 1 ), sizeof ( FT_UShort ),
81  ( int(*)(const void*, const void*) )gxv_compare_ushort_offset );
82 
83  if ( buff[nmemb] > limit )
85 
86  for ( i = 0; i < nmemb; i++ )
87  {
88  FT_UInt j;
89 
90 
91  for ( j = 0; j < nmemb; j++ )
92  if ( buff[j] == offset[i] )
93  break;
94 
95  if ( j == nmemb )
97 
98  *(length[i]) = (FT_UShort)( buff[j + 1] - buff[j] );
99 
100  if ( 0 != offset[i] && 0 == *(length[i]) )
102  }
103  }
104 
105 
106  /*************************************************************************/
107  /*************************************************************************/
108  /***** *****/
109  /***** 32bit offset sorter *****/
110  /***** *****/
111  /*************************************************************************/
112  /*************************************************************************/
113 
114  static int
115  gxv_compare_ulong_offset( FT_ULong* a,
116  FT_ULong* b )
117  {
118  if ( *a < *b )
119  return -1;
120  else if ( *a > *b )
121  return 1;
122  else
123  return 0;
124  }
125 
126 
127  FT_LOCAL_DEF( void )
129  FT_ULong** length,
130  FT_ULong* buff,
131  FT_UInt nmemb,
132  FT_ULong limit,
133  GXV_Validator valid)
134  {
135  FT_UInt i;
136 
137 
138  for ( i = 0; i < nmemb; i++ )
139  *(length[i]) = 0;
140 
141  for ( i = 0; i < nmemb; i++ )
142  buff[i] = offset[i];
143  buff[nmemb] = limit;
144 
145  ft_qsort( buff, ( nmemb + 1 ), sizeof ( FT_ULong ),
146  ( int(*)(const void*, const void*) )gxv_compare_ulong_offset );
147 
148  if ( buff[nmemb] > limit )
150 
151  for ( i = 0; i < nmemb; i++ )
152  {
153  FT_UInt j;
154 
155 
156  for ( j = 0; j < nmemb; j++ )
157  if ( buff[j] == offset[i] )
158  break;
159 
160  if ( j == nmemb )
162 
163  *(length[i]) = buff[j + 1] - buff[j];
164 
165  if ( 0 != offset[i] && 0 == *(length[i]) )
167  }
168  }
169 
170 
171  /*************************************************************************/
172  /*************************************************************************/
173  /***** *****/
174  /***** scan value array and get min & max *****/
175  /***** *****/
176  /*************************************************************************/
177  /*************************************************************************/
178 
179 
180  FT_LOCAL_DEF( void )
182  FT_Bytes limit,
183  FT_Byte* min,
184  FT_Byte* max,
185  GXV_Validator valid )
186  {
187  FT_Bytes p = table;
188 
189 
190  *min = 0xFF;
191  *max = 0x00;
192 
193  while ( p < limit )
194  {
195  FT_Byte val;
196 
197 
198  GXV_LIMIT_CHECK( 1 );
199  val = FT_NEXT_BYTE( p );
200 
201  *min = (FT_Byte)FT_MIN( *min, val );
202  *max = (FT_Byte)FT_MAX( *max, val );
203  }
204 
205  valid->subtable_length = p - table;
206  }
207 
208 
209  FT_LOCAL_DEF( void )
211  FT_Bytes limit,
212  FT_UShort* min,
213  FT_UShort* max,
214  GXV_Validator valid )
215  {
216  FT_Bytes p = table;
217 
218 
219  *min = 0xFFFFU;
220  *max = 0x0000;
221 
222  while ( p < limit )
223  {
224  FT_UShort val;
225 
226 
227  GXV_LIMIT_CHECK( 2 );
228  val = FT_NEXT_USHORT( p );
229 
230  *min = (FT_Byte)FT_MIN( *min, val );
231  *max = (FT_Byte)FT_MAX( *max, val );
232  }
233 
234  valid->subtable_length = p - table;
235  }
236 
237 
238  /*************************************************************************/
239  /*************************************************************************/
240  /***** *****/
241  /***** BINSEARCHHEADER *****/
242  /***** *****/
243  /*************************************************************************/
244  /*************************************************************************/
245 
246  typedef struct GXV_BinSrchHeader_
247  {
248  FT_UShort unitSize;
249  FT_UShort nUnits;
250  FT_UShort searchRange;
251  FT_UShort entrySelector;
252  FT_UShort rangeShift;
253 
255 
256 
257  static void
258  gxv_BinSrchHeader_check_consistency( GXV_BinSrchHeader* binSrchHeader,
259  GXV_Validator valid )
260  {
261  FT_UShort searchRange;
262  FT_UShort entrySelector;
263  FT_UShort rangeShift;
264 
265 
266  if ( binSrchHeader->unitSize == 0 )
268 
269  if ( binSrchHeader->nUnits == 0 )
270  {
271  if ( binSrchHeader->searchRange == 0 &&
272  binSrchHeader->entrySelector == 0 &&
273  binSrchHeader->rangeShift == 0 )
274  return;
275  else
277  }
278 
279  for ( searchRange = 1, entrySelector = 1;
280  ( searchRange * 2 ) <= binSrchHeader->nUnits &&
281  searchRange < 0x8000U;
282  searchRange *= 2, entrySelector++ )
283  ;
284 
285  entrySelector--;
286  searchRange = (FT_UShort)( searchRange * binSrchHeader->unitSize );
287  rangeShift = (FT_UShort)( binSrchHeader->nUnits * binSrchHeader->unitSize
288  - searchRange );
289 
290  if ( searchRange != binSrchHeader->searchRange ||
291  entrySelector != binSrchHeader->entrySelector ||
292  rangeShift != binSrchHeader->rangeShift )
293  {
294  GXV_TRACE(( "Inconsistency found in BinSrchHeader\n" ));
295  GXV_TRACE(( "originally: unitSize=%d, nUnits=%d, "
296  "searchRange=%d, entrySelector=%d, "
297  "rangeShift=%d\n",
298  binSrchHeader->unitSize, binSrchHeader->nUnits,
299  binSrchHeader->searchRange, binSrchHeader->entrySelector,
300  binSrchHeader->rangeShift ));
301  GXV_TRACE(( "calculated: unitSize=%d, nUnits=%d, "
302  "searchRange=%d, entrySelector=%d, "
303  "rangeShift=%d\n",
304  binSrchHeader->unitSize, binSrchHeader->nUnits,
305  searchRange, entrySelector, rangeShift ));
306 
308  }
309  }
310 
311 
312  /*
313  * parser & validator of BinSrchHeader
314  * which is used in LookupTable format 2, 4, 6.
315  *
316  * Essential parameters (unitSize, nUnits) are returned by
317  * given pointer, others (searchRange, entrySelector, rangeShift)
318  * can be calculated by essential parameters, so they are just
319  * validated and discarded.
320  *
321  * However, wrong values in searchRange, entrySelector, rangeShift
322  * won't cause fatal errors, because these parameters might be
323  * only used in old m68k font driver in MacOS.
324  * -- suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
325  */
326 
327  FT_LOCAL_DEF( void )
329  FT_Bytes limit,
330  FT_UShort* unitSize_p,
331  FT_UShort* nUnits_p,
332  GXV_Validator valid )
333  {
334  FT_Bytes p = table;
335  GXV_BinSrchHeader binSrchHeader;
336 
337 
338  GXV_NAME_ENTER( "BinSrchHeader validate" );
339 
340  if ( *unitSize_p == 0 )
341  {
342  GXV_LIMIT_CHECK( 2 );
343  binSrchHeader.unitSize = FT_NEXT_USHORT( p );
344  }
345  else
346  binSrchHeader.unitSize = *unitSize_p;
347 
348  if ( *nUnits_p == 0 )
349  {
350  GXV_LIMIT_CHECK( 2 );
351  binSrchHeader.nUnits = FT_NEXT_USHORT( p );
352  }
353  else
354  binSrchHeader.nUnits = *nUnits_p;
355 
356  GXV_LIMIT_CHECK( 2 + 2 + 2 );
357  binSrchHeader.searchRange = FT_NEXT_USHORT( p );
358  binSrchHeader.entrySelector = FT_NEXT_USHORT( p );
359  binSrchHeader.rangeShift = FT_NEXT_USHORT( p );
360  GXV_TRACE(( "nUnits %d\n", binSrchHeader.nUnits ));
361 
362  gxv_BinSrchHeader_check_consistency( &binSrchHeader, valid );
363 
364  if ( *unitSize_p == 0 )
365  *unitSize_p = binSrchHeader.unitSize;
366 
367  if ( *nUnits_p == 0 )
368  *nUnits_p = binSrchHeader.nUnits;
369 
370  valid->subtable_length = p - table;
371  GXV_EXIT;
372  }
373 
374 
375  /*************************************************************************/
376  /*************************************************************************/
377  /***** *****/
378  /***** LOOKUP TABLE *****/
379  /***** *****/
380  /*************************************************************************/
381  /*************************************************************************/
382 
383 #define GXV_LOOKUP_VALUE_LOAD( P, SIGNSPEC ) \
384  ( P += 2, gxv_lookup_value_load( P - 2, SIGNSPEC ) )
385 
386  static GXV_LookupValueDesc
387  gxv_lookup_value_load( FT_Bytes p,
388  int signspec )
389  {
391 
392 
393  if ( signspec == GXV_LOOKUPVALUE_UNSIGNED )
394  v.u = FT_NEXT_USHORT( p );
395  else
396  v.s = FT_NEXT_SHORT( p );
397 
398  return v;
399  }
400 
401 
402 #define GXV_UNITSIZE_VALIDATE( FORMAT, UNITSIZE, NUNITS, CORRECTSIZE ) \
403  FT_BEGIN_STMNT \
404  if ( UNITSIZE != CORRECTSIZE ) \
405  { \
406  FT_ERROR(( "unitSize=%d differs from" \
407  " expected unitSize=%d" \
408  " in LookupTable %s\n", \
409  UNITSIZE, CORRECTSIZE, FORMAT )); \
410  if ( UNITSIZE != 0 && NUNITS != 0 ) \
411  { \
412  FT_ERROR(( " cannot validate anymore\n" )); \
413  FT_INVALID_FORMAT; \
414  } \
415  else \
416  FT_ERROR(( " forcibly continues\n" )); \
417  } \
418  FT_END_STMNT
419 
420 
421  /* ================= Simple Array Format 0 Lookup Table ================ */
422  static void
423  gxv_LookupTable_fmt0_validate( FT_Bytes table,
424  FT_Bytes limit,
425  GXV_Validator valid )
426  {
427  FT_Bytes p = table;
428  FT_UShort i;
429 
431 
432 
433  GXV_NAME_ENTER( "LookupTable format 0" );
434 
435  GXV_LIMIT_CHECK( 2 * valid->face->num_glyphs );
436 
437  for ( i = 0; i < valid->face->num_glyphs; i++ )
438  {
439  GXV_LIMIT_CHECK( 2 );
440  if ( p + 2 >= limit ) /* some fonts have too-short fmt0 array */
441  {
442  GXV_TRACE(( "too short, glyphs %d - %d are missing\n",
443  i, valid->face->num_glyphs ));
445  break;
446  }
447 
448  value = GXV_LOOKUP_VALUE_LOAD( p, valid->lookupval_sign );
449  valid->lookupval_func( i, &value, valid );
450  }
451 
452  valid->subtable_length = p - table;
453  GXV_EXIT;
454  }
455 
456 
457  /* ================= Segment Single Format 2 Loolup Table ============== */
458  /*
459  * Apple spec says:
460  *
461  * To guarantee that a binary search terminates, you must include one or
462  * more special `end of search table' values at the end of the data to
463  * be searched. The number of termination values that need to be
464  * included is table-specific. The value that indicates binary search
465  * termination is 0xFFFF.
466  *
467  * The problem is that nUnits does not include this end-marker. It's
468  * quite difficult to discriminate whether the following 0xFFFF comes from
469  * the end-marker or some next data.
470  *
471  * -- suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
472  */
473  static void
474  gxv_LookupTable_fmt2_skip_endmarkers( FT_Bytes table,
475  FT_UShort unitSize,
476  GXV_Validator valid )
477  {
478  FT_Bytes p = table;
479 
480 
481  while ( ( p + 4 ) < valid->root->limit )
482  {
483  if ( p[0] != 0xFF || p[1] != 0xFF || /* lastGlyph */
484  p[2] != 0xFF || p[3] != 0xFF ) /* firstGlyph */
485  break;
486  p += unitSize;
487  }
488 
489  valid->subtable_length = p - table;
490  }
491 
492 
493  static void
494  gxv_LookupTable_fmt2_validate( FT_Bytes table,
495  FT_Bytes limit,
496  GXV_Validator valid )
497  {
498  FT_Bytes p = table;
499  FT_UShort gid;
500 
501  FT_UShort unitSize;
502  FT_UShort nUnits;
503  FT_UShort unit;
504  FT_UShort lastGlyph;
507 
508 
509  GXV_NAME_ENTER( "LookupTable format 2" );
510 
511  unitSize = nUnits = 0;
512  gxv_BinSrchHeader_validate( p, limit, &unitSize, &nUnits, valid );
513  p += valid->subtable_length;
514 
515  GXV_UNITSIZE_VALIDATE( "format2", unitSize, nUnits, 6 );
516 
517  for ( unit = 0, gid = 0; unit < nUnits; unit++ )
518  {
519  GXV_LIMIT_CHECK( 2 + 2 + 2 );
520  lastGlyph = FT_NEXT_USHORT( p );
521  firstGlyph = FT_NEXT_USHORT( p );
522  value = GXV_LOOKUP_VALUE_LOAD( p, valid->lookupval_sign );
523 
524  gxv_glyphid_validate( firstGlyph, valid );
525  gxv_glyphid_validate( lastGlyph, valid );
526 
527  if ( lastGlyph < gid )
528  {
529  GXV_TRACE(( "reverse ordered segment specification:"
530  " lastGlyph[%d]=%d < lastGlyph[%d]=%d\n",
531  unit, lastGlyph, unit - 1 , gid ));
533  }
534 
535  if ( lastGlyph < firstGlyph )
536  {
537  GXV_TRACE(( "reverse ordered range specification at unit %d:",
538  " lastGlyph %d < firstGlyph %d ",
539  unit, lastGlyph, firstGlyph ));
541 
542  if ( valid->root->level == FT_VALIDATE_TIGHT )
543  continue; /* ftxvalidator silently skips such an entry */
544 
545  FT_TRACE4(( "continuing with exchanged values\n" ));
546  gid = firstGlyph;
547  firstGlyph = lastGlyph;
548  lastGlyph = gid;
549  }
550 
551  for ( gid = firstGlyph; gid <= lastGlyph; gid++ )
552  valid->lookupval_func( gid, &value, valid );
553  }
554 
555  gxv_LookupTable_fmt2_skip_endmarkers( p, unitSize, valid );
556  p += valid->subtable_length;
557 
558  valid->subtable_length = p - table;
559  GXV_EXIT;
560  }
561 
562 
563  /* ================= Segment Array Format 4 Lookup Table =============== */
564  static void
565  gxv_LookupTable_fmt4_validate( FT_Bytes table,
566  FT_Bytes limit,
567  GXV_Validator valid )
568  {
569  FT_Bytes p = table;
570  FT_UShort unit;
571  FT_UShort gid;
572 
573  FT_UShort unitSize;
574  FT_UShort nUnits;
575  FT_UShort lastGlyph;
577  GXV_LookupValueDesc base_value;
579 
580 
581  GXV_NAME_ENTER( "LookupTable format 4" );
582 
583  unitSize = nUnits = 0;
584  gxv_BinSrchHeader_validate( p, limit, &unitSize, &nUnits, valid );
585  p += valid->subtable_length;
586 
587  GXV_UNITSIZE_VALIDATE( "format4", unitSize, nUnits, 6 );
588 
589  for ( unit = 0, gid = 0; unit < nUnits; unit++ )
590  {
591  GXV_LIMIT_CHECK( 2 + 2 );
592  lastGlyph = FT_NEXT_USHORT( p );
593  firstGlyph = FT_NEXT_USHORT( p );
594 
595  gxv_glyphid_validate( firstGlyph, valid );
596  gxv_glyphid_validate( lastGlyph, valid );
597 
598  if ( lastGlyph < gid )
599  {
600  GXV_TRACE(( "reverse ordered segment specification:"
601  " lastGlyph[%d]=%d < lastGlyph[%d]=%d\n",
602  unit, lastGlyph, unit - 1 , gid ));
604  }
605 
606  if ( lastGlyph < firstGlyph )
607  {
608  GXV_TRACE(( "reverse ordered range specification at unit %d:",
609  " lastGlyph %d < firstGlyph %d ",
610  unit, lastGlyph, firstGlyph ));
612 
613  if ( valid->root->level == FT_VALIDATE_TIGHT )
614  continue; /* ftxvalidator silently skips such an entry */
615 
616  FT_TRACE4(( "continuing with exchanged values\n" ));
617  gid = firstGlyph;
618  firstGlyph = lastGlyph;
619  lastGlyph = gid;
620  }
621 
622  GXV_LIMIT_CHECK( 2 );
624 
625  for ( gid = firstGlyph; gid <= lastGlyph; gid++ )
626  {
627  value = valid->lookupfmt4_trans( (FT_UShort)( gid - firstGlyph ),
628  &base_value,
629  limit,
630  valid );
631 
632  valid->lookupval_func( gid, &value, valid );
633  }
634  }
635 
636  gxv_LookupTable_fmt2_skip_endmarkers( p, unitSize, valid );
637  p += valid->subtable_length;
638 
639  valid->subtable_length = p - table;
640  GXV_EXIT;
641  }
642 
643 
644  /* ================= Segment Table Format 6 Lookup Table =============== */
645  static void
646  gxv_LookupTable_fmt6_skip_endmarkers( FT_Bytes table,
647  FT_UShort unitSize,
648  GXV_Validator valid )
649  {
650  FT_Bytes p = table;
651 
652 
653  while ( p < valid->root->limit )
654  {
655  if ( p[0] != 0xFF || p[1] != 0xFF )
656  break;
657  p += unitSize;
658  }
659 
660  valid->subtable_length = p - table;
661  }
662 
663 
664  static void
665  gxv_LookupTable_fmt6_validate( FT_Bytes table,
666  FT_Bytes limit,
667  GXV_Validator valid )
668  {
669  FT_Bytes p = table;
670  FT_UShort unit;
671  FT_UShort prev_glyph;
672 
673  FT_UShort unitSize;
674  FT_UShort nUnits;
675  FT_UShort glyph;
677 
678 
679  GXV_NAME_ENTER( "LookupTable format 6" );
680 
681  unitSize = nUnits = 0;
682  gxv_BinSrchHeader_validate( p, limit, &unitSize, &nUnits, valid );
683  p += valid->subtable_length;
684 
685  GXV_UNITSIZE_VALIDATE( "format6", unitSize, nUnits, 4 );
686 
687  for ( unit = 0, prev_glyph = 0; unit < nUnits; unit++ )
688  {
689  GXV_LIMIT_CHECK( 2 + 2 );
690  glyph = FT_NEXT_USHORT( p );
691  value = GXV_LOOKUP_VALUE_LOAD( p, valid->lookupval_sign );
692 
693  if ( gxv_glyphid_validate( glyph, valid ) )
694  GXV_TRACE(( " endmarker found within defined range"
695  " (entry %d < nUnits=%d)\n",
696  unit, nUnits ));
697 
698  if ( prev_glyph > glyph )
699  {
700  GXV_TRACE(( "current gid 0x%04x < previous gid 0x%04x\n",
701  glyph, prev_glyph ));
703  }
704  prev_glyph = glyph;
705 
706  valid->lookupval_func( glyph, &value, valid );
707  }
708 
709  gxv_LookupTable_fmt6_skip_endmarkers( p, unitSize, valid );
710  p += valid->subtable_length;
711 
712  valid->subtable_length = p - table;
713  GXV_EXIT;
714  }
715 
716 
717  /* ================= Trimmed Array Format 8 Lookup Table =============== */
718  static void
719  gxv_LookupTable_fmt8_validate( FT_Bytes table,
720  FT_Bytes limit,
721  GXV_Validator valid )
722  {
723  FT_Bytes p = table;
724  FT_UShort i;
725 
728  FT_UShort glyphCount;
729 
730 
731  GXV_NAME_ENTER( "LookupTable format 8" );
732 
733  /* firstGlyph + glyphCount */
734  GXV_LIMIT_CHECK( 2 + 2 );
735  firstGlyph = FT_NEXT_USHORT( p );
736  glyphCount = FT_NEXT_USHORT( p );
737 
738  gxv_glyphid_validate( firstGlyph, valid );
739  gxv_glyphid_validate( (FT_UShort)( firstGlyph + glyphCount ), valid );
740 
741  /* valueArray */
742  for ( i = 0; i < glyphCount; i++ )
743  {
744  GXV_LIMIT_CHECK( 2 );
745  value = GXV_LOOKUP_VALUE_LOAD( p, valid->lookupval_sign );
746  valid->lookupval_func( (FT_UShort)( firstGlyph + i ), &value, valid );
747  }
748 
749  valid->subtable_length = p - table;
750  GXV_EXIT;
751  }
752 
753 
754  FT_LOCAL_DEF( void )
756  FT_Bytes limit,
757  GXV_Validator valid )
758  {
759  FT_Bytes p = table;
761 
762  GXV_Validate_Func fmt_funcs_table[] =
763  {
764  gxv_LookupTable_fmt0_validate, /* 0 */
765  NULL, /* 1 */
766  gxv_LookupTable_fmt2_validate, /* 2 */
767  NULL, /* 3 */
768  gxv_LookupTable_fmt4_validate, /* 4 */
769  NULL, /* 5 */
770  gxv_LookupTable_fmt6_validate, /* 6 */
771  NULL, /* 7 */
772  gxv_LookupTable_fmt8_validate, /* 8 */
773  };
774 
776 
777 
778  GXV_NAME_ENTER( "LookupTable" );
779 
780  /* lookuptbl_head may be used in fmt4 transit function. */
781  valid->lookuptbl_head = table;
782 
783  /* format */
784  GXV_LIMIT_CHECK( 2 );
785  format = FT_NEXT_USHORT( p );
786  GXV_TRACE(( " (format %d)\n", format ));
787 
788  if ( format > 8 )
790 
791  func = fmt_funcs_table[format];
792  if ( func == NULL )
794 
795  func( p, limit, valid );
796  p += valid->subtable_length;
797 
798  valid->subtable_length = p - table;
799 
800  GXV_EXIT;
801  }
802 
803 
804  /*************************************************************************/
805  /*************************************************************************/
806  /***** *****/
807  /***** Glyph ID *****/
808  /***** *****/
809  /*************************************************************************/
810  /*************************************************************************/
811 
814  GXV_Validator valid )
815  {
816  FT_Face face;
817 
818 
819  if ( gid == 0xFFFFU )
820  {
821  GXV_EXIT;
822  return 1;
823  }
824 
825  face = valid->face;
826  if ( face->num_glyphs < gid )
827  {
828  GXV_TRACE(( " gxv_glyphid_check() gid overflow: num_glyphs %d < %d\n",
829  face->num_glyphs, gid ));
831  }
832 
833  return 0;
834  }
835 
836 
837  /*************************************************************************/
838  /*************************************************************************/
839  /***** *****/
840  /***** CONTROL POINT *****/
841  /***** *****/
842  /*************************************************************************/
843  /*************************************************************************/
844 
845  FT_LOCAL_DEF( void )
847  FT_Short ctl_point,
848  GXV_Validator valid )
849  {
850  FT_Face face;
851  FT_Error error;
852 
853  FT_GlyphSlot glyph;
854  FT_Outline outline;
855  short n_points;
856 
857 
858  face = valid->face;
859 
860  error = FT_Load_Glyph( face,
861  gid,
863  if ( error )
865 
866  glyph = face->glyph;
867  outline = glyph->outline;
868  n_points = outline.n_points;
869 
870 
871  if ( !( ctl_point < n_points ) )
873  }
874 
875 
876  /*************************************************************************/
877  /*************************************************************************/
878  /***** *****/
879  /***** SFNT NAME *****/
880  /***** *****/
881  /*************************************************************************/
882  /*************************************************************************/
883 
884  FT_LOCAL_DEF( void )
886  FT_UShort min_index,
887  FT_UShort max_index,
888  GXV_Validator valid )
889  {
891  FT_UInt i;
892  FT_UInt nnames;
893 
894 
895  GXV_NAME_ENTER( "sfntName" );
896 
897  if ( name_index < min_index || max_index < name_index )
899 
900  nnames = FT_Get_Sfnt_Name_Count( valid->face );
901  for ( i = 0; i < nnames; i++ )
902  {
903  if ( FT_Get_Sfnt_Name( valid->face, i, &name ) != FT_Err_Ok )
904  continue ;
905 
906  if ( name.name_id == name_index )
907  goto Out;
908  }
909 
910  GXV_TRACE(( " nameIndex = %d (UNTITLED)\n", name_index ));
912  goto Exit; /* make compiler happy */
913 
914  Out:
915  FT_TRACE1(( " nameIndex = %d (", name_index ));
917  FT_TRACE1(( ")\n" ));
918 
919  Exit:
920  GXV_EXIT;
921  }
922 
923 
924  /*************************************************************************/
925  /*************************************************************************/
926  /***** *****/
927  /***** STATE TABLE *****/
928  /***** *****/
929  /*************************************************************************/
930  /*************************************************************************/
931 
932  /* -------------------------- Class Table --------------------------- */
933 
934  /*
935  * highestClass specifies how many classes are defined in this
936  * Class Subtable. Apple spec does not mention whether undefined
937  * holes in the class (e.g.: 0-3 are predefined, 4 is unused, 5 is used)
938  * are permitted. At present, holes in a defined class are not checked.
939  * -- suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
940  */
941 
942  static void
943  gxv_ClassTable_validate( FT_Bytes table,
944  FT_UShort* length_p,
945  FT_UShort stateSize,
946  FT_Byte* maxClassID_p,
947  GXV_Validator valid )
948  {
949  FT_Bytes p = table;
950  FT_Bytes limit = table + *length_p;
952  FT_UShort nGlyphs;
953 
954 
955  GXV_NAME_ENTER( "ClassTable" );
956 
957  *maxClassID_p = 3; /* Classes 0, 2, and 3 are predefined */
958 
959  GXV_LIMIT_CHECK( 2 + 2 );
960  firstGlyph = FT_NEXT_USHORT( p );
961  nGlyphs = FT_NEXT_USHORT( p );
962 
963  GXV_TRACE(( " (firstGlyph = %d, nGlyphs = %d)\n", firstGlyph, nGlyphs ));
964 
965  if ( !nGlyphs )
966  goto Out;
967 
968  gxv_glyphid_validate( (FT_UShort)( firstGlyph + nGlyphs ), valid );
969 
970  {
971  FT_Byte nGlyphInClass[256];
972  FT_Byte classID;
973  FT_UShort i;
974 
975 
976  ft_memset( nGlyphInClass, 0, 256 );
977 
978 
979  for ( i = 0; i < nGlyphs; i++ )
980  {
981  GXV_LIMIT_CHECK( 1 );
982  classID = FT_NEXT_BYTE( p );
983  switch ( classID )
984  {
985  /* following classes should not appear in class array */
986  case 0: /* end of text */
987  case 2: /* out of bounds */
988  case 3: /* end of line */
990  break;
991 
992  case 1: /* out of bounds */
993  default: /* user-defined: 4 - ( stateSize - 1 ) */
994  if ( classID >= stateSize )
995  FT_INVALID_DATA; /* assign glyph to undefined state */
996 
997  nGlyphInClass[classID]++;
998  break;
999  }
1000  }
1001  *length_p = (FT_UShort)( p - table );
1002 
1003  /* scan max ClassID in use */
1004  for ( i = 0; i < stateSize; i++ )
1005  if ( ( 3 < i ) && ( nGlyphInClass[i] > 0 ) )
1006  *maxClassID_p = (FT_Byte)i; /* XXX: Check Range? */
1007  }
1008 
1009  Out:
1010  GXV_TRACE(( "Declared stateSize=0x%02x, Used maxClassID=0x%02x\n",
1011  stateSize, *maxClassID_p ));
1012  GXV_EXIT;
1013  }
1014 
1015 
1016  /* --------------------------- State Array ----------------------------- */
1017 
1018  static void
1019  gxv_StateArray_validate( FT_Bytes table,
1020  FT_UShort* length_p,
1021  FT_Byte maxClassID,
1022  FT_UShort stateSize,
1023  FT_Byte* maxState_p,
1024  FT_Byte* maxEntry_p,
1025  GXV_Validator valid )
1026  {
1027  FT_Bytes p = table;
1028  FT_Bytes limit = table + *length_p;
1029  FT_Byte clazz;
1030  FT_Byte entry;
1031 
1032  FT_UNUSED( stateSize ); /* for the non-debugging case */
1033 
1034 
1035  GXV_NAME_ENTER( "StateArray" );
1036 
1037  GXV_TRACE(( "parse %d bytes by stateSize=%d maxClassID=%d\n",
1038  (int)(*length_p), stateSize, (int)(maxClassID) ));
1039 
1040  /*
1041  * 2 states are predefined and must be described in StateArray:
1042  * state 0 (start of text), 1 (start of line)
1043  */
1044  GXV_LIMIT_CHECK( ( 1 + maxClassID ) * 2 );
1045 
1046  *maxState_p = 0;
1047  *maxEntry_p = 0;
1048 
1049  /* read if enough to read another state */
1050  while ( p + ( 1 + maxClassID ) <= limit )
1051  {
1052  (*maxState_p)++;
1053  for ( clazz = 0; clazz <= maxClassID; clazz++ )
1054  {
1055  entry = FT_NEXT_BYTE( p );
1056  *maxEntry_p = (FT_Byte)FT_MAX( *maxEntry_p, entry );
1057  }
1058  }
1059  GXV_TRACE(( "parsed: maxState=%d, maxEntry=%d\n",
1060  *maxState_p, *maxEntry_p ));
1061 
1062  *length_p = (FT_UShort)( p - table );
1063 
1064  GXV_EXIT;
1065  }
1066 
1067 
1068  /* --------------------------- Entry Table ----------------------------- */
1069 
1070  static void
1071  gxv_EntryTable_validate( FT_Bytes table,
1072  FT_UShort* length_p,
1073  FT_Byte maxEntry,
1074  FT_UShort stateArray,
1075  FT_UShort stateArray_length,
1076  FT_Byte maxClassID,
1077  FT_Bytes statetable_table,
1078  FT_Bytes statetable_limit,
1079  GXV_Validator valid )
1080  {
1081  FT_Bytes p = table;
1082  FT_Bytes limit = table + *length_p;
1083  FT_Byte entry;
1084  FT_Byte state;
1085  FT_Int entrySize = 2 + 2 + GXV_GLYPHOFFSET_SIZE( statetable );
1086 
1087  GXV_XStateTable_GlyphOffsetDesc glyphOffset;
1088 
1089 
1090  GXV_NAME_ENTER( "EntryTable" );
1091 
1092  GXV_TRACE(( "maxEntry=%d entrySize=%d\n", maxEntry, entrySize ));
1093 
1094  if ( ( maxEntry + 1 ) * entrySize > *length_p )
1095  {
1097 
1098  /* ftxvalidator and FontValidator both warn and continue */
1099  maxEntry = (FT_Byte)( *length_p / entrySize - 1 );
1100  GXV_TRACE(( "too large maxEntry, shrinking to %d fit EntryTable length\n",
1101  maxEntry ));
1102  }
1103 
1104  for ( entry = 0; entry <= maxEntry; entry++ )
1105  {
1106  FT_UShort newState;
1107  FT_UShort flags;
1108 
1109 
1110  GXV_LIMIT_CHECK( 2 + 2 );
1111  newState = FT_NEXT_USHORT( p );
1112  flags = FT_NEXT_USHORT( p );
1113 
1114 
1115  if ( newState < stateArray ||
1116  stateArray + stateArray_length < newState )
1117  {
1118  GXV_TRACE(( " newState offset 0x%04x is out of stateArray\n",
1119  newState ));
1121  continue;
1122  }
1123 
1124  if ( 0 != ( ( newState - stateArray ) % ( 1 + maxClassID ) ) )
1125  {
1126  GXV_TRACE(( " newState offset 0x%04x is not aligned to %d-classes\n",
1127  newState, 1 + maxClassID ));
1129  continue;
1130  }
1131 
1132  state = (FT_Byte)( ( newState - stateArray ) / ( 1 + maxClassID ) );
1133 
1134  switch ( GXV_GLYPHOFFSET_FMT( statetable ) )
1135  {
1136  case GXV_GLYPHOFFSET_NONE:
1137  glyphOffset.uc = 0; /* make compiler happy */
1138  break;
1139 
1140  case GXV_GLYPHOFFSET_UCHAR:
1141  glyphOffset.uc = FT_NEXT_BYTE( p );
1142  break;
1143 
1144  case GXV_GLYPHOFFSET_CHAR:
1145  glyphOffset.c = FT_NEXT_CHAR( p );
1146  break;
1147 
1149  glyphOffset.u = FT_NEXT_USHORT( p );
1150  break;
1151 
1152  case GXV_GLYPHOFFSET_SHORT:
1153  glyphOffset.s = FT_NEXT_SHORT( p );
1154  break;
1155 
1156  case GXV_GLYPHOFFSET_ULONG:
1157  glyphOffset.ul = FT_NEXT_ULONG( p );
1158  break;
1159 
1160  case GXV_GLYPHOFFSET_LONG:
1161  glyphOffset.l = FT_NEXT_LONG( p );
1162  break;
1163 
1164  default:
1166  goto Exit;
1167  }
1168 
1169  if ( NULL != valid->statetable.entry_validate_func )
1170  valid->statetable.entry_validate_func( state,
1171  flags,
1172  &glyphOffset,
1173  statetable_table,
1174  statetable_limit,
1175  valid );
1176  }
1177 
1178  Exit:
1179  *length_p = (FT_UShort)( p - table );
1180 
1181  GXV_EXIT;
1182  }
1183 
1184 
1185  /* =========================== State Table ============================= */
1186 
1187  FT_LOCAL_DEF( void )
1189  FT_UShort classTable,
1190  FT_UShort stateArray,
1191  FT_UShort entryTable,
1192  FT_UShort* classTable_length_p,
1193  FT_UShort* stateArray_length_p,
1194  FT_UShort* entryTable_length_p,
1195  GXV_Validator valid )
1196  {
1197  FT_UShort o[3];
1198  FT_UShort* l[3];
1199  FT_UShort buff[4];
1200 
1201 
1202  o[0] = classTable;
1203  o[1] = stateArray;
1204  o[2] = entryTable;
1205  l[0] = classTable_length_p;
1206  l[1] = stateArray_length_p;
1207  l[2] = entryTable_length_p;
1208 
1209  gxv_set_length_by_ushort_offset( o, l, buff, 3, table_size, valid );
1210  }
1211 
1212 
1213  FT_LOCAL_DEF( void )
1215  FT_Bytes limit,
1216  GXV_Validator valid )
1217  {
1218  FT_UShort stateSize;
1219  FT_UShort classTable; /* offset to Class(Sub)Table */
1220  FT_UShort stateArray; /* offset to StateArray */
1221  FT_UShort entryTable; /* offset to EntryTable */
1222 
1223  FT_UShort classTable_length;
1224  FT_UShort stateArray_length;
1225  FT_UShort entryTable_length;
1226  FT_Byte maxClassID;
1227  FT_Byte maxState;
1228  FT_Byte maxEntry;
1229 
1231 
1232  FT_Bytes p = table;
1233 
1234 
1235  GXV_NAME_ENTER( "StateTable" );
1236 
1237  GXV_TRACE(( "StateTable header\n" ));
1238 
1239  GXV_LIMIT_CHECK( 2 + 2 + 2 + 2 );
1240  stateSize = FT_NEXT_USHORT( p );
1241  classTable = FT_NEXT_USHORT( p );
1242  stateArray = FT_NEXT_USHORT( p );
1243  entryTable = FT_NEXT_USHORT( p );
1244 
1245  GXV_TRACE(( "stateSize=0x%04x\n", stateSize ));
1246  GXV_TRACE(( "offset to classTable=0x%04x\n", classTable ));
1247  GXV_TRACE(( "offset to stateArray=0x%04x\n", stateArray ));
1248  GXV_TRACE(( "offset to entryTable=0x%04x\n", entryTable ));
1249 
1250  if ( stateSize > 0xFF )
1252 
1253  if ( valid->statetable.optdata_load_func != NULL )
1254  valid->statetable.optdata_load_func( p, limit, valid );
1255 
1256  if ( valid->statetable.subtable_setup_func != NULL)
1257  setup_func = valid->statetable.subtable_setup_func;
1258  else
1259  setup_func = gxv_StateTable_subtable_setup;
1260 
1261  setup_func( (FT_UShort)( limit - table ),
1262  classTable,
1263  stateArray,
1264  entryTable,
1265  &classTable_length,
1266  &stateArray_length,
1267  &entryTable_length,
1268  valid );
1269 
1270  GXV_TRACE(( "StateTable Subtables\n" ));
1271 
1272  if ( classTable != 0 )
1273  gxv_ClassTable_validate( table + classTable,
1274  &classTable_length,
1275  stateSize,
1276  &maxClassID,
1277  valid );
1278  else
1279  maxClassID = (FT_Byte)( stateSize - 1 );
1280 
1281  if ( stateArray != 0 )
1282  gxv_StateArray_validate( table + stateArray,
1283  &stateArray_length,
1284  maxClassID,
1285  stateSize,
1286  &maxState,
1287  &maxEntry,
1288  valid );
1289  else
1290  {
1291  maxState = 1; /* 0:start of text, 1:start of line are predefined */
1292  maxEntry = 0;
1293  }
1294 
1295  if ( maxEntry > 0 && entryTable == 0 )
1297 
1298  if ( entryTable != 0 )
1299  gxv_EntryTable_validate( table + entryTable,
1300  &entryTable_length,
1301  maxEntry,
1302  stateArray,
1303  stateArray_length,
1304  maxClassID,
1305  table,
1306  limit,
1307  valid );
1308 
1309  GXV_EXIT;
1310  }
1311 
1312 
1313  /* ================= eXtended State Table (for morx) =================== */
1314 
1315  FT_LOCAL_DEF( void )
1317  FT_ULong classTable,
1318  FT_ULong stateArray,
1319  FT_ULong entryTable,
1320  FT_ULong* classTable_length_p,
1321  FT_ULong* stateArray_length_p,
1322  FT_ULong* entryTable_length_p,
1323  GXV_Validator valid )
1324  {
1325  FT_ULong o[3];
1326  FT_ULong* l[3];
1327  FT_ULong buff[4];
1328 
1329 
1330  o[0] = classTable;
1331  o[1] = stateArray;
1332  o[2] = entryTable;
1333  l[0] = classTable_length_p;
1334  l[1] = stateArray_length_p;
1335  l[2] = entryTable_length_p;
1336 
1337  gxv_set_length_by_ulong_offset( o, l, buff, 3, table_size, valid );
1338  }
1339 
1340 
1341  static void
1342  gxv_XClassTable_lookupval_validate( FT_UShort glyph,
1343  GXV_LookupValueCPtr value_p,
1344  GXV_Validator valid )
1345  {
1346  FT_UNUSED( glyph );
1347 
1348  if ( value_p->u >= valid->xstatetable.nClasses )
1350  if ( value_p->u > valid->xstatetable.maxClassID )
1351  valid->xstatetable.maxClassID = value_p->u;
1352  }
1353 
1354 
1355  /*
1356  +===============+ --------+
1357  | lookup header | |
1358  +===============+ |
1359  | BinSrchHeader | |
1360  +===============+ |
1361  | lastGlyph[0] | |
1362  +---------------+ |
1363  | firstGlyph[0] | | head of lookup table
1364  +---------------+ | +
1365  | offset[0] | -> | offset [byte]
1366  +===============+ | +
1367  | lastGlyph[1] | | (glyphID - firstGlyph) * 2 [byte]
1368  +---------------+ |
1369  | firstGlyph[1] | |
1370  +---------------+ |
1371  | offset[1] | |
1372  +===============+ |
1373  |
1374  .... |
1375  |
1376  16bit value array |
1377  +===============+ |
1378  | value | <-------+
1379  ....
1380  */
1381  static GXV_LookupValueDesc
1382  gxv_XClassTable_lookupfmt4_transit( FT_UShort relative_gindex,
1383  GXV_LookupValueCPtr base_value_p,
1384  FT_Bytes lookuptbl_limit,
1385  GXV_Validator valid )
1386  {
1387  FT_Bytes p;
1388  FT_Bytes limit;
1389  FT_UShort offset;
1391 
1392  /* XXX: check range? */
1393  offset = (FT_UShort)( base_value_p->u +
1394  relative_gindex * sizeof ( FT_UShort ) );
1395 
1396  p = valid->lookuptbl_head + offset;
1397  limit = lookuptbl_limit;
1398 
1399  GXV_LIMIT_CHECK ( 2 );
1400  value.u = FT_NEXT_USHORT( p );
1401 
1402  return value;
1403  }
1404 
1405 
1406  static void
1407  gxv_XStateArray_validate( FT_Bytes table,
1408  FT_ULong* length_p,
1409  FT_UShort maxClassID,
1410  FT_ULong stateSize,
1411  FT_UShort* maxState_p,
1412  FT_UShort* maxEntry_p,
1413  GXV_Validator valid )
1414  {
1415  FT_Bytes p = table;
1416  FT_Bytes limit = table + *length_p;
1417  FT_UShort clazz;
1418  FT_UShort entry;
1419 
1420  FT_UNUSED( stateSize ); /* for the non-debugging case */
1421 
1422 
1423  GXV_NAME_ENTER( "XStateArray" );
1424 
1425  GXV_TRACE(( "parse % 3d bytes by stateSize=% 3d maxClassID=% 3d\n",
1426  (int)(*length_p), stateSize, (int)(maxClassID) ));
1427 
1428  /*
1429  * 2 states are predefined and must be described:
1430  * state 0 (start of text), 1 (start of line)
1431  */
1432  GXV_LIMIT_CHECK( ( 1 + maxClassID ) * 2 * 2 );
1433 
1434  *maxState_p = 0;
1435  *maxEntry_p = 0;
1436 
1437  /* read if enough to read another state */
1438  while ( p + ( ( 1 + maxClassID ) * 2 ) <= limit )
1439  {
1440  (*maxState_p)++;
1441  for ( clazz = 0; clazz <= maxClassID; clazz++ )
1442  {
1443  entry = FT_NEXT_USHORT( p );
1444  *maxEntry_p = (FT_UShort)FT_MAX( *maxEntry_p, entry );
1445  }
1446  }
1447  GXV_TRACE(( "parsed: maxState=%d, maxEntry=%d\n",
1448  *maxState_p, *maxEntry_p ));
1449 
1450  *length_p = p - table;
1451 
1452  GXV_EXIT;
1453  }
1454 
1455 
1456  static void
1457  gxv_XEntryTable_validate( FT_Bytes table,
1458  FT_ULong* length_p,
1459  FT_UShort maxEntry,
1460  FT_ULong stateArray_length,
1461  FT_UShort maxClassID,
1462  FT_Bytes xstatetable_table,
1463  FT_Bytes xstatetable_limit,
1464  GXV_Validator valid )
1465  {
1466  FT_Bytes p = table;
1467  FT_Bytes limit = table + *length_p;
1468  FT_UShort entry;
1469  FT_UShort state;
1470  FT_Int entrySize = 2 + 2 + GXV_GLYPHOFFSET_SIZE( xstatetable );
1471 
1472 
1473  GXV_NAME_ENTER( "XEntryTable" );
1474  GXV_TRACE(( "maxEntry=%d entrySize=%d\n", maxEntry, entrySize ));
1475 
1476  if ( ( p + ( maxEntry + 1 ) * entrySize ) > limit )
1478 
1479  for (entry = 0; entry <= maxEntry ; entry++ )
1480  {
1481  FT_UShort newState_idx;
1482  FT_UShort flags;
1483  GXV_XStateTable_GlyphOffsetDesc glyphOffset;
1484 
1485 
1486  GXV_LIMIT_CHECK( 2 + 2 );
1487  newState_idx = FT_NEXT_USHORT( p );
1488  flags = FT_NEXT_USHORT( p );
1489 
1490  if ( stateArray_length < (FT_ULong)( newState_idx * 2 ) )
1491  {
1492  GXV_TRACE(( " newState index 0x%04x points out of stateArray\n",
1493  newState_idx ));
1495  }
1496 
1497  state = (FT_UShort)( newState_idx / ( 1 + maxClassID ) );
1498  if ( 0 != ( newState_idx % ( 1 + maxClassID ) ) )
1499  {
1500  FT_TRACE4(( "-> new state = %d (supposed)\n"
1501  "but newState index 0x%04x is not aligned to %d-classes\n",
1502  state, newState_idx, 1 + maxClassID ));
1504  }
1505 
1506  switch ( GXV_GLYPHOFFSET_FMT( xstatetable ) )
1507  {
1508  case GXV_GLYPHOFFSET_NONE:
1509  glyphOffset.uc = 0; /* make compiler happy */
1510  break;
1511 
1512  case GXV_GLYPHOFFSET_UCHAR:
1513  glyphOffset.uc = FT_NEXT_BYTE( p );
1514  break;
1515 
1516  case GXV_GLYPHOFFSET_CHAR:
1517  glyphOffset.c = FT_NEXT_CHAR( p );
1518  break;
1519 
1521  glyphOffset.u = FT_NEXT_USHORT( p );
1522  break;
1523 
1524  case GXV_GLYPHOFFSET_SHORT:
1525  glyphOffset.s = FT_NEXT_SHORT( p );
1526  break;
1527 
1528  case GXV_GLYPHOFFSET_ULONG:
1529  glyphOffset.ul = FT_NEXT_ULONG( p );
1530  break;
1531 
1532  case GXV_GLYPHOFFSET_LONG:
1533  glyphOffset.l = FT_NEXT_LONG( p );
1534  break;
1535 
1536  default:
1538  goto Exit;
1539  }
1540 
1541  if ( NULL != valid->xstatetable.entry_validate_func )
1542  valid->xstatetable.entry_validate_func( state,
1543  flags,
1544  &glyphOffset,
1545  xstatetable_table,
1546  xstatetable_limit,
1547  valid );
1548  }
1549 
1550  Exit:
1551  *length_p = p - table;
1552 
1553  GXV_EXIT;
1554  }
1555 
1556 
1557  FT_LOCAL_DEF( void )
1559  FT_Bytes limit,
1560  GXV_Validator valid )
1561  {
1562  /* StateHeader members */
1563  FT_ULong classTable; /* offset to Class(Sub)Table */
1564  FT_ULong stateArray; /* offset to StateArray */
1565  FT_ULong entryTable; /* offset to EntryTable */
1566 
1567  FT_ULong classTable_length;
1568  FT_ULong stateArray_length;
1569  FT_ULong entryTable_length;
1570  FT_UShort maxState;
1571  FT_UShort maxEntry;
1572 
1574 
1575  FT_Bytes p = table;
1576 
1577 
1578  GXV_NAME_ENTER( "XStateTable" );
1579 
1580  GXV_TRACE(( "XStateTable header\n" ));
1581 
1582  GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 );
1583  valid->xstatetable.nClasses = FT_NEXT_ULONG( p );
1584  classTable = FT_NEXT_ULONG( p );
1585  stateArray = FT_NEXT_ULONG( p );
1586  entryTable = FT_NEXT_ULONG( p );
1587 
1588  GXV_TRACE(( "nClasses =0x%08x\n", valid->xstatetable.nClasses ));
1589  GXV_TRACE(( "offset to classTable=0x%08x\n", classTable ));
1590  GXV_TRACE(( "offset to stateArray=0x%08x\n", stateArray ));
1591  GXV_TRACE(( "offset to entryTable=0x%08x\n", entryTable ));
1592 
1593  if ( valid->xstatetable.nClasses > 0xFFFFU )
1595 
1596  GXV_TRACE(( "StateTable Subtables\n" ));
1597 
1598  if ( valid->xstatetable.optdata_load_func != NULL )
1599  valid->xstatetable.optdata_load_func( p, limit, valid );
1600 
1601  if ( valid->xstatetable.subtable_setup_func != NULL )
1602  setup_func = valid->xstatetable.subtable_setup_func;
1603  else
1604  setup_func = gxv_XStateTable_subtable_setup;
1605 
1606  setup_func( limit - table,
1607  classTable,
1608  stateArray,
1609  entryTable,
1610  &classTable_length,
1611  &stateArray_length,
1612  &entryTable_length,
1613  valid );
1614 
1615  if ( classTable != 0 )
1616  {
1617  valid->xstatetable.maxClassID = 0;
1619  valid->lookupval_func = gxv_XClassTable_lookupval_validate;
1620  valid->lookupfmt4_trans = gxv_XClassTable_lookupfmt4_transit;
1621  gxv_LookupTable_validate( table + classTable,
1622  table + classTable + classTable_length,
1623  valid );
1624  if ( valid->subtable_length < classTable_length )
1625  classTable_length = valid->subtable_length;
1626  }
1627  else
1628  {
1629  /* XXX: check range? */
1630  valid->xstatetable.maxClassID =
1631  (FT_UShort)( valid->xstatetable.nClasses - 1 );
1632  }
1633 
1634  if ( stateArray != 0 )
1635  gxv_XStateArray_validate( table + stateArray,
1636  &stateArray_length,
1637  valid->xstatetable.maxClassID,
1638  valid->xstatetable.nClasses,
1639  &maxState,
1640  &maxEntry,
1641  valid );
1642  else
1643  {
1644  maxState = 1; /* 0:start of text, 1:start of line are predefined */
1645  maxEntry = 0;
1646  }
1647 
1648  if ( maxEntry > 0 && entryTable == 0 )
1650 
1651  if ( entryTable != 0 )
1652  gxv_XEntryTable_validate( table + entryTable,
1653  &entryTable_length,
1654  maxEntry,
1655  stateArray_length,
1656  valid->xstatetable.maxClassID,
1657  table,
1658  limit,
1659  valid );
1660 
1661  GXV_EXIT;
1662  }
1663 
1664 
1665  /*************************************************************************/
1666  /*************************************************************************/
1667  /***** *****/
1668  /***** Table overlapping *****/
1669  /***** *****/
1670  /*************************************************************************/
1671  /*************************************************************************/
1672 
1673  static int
1674  gxv_compare_ranges( FT_Bytes table1_start,
1675  FT_ULong table1_length,
1676  FT_Bytes table2_start,
1677  FT_ULong table2_length )
1678  {
1679  if ( table1_start == table2_start )
1680  {
1681  if ( ( table1_length == 0 || table2_length == 0 ) )
1682  goto Out;
1683  }
1684  else if ( table1_start < table2_start )
1685  {
1686  if ( ( table1_start + table1_length ) <= table2_start )
1687  goto Out;
1688  }
1689  else if ( table1_start > table2_start )
1690  {
1691  if ( ( table1_start >= table2_start + table2_length ) )
1692  goto Out;
1693  }
1694  return 1;
1695 
1696  Out:
1697  return 0;
1698  }
1699 
1700 
1701  FT_LOCAL_DEF( void )
1703  FT_ULong length,
1704  const FT_String* name,
1705  GXV_odtect_Range odtect )
1706  {
1707  odtect->range[odtect->nRanges].start = start;
1708  odtect->range[odtect->nRanges].length = length;
1709  odtect->range[odtect->nRanges].name = (FT_String*)name;
1710  odtect->nRanges++;
1711  }
1712 
1713 
1714  FT_LOCAL_DEF( void )
1716  GXV_Validator valid )
1717  {
1718  FT_UInt i, j;
1719 
1720 
1721  GXV_NAME_ENTER( "check overlap among multi ranges" );
1722 
1723  for ( i = 0; i < odtect->nRanges; i++ )
1724  for ( j = 0; j < i; j++ )
1725  if ( 0 != gxv_compare_ranges( odtect->range[i].start,
1726  odtect->range[i].length,
1727  odtect->range[j].start,
1728  odtect->range[j].length ) )
1729  {
1730  if ( odtect->range[i].name || odtect->range[j].name )
1731  GXV_TRACE(( "found overlap between range %d and range %d\n",
1732  i, j ));
1733  else
1734  GXV_TRACE(( "found overlap between `%s' and `%s\'\n",
1735  odtect->range[i].name,
1736  odtect->range[j].name ));
1738  }
1739 
1740  GXV_EXIT;
1741  }
1742 
1743 
1744 /* END */
GLenum GLuint GLenum GLsizei length
int FT_Error
Definition: fttypes.h:296
unsigned long FT_ULong
Definition: fttypes.h:249
struct GXV_BinSrchHeader_ GXV_BinSrchHeader
GLboolean GLboolean GLboolean GLboolean a
GLfloat GLfloat p
#define FT_NEXT_LONG(buffer)
Definition: ftstream.h:235
GXV_StateTable_Subtable_Setup_Func subtable_setup_func
Definition: gxvcommn.h:184
gxv_ctlPoint_validate(FT_UShort gid, FT_Short ctl_point, GXV_Validator valid)
Definition: gxvcommn.c:846
#define FT_INVALID_FORMAT
Definition: ftvalid.h:133
#define NULL
Definition: ftobjs.h:61
#define GXV_NAME_ENTER(name)
Definition: gxvcommn.h:301
signed int FT_Int
Definition: fttypes.h:216
#define GXV_TRACE(s)
Definition: gxvcommn.h:304
sizeof(AF_ModuleRec)
png_infop int * unit
Definition: png.h:2299
#define FT_NEXT_BYTE(buffer)
Definition: ftstream.h:220
#define FT_UNUSED(arg)
Definition: ftconfig.h:76
#define FT_MIN(a, b)
Definition: ftobjs.h:70
#define ft_memset
Definition: ftstdlib.h:83
GLuint start
gxv_XStateTable_validate(FT_Bytes table, FT_Bytes limit, GXV_Validator valid)
Definition: gxvcommn.c:1558
#define FT_INVALID_TOO_SHORT
Definition: ftvalid.h:125
return FT_Err_Ok
Definition: ftbbox.c:645
gxv_XStateTable_subtable_setup(FT_ULong table_size, FT_ULong classTable, FT_ULong stateArray, FT_ULong entryTable, FT_ULong *classTable_length_p, FT_ULong *stateArray_length_p, FT_ULong *entryTable_length_p, GXV_Validator valid)
Definition: gxvcommn.c:1316
gxv_BinSrchHeader_validate(FT_Bytes table, FT_Bytes limit, FT_UShort *unitSize_p, FT_UShort *nUnits_p, GXV_Validator valid)
Definition: gxvcommn.c:328
#define GXV_GLYPHOFFSET_FMT(table)
Definition: gxvcommn.h:133
GLboolean GLboolean GLboolean b
png_uint_32 i
Definition: png.h:2640
#define GXV_SET_ERR_IF_PARANOID(err)
Definition: gxvcommn.h:66
GXV_XStateTable_Entry_Validate_Func entry_validate_func
Definition: gxvcommn.h:226
#define FT_TRACE1(varformat)
Definition: ftdebug.h:158
GLenum GLuint GLint GLenum face
GXV_StateTable_Entry_Validate_Func entry_validate_func
Definition: gxvcommn.h:185
#define const
Definition: zconf.h:91
FT_Outline outline
Definition: freetype.h:1631
#define ft_qsort
Definition: ftstdlib.h:121
unsigned char FT_Byte
Definition: fttypes.h:150
#define GXV_LOOKUP_VALUE_LOAD(P, SIGNSPEC)
Definition: gxvcommn.c:383
FT_Load_Glyph(FT_Face face, FT_UInt glyph_index, FT_Int32 load_flags)
Definition: ftobjs.c:574
#define FT_TRACE4(varformat)
Definition: ftdebug.h:161
#define GXV_GLYPHOFFSET_SIZE(table)
Definition: gxvcommn.h:136
GXV_StateTable_ValidatorRec statetable
Definition: gxvcommn.h:254
#define GXV_EXIT
Definition: gxvcommn.h:302
FT_Bytes lookuptbl_head
Definition: gxvcommn.h:249
GXV_StateTable_OptData_Load_Func optdata_load_func
Definition: gxvcommn.h:186
FT_Error error
Definition: cffdrivr.c:411
const GLdouble * v
char FT_String
Definition: fttypes.h:183
GLbitfield flags
gxv_sfntName_validate(FT_UShort name_index, FT_UShort min_index, FT_UShort max_index, GXV_Validator valid)
Definition: gxvcommn.c:885
float min(float a, float b)
Definition: Vector2.hpp:307
GLenum const GLvoid GLbitfield GLuint firstGlyph
#define FT_MAX(a, b)
Definition: ftobjs.h:71
GLuint GLfloat * val
GXV_XStateTable_Subtable_Setup_Func subtable_setup_func
Definition: gxvcommn.h:225
local int root
Definition: enough.c:171
#define GXV_UNITSIZE_VALIDATE(FORMAT, UNITSIZE, NUNITS, CORRECTSIZE)
Definition: gxvcommn.c:402
GXV_XStateTable_ValidatorRec xstatetable
Definition: gxvcommn.h:255
const FT_Byte * FT_Bytes
Definition: fttypes.h:161
GLintptr offset
FT_Get_Sfnt_Name(FT_Face face, FT_UInt idx, FT_SfntName *aname)
GLsizei const GLfloat * value
short n_points
Definition: ftimage.h:386
signed short FT_Short
Definition: fttypes.h:194
gxv_odtect_validate(GXV_odtect_Range odtect, GXV_Validator valid)
Definition: gxvcommn.c:1715
local int max
Definition: enough.c:170
gxv_LookupTable_validate(FT_Bytes table, FT_Bytes limit, GXV_Validator valid)
Definition: gxvcommn.c:755
GLuint const GLchar * name
#define FT_NEXT_USHORT(buffer)
Definition: ftstream.h:226
FT_BEGIN_HEADER struct FT_SfntName_ FT_SfntName
GXV_XStateTable_OptData_Load_Func optdata_load_func
Definition: gxvcommn.h:227
#define FT_INVALID_OFFSET
Definition: ftvalid.h:129
FT_Long num_glyphs
Definition: freetype.h:927
FT_GlyphSlot glyph
Definition: freetype.h:956
unsigned int FT_UInt
Definition: fttypes.h:227
gxv_StateTable_subtable_setup(FT_UShort table_size, FT_UShort classTable, FT_UShort stateArray, FT_UShort entryTable, FT_UShort *classTable_length_p, FT_UShort *stateArray_length_p, FT_UShort *entryTable_length_p, GXV_Validator valid)
Definition: gxvcommn.c:1188
gxv_set_length_by_ushort_offset(FT_UShort *offset, FT_UShort **length, FT_UShort *buff, FT_UInt nmemb, FT_UShort limit, GXV_Validator valid)
Definition: gxvcommn.c:63
FT_ULong subtable_length
Definition: gxvcommn.h:244
gxv_array_getlimits_byte(FT_Bytes table, FT_Bytes limit, FT_Byte *min, FT_Byte *max, GXV_Validator valid)
Definition: gxvcommn.c:181
void(* GXV_XStateTable_Subtable_Setup_Func)(FT_ULong table_size, FT_ULong classTable, FT_ULong stateArray, FT_ULong entryTable, FT_ULong *classTable_length_p, FT_ULong *stateArray_length_p, FT_ULong *entryTable_length_p, GXV_Validator valid)
Definition: gxvcommn.h:198
#define FT_NEXT_ULONG(buffer)
Definition: ftstream.h:238
GXV_Lookup_Fmt4_Transit_Func lookupfmt4_trans
Definition: gxvcommn.h:248
GLenum func
FT_Validator root
Definition: gxvcommn.h:239
FT_Get_Sfnt_Name_Count(FT_Face face)
#define FT_INVALID_DATA
Definition: ftvalid.h:141
#define FT_INVALID_GLYPH_ID
Definition: ftvalid.h:137
#define FT_NEXT_SHORT(buffer)
Definition: ftstream.h:223
void(* GXV_Validate_Func)(FT_Bytes table, FT_Bytes limit, GXV_Validator valid)
Definition: gxvcommn.h:82
#define FT_LOAD_NO_BITMAP
Definition: freetype.h:2552
GXV_Lookup_Value_Validate_Func lookupval_func
Definition: gxvcommn.h:247
GXV_LookupValue_SignSpec lookupval_sign
Definition: gxvcommn.h:246
gxv_odtect_add_range(FT_Bytes start, FT_ULong length, const FT_String *name, GXV_odtect_Range odtect)
Definition: gxvcommn.c:1702
#define FT_LOAD_IGNORE_TRANSFORM
Definition: freetype.h:2559
unsigned short FT_UShort
Definition: fttypes.h:205
GLenum GLsizei GLenum GLenum const GLvoid * table
gxv_StateTable_validate(FT_Bytes table, FT_Bytes limit, GXV_Validator valid)
Definition: gxvcommn.c:1214
#define FT_NEXT_CHAR(buffer)
Definition: ftstream.h:217
gxv_glyphid_validate(FT_UShort gid, GXV_Validator valid)
Definition: gxvcommn.c:813
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
gxv_array_getlimits_ushort(FT_Bytes table, FT_Bytes limit, FT_UShort *min, FT_UShort *max, GXV_Validator valid)
Definition: gxvcommn.c:210
#define GXV_TRACE_HEXDUMP_SFNTNAME(n)
Definition: gxvcommn.h:359
GLint limit
gxv_set_length_by_ulong_offset(FT_ULong *offset, FT_ULong **length, FT_ULong *buff, FT_UInt nmemb, FT_ULong limit, GXV_Validator valid)
Definition: gxvcommn.c:128
#define FT_LOCAL_DEF(x)
Definition: ftconfig.h:236
#define GXV_LIMIT_CHECK(_count)
Definition: gxvcommn.h:272
void(* GXV_StateTable_Subtable_Setup_Func)(FT_UShort table_size, FT_UShort classTable, FT_UShort stateArray, FT_UShort entryTable, FT_UShort *classTable_length_p, FT_UShort *stateArray_length_p, FT_UShort *entryTable_length_p, GXV_Validator valid)
Definition: gxvcommn.h:156