[FREETYPE] Update to v2.9.0 and use this as a chance to slim down our lib a bit....
[reactos.git] / sdk / lib / 3rdparty / freetype / src / gxvalid / gxvjust.c
1 /***************************************************************************/
2 /* */
3 /* gxvjust.c */
4 /* */
5 /* TrueTypeGX/AAT just table validation (body). */
6 /* */
7 /* Copyright 2005-2018 by */
8 /* 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 "gxvalid.h"
29 #include "gxvcommn.h"
30
31 #include FT_SFNT_NAMES_H
32
33
34 /*************************************************************************/
35 /* */
36 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
37 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
38 /* messages during execution. */
39 /* */
40 #undef FT_COMPONENT
41 #define FT_COMPONENT trace_gxvjust
42
43 /*
44 * referred `just' table format specification:
45 * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6just.html
46 * last updated 2000.
47 * ----------------------------------------------
48 * [JUST HEADER]: GXV_JUST_HEADER_SIZE
49 * version (fixed: 32bit) = 0x00010000
50 * format (uint16: 16bit) = 0 is only defined (2000)
51 * horizOffset (uint16: 16bit)
52 * vertOffset (uint16: 16bit)
53 * ----------------------------------------------
54 */
55
56 typedef struct GXV_just_DataRec_
57 {
58 FT_UShort wdc_offset_max;
59 FT_UShort wdc_offset_min;
60 FT_UShort pc_offset_max;
61 FT_UShort pc_offset_min;
62
63 } GXV_just_DataRec, *GXV_just_Data;
64
65
66 #define GXV_JUST_DATA( a ) GXV_TABLE_DATA( just, a )
67
68
69 /* GX just table does not define their subset of GID */
70 static void
71 gxv_just_check_max_gid( FT_UShort gid,
72 const FT_String* msg_tag,
73 GXV_Validator gxvalid )
74 {
75 if ( gid < gxvalid->face->num_glyphs )
76 return;
77
78 GXV_TRACE(( "just table includes too large %s"
79 " GID=%d > %d (in maxp)\n",
80 msg_tag, gid, gxvalid->face->num_glyphs ));
81 GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
82 }
83
84
85 static void
86 gxv_just_wdp_entry_validate( FT_Bytes table,
87 FT_Bytes limit,
88 GXV_Validator gxvalid )
89 {
90 FT_Bytes p = table;
91 FT_ULong justClass;
92 #ifdef GXV_LOAD_UNUSED_VARS
93 FT_Fixed beforeGrowLimit;
94 FT_Fixed beforeShrinkGrowLimit;
95 FT_Fixed afterGrowLimit;
96 FT_Fixed afterShrinkGrowLimit;
97 FT_UShort growFlags;
98 FT_UShort shrinkFlags;
99 #endif
100
101
102 GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 + 4 + 2 + 2 );
103 justClass = FT_NEXT_ULONG( p );
104 #ifndef GXV_LOAD_UNUSED_VARS
105 p += 4 + 4 + 4 + 4 + 2 + 2;
106 #else
107 beforeGrowLimit = FT_NEXT_ULONG( p );
108 beforeShrinkGrowLimit = FT_NEXT_ULONG( p );
109 afterGrowLimit = FT_NEXT_ULONG( p );
110 afterShrinkGrowLimit = FT_NEXT_ULONG( p );
111 growFlags = FT_NEXT_USHORT( p );
112 shrinkFlags = FT_NEXT_USHORT( p );
113 #endif
114
115 /* According to Apple spec, only 7bits in justClass is used */
116 if ( ( justClass & 0xFFFFFF80UL ) != 0 )
117 {
118 GXV_TRACE(( "just table includes non-zero value"
119 " in unused justClass higher bits"
120 " of WidthDeltaPair" ));
121 GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
122 }
123
124 gxvalid->subtable_length = (FT_ULong)( p - table );
125 }
126
127
128 static void
129 gxv_just_wdc_entry_validate( FT_Bytes table,
130 FT_Bytes limit,
131 GXV_Validator gxvalid )
132 {
133 FT_Bytes p = table;
134 FT_ULong count, i;
135
136
137 GXV_LIMIT_CHECK( 4 );
138 count = FT_NEXT_ULONG( p );
139 for ( i = 0; i < count; i++ )
140 {
141 GXV_TRACE(( "validating wdc pair %d/%d\n", i + 1, count ));
142 gxv_just_wdp_entry_validate( p, limit, gxvalid );
143 p += gxvalid->subtable_length;
144 }
145
146 gxvalid->subtable_length = (FT_ULong)( p - table );
147 }
148
149
150 static void
151 gxv_just_widthDeltaClusters_validate( FT_Bytes table,
152 FT_Bytes limit,
153 GXV_Validator gxvalid )
154 {
155 FT_Bytes p = table;
156 FT_Bytes wdc_end = table + GXV_JUST_DATA( wdc_offset_max );
157 FT_UInt i;
158
159
160 GXV_NAME_ENTER( "just justDeltaClusters" );
161
162 if ( limit <= wdc_end )
163 FT_INVALID_OFFSET;
164
165 for ( i = 0; p <= wdc_end; i++ )
166 {
167 gxv_just_wdc_entry_validate( p, limit, gxvalid );
168 p += gxvalid->subtable_length;
169 }
170
171 gxvalid->subtable_length = (FT_ULong)( p - table );
172
173 GXV_EXIT;
174 }
175
176
177 static void
178 gxv_just_actSubrecord_type0_validate( FT_Bytes table,
179 FT_Bytes limit,
180 GXV_Validator gxvalid )
181 {
182 FT_Bytes p = table;
183
184 FT_Fixed lowerLimit;
185 FT_Fixed upperLimit;
186 #ifdef GXV_LOAD_UNUSED_VARS
187 FT_UShort order;
188 #endif
189 FT_UShort decomposedCount;
190
191 FT_UInt i;
192
193
194 GXV_LIMIT_CHECK( 4 + 4 + 2 + 2 );
195 lowerLimit = FT_NEXT_LONG( p );
196 upperLimit = FT_NEXT_LONG( p );
197 #ifdef GXV_LOAD_UNUSED_VARS
198 order = FT_NEXT_USHORT( p );
199 #else
200 p += 2;
201 #endif
202 decomposedCount = FT_NEXT_USHORT( p );
203
204 if ( lowerLimit >= upperLimit )
205 {
206 GXV_TRACE(( "just table includes invalid range spec:"
207 " lowerLimit(%d) > upperLimit(%d)\n" ));
208 GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
209 }
210
211 for ( i = 0; i < decomposedCount; i++ )
212 {
213 FT_UShort glyphs;
214
215
216 GXV_LIMIT_CHECK( 2 );
217 glyphs = FT_NEXT_USHORT( p );
218 gxv_just_check_max_gid( glyphs, "type0:glyphs", gxvalid );
219 }
220
221 gxvalid->subtable_length = (FT_ULong)( p - table );
222 }
223
224
225 static void
226 gxv_just_actSubrecord_type1_validate( FT_Bytes table,
227 FT_Bytes limit,
228 GXV_Validator gxvalid )
229 {
230 FT_Bytes p = table;
231 FT_UShort addGlyph;
232
233
234 GXV_LIMIT_CHECK( 2 );
235 addGlyph = FT_NEXT_USHORT( p );
236
237 gxv_just_check_max_gid( addGlyph, "type1:addGlyph", gxvalid );
238
239 gxvalid->subtable_length = (FT_ULong)( p - table );
240 }
241
242
243 static void
244 gxv_just_actSubrecord_type2_validate( FT_Bytes table,
245 FT_Bytes limit,
246 GXV_Validator gxvalid )
247 {
248 FT_Bytes p = table;
249 #ifdef GXV_LOAD_UNUSED_VARS
250 FT_Fixed substThreshhold; /* Apple misspelled "Threshhold" */
251 #endif
252 FT_UShort addGlyph;
253 FT_UShort substGlyph;
254
255
256 GXV_LIMIT_CHECK( 4 + 2 + 2 );
257 #ifdef GXV_LOAD_UNUSED_VARS
258 substThreshhold = FT_NEXT_ULONG( p );
259 #else
260 p += 4;
261 #endif
262 addGlyph = FT_NEXT_USHORT( p );
263 substGlyph = FT_NEXT_USHORT( p );
264
265 if ( addGlyph != 0xFFFF )
266 gxv_just_check_max_gid( addGlyph, "type2:addGlyph", gxvalid );
267
268 gxv_just_check_max_gid( substGlyph, "type2:substGlyph", gxvalid );
269
270 gxvalid->subtable_length = (FT_ULong)( p - table );
271 }
272
273
274 static void
275 gxv_just_actSubrecord_type4_validate( FT_Bytes table,
276 FT_Bytes limit,
277 GXV_Validator gxvalid )
278 {
279 FT_Bytes p = table;
280 FT_ULong variantsAxis;
281 FT_Fixed minimumLimit;
282 FT_Fixed noStretchValue;
283 FT_Fixed maximumLimit;
284
285
286 GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 );
287 variantsAxis = FT_NEXT_ULONG( p );
288 minimumLimit = FT_NEXT_LONG( p );
289 noStretchValue = FT_NEXT_LONG( p );
290 maximumLimit = FT_NEXT_LONG( p );
291
292 gxvalid->subtable_length = (FT_ULong)( p - table );
293
294 if ( variantsAxis != 0x64756374L ) /* 'duct' */
295 GXV_TRACE(( "variantsAxis 0x%08x is non default value",
296 variantsAxis ));
297
298 if ( minimumLimit > noStretchValue )
299 GXV_TRACE(( "type4:minimumLimit 0x%08x > noStretchValue 0x%08x\n",
300 minimumLimit, noStretchValue ));
301 else if ( noStretchValue > maximumLimit )
302 GXV_TRACE(( "type4:noStretchValue 0x%08x > maximumLimit 0x%08x\n",
303 noStretchValue, maximumLimit ));
304 else if ( !IS_PARANOID_VALIDATION )
305 return;
306
307 FT_INVALID_DATA;
308 }
309
310
311 static void
312 gxv_just_actSubrecord_type5_validate( FT_Bytes table,
313 FT_Bytes limit,
314 GXV_Validator gxvalid )
315 {
316 FT_Bytes p = table;
317 FT_UShort flags;
318 FT_UShort glyph;
319
320
321 GXV_LIMIT_CHECK( 2 + 2 );
322 flags = FT_NEXT_USHORT( p );
323 glyph = FT_NEXT_USHORT( p );
324
325 if ( flags )
326 GXV_TRACE(( "type5: nonzero value 0x%04x in unused flags\n",
327 flags ));
328 gxv_just_check_max_gid( glyph, "type5:glyph", gxvalid );
329
330 gxvalid->subtable_length = (FT_ULong)( p - table );
331 }
332
333
334 /* parse single actSubrecord */
335 static void
336 gxv_just_actSubrecord_validate( FT_Bytes table,
337 FT_Bytes limit,
338 GXV_Validator gxvalid )
339 {
340 FT_Bytes p = table;
341 FT_UShort actionClass;
342 FT_UShort actionType;
343 FT_ULong actionLength;
344
345
346 GXV_NAME_ENTER( "just actSubrecord" );
347
348 GXV_LIMIT_CHECK( 2 + 2 + 4 );
349 actionClass = FT_NEXT_USHORT( p );
350 actionType = FT_NEXT_USHORT( p );
351 actionLength = FT_NEXT_ULONG( p );
352
353 /* actionClass is related with justClass using 7bit only */
354 if ( ( actionClass & 0xFF80 ) != 0 )
355 GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
356
357 if ( actionType == 0 )
358 gxv_just_actSubrecord_type0_validate( p, limit, gxvalid );
359 else if ( actionType == 1 )
360 gxv_just_actSubrecord_type1_validate( p, limit, gxvalid );
361 else if ( actionType == 2 )
362 gxv_just_actSubrecord_type2_validate( p, limit, gxvalid );
363 else if ( actionType == 3 )
364 ; /* Stretch glyph action: no actionData */
365 else if ( actionType == 4 )
366 gxv_just_actSubrecord_type4_validate( p, limit, gxvalid );
367 else if ( actionType == 5 )
368 gxv_just_actSubrecord_type5_validate( p, limit, gxvalid );
369 else
370 FT_INVALID_DATA;
371
372 gxvalid->subtable_length = actionLength;
373
374 GXV_EXIT;
375 }
376
377
378 static void
379 gxv_just_pcActionRecord_validate( FT_Bytes table,
380 FT_Bytes limit,
381 GXV_Validator gxvalid )
382 {
383 FT_Bytes p = table;
384 FT_ULong actionCount;
385 FT_ULong i;
386
387
388 GXV_LIMIT_CHECK( 4 );
389 actionCount = FT_NEXT_ULONG( p );
390 GXV_TRACE(( "actionCount = %d\n", actionCount ));
391
392 for ( i = 0; i < actionCount; i++ )
393 {
394 gxv_just_actSubrecord_validate( p, limit, gxvalid );
395 p += gxvalid->subtable_length;
396 }
397
398 gxvalid->subtable_length = (FT_ULong)( p - table );
399
400 GXV_EXIT;
401 }
402
403
404 static void
405 gxv_just_pcTable_LookupValue_entry_validate( FT_UShort glyph,
406 GXV_LookupValueCPtr value_p,
407 GXV_Validator gxvalid )
408 {
409 FT_UNUSED( glyph );
410
411 if ( value_p->u > GXV_JUST_DATA( pc_offset_max ) )
412 GXV_JUST_DATA( pc_offset_max ) = value_p->u;
413 if ( value_p->u < GXV_JUST_DATA( pc_offset_max ) )
414 GXV_JUST_DATA( pc_offset_min ) = value_p->u;
415 }
416
417
418 static void
419 gxv_just_pcLookupTable_validate( FT_Bytes table,
420 FT_Bytes limit,
421 GXV_Validator gxvalid )
422 {
423 FT_Bytes p = table;
424
425
426 GXV_NAME_ENTER( "just pcLookupTable" );
427 GXV_JUST_DATA( pc_offset_max ) = 0x0000;
428 GXV_JUST_DATA( pc_offset_min ) = 0xFFFFU;
429
430 gxvalid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
431 gxvalid->lookupval_func = gxv_just_pcTable_LookupValue_entry_validate;
432
433 gxv_LookupTable_validate( p, limit, gxvalid );
434
435 /* subtable_length is set by gxv_LookupTable_validate() */
436
437 GXV_EXIT;
438 }
439
440
441 static void
442 gxv_just_postcompTable_validate( FT_Bytes table,
443 FT_Bytes limit,
444 GXV_Validator gxvalid )
445 {
446 FT_Bytes p = table;
447
448
449 GXV_NAME_ENTER( "just postcompTable" );
450
451 gxv_just_pcLookupTable_validate( p, limit, gxvalid );
452 p += gxvalid->subtable_length;
453
454 gxv_just_pcActionRecord_validate( p, limit, gxvalid );
455 p += gxvalid->subtable_length;
456
457 gxvalid->subtable_length = (FT_ULong)( p - table );
458
459 GXV_EXIT;
460 }
461
462
463 static void
464 gxv_just_classTable_entry_validate(
465 FT_Byte state,
466 FT_UShort flags,
467 GXV_StateTable_GlyphOffsetCPtr glyphOffset_p,
468 FT_Bytes table,
469 FT_Bytes limit,
470 GXV_Validator gxvalid )
471 {
472 #ifdef GXV_LOAD_UNUSED_VARS
473 /* TODO: validate markClass & currentClass */
474 FT_UShort setMark;
475 FT_UShort dontAdvance;
476 FT_UShort markClass;
477 FT_UShort currentClass;
478 #endif
479
480 FT_UNUSED( state );
481 FT_UNUSED( glyphOffset_p );
482 FT_UNUSED( table );
483 FT_UNUSED( limit );
484 FT_UNUSED( gxvalid );
485
486 #ifndef GXV_LOAD_UNUSED_VARS
487 FT_UNUSED( flags );
488 #else
489 setMark = (FT_UShort)( ( flags >> 15 ) & 1 );
490 dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
491 markClass = (FT_UShort)( ( flags >> 7 ) & 0x7F );
492 currentClass = (FT_UShort)( flags & 0x7F );
493 #endif
494 }
495
496
497 static void
498 gxv_just_justClassTable_validate ( FT_Bytes table,
499 FT_Bytes limit,
500 GXV_Validator gxvalid )
501 {
502 FT_Bytes p = table;
503 FT_UShort length;
504 FT_UShort coverage;
505 FT_ULong subFeatureFlags;
506
507
508 GXV_NAME_ENTER( "just justClassTable" );
509
510 GXV_LIMIT_CHECK( 2 + 2 + 4 );
511 length = FT_NEXT_USHORT( p );
512 coverage = FT_NEXT_USHORT( p );
513 subFeatureFlags = FT_NEXT_ULONG( p );
514
515 GXV_TRACE(( " justClassTable: coverage = 0x%04x (%s) ", coverage ));
516 if ( ( coverage & 0x4000 ) == 0 )
517 GXV_TRACE(( "ascending\n" ));
518 else
519 GXV_TRACE(( "descending\n" ));
520
521 if ( subFeatureFlags )
522 GXV_TRACE(( " justClassTable: nonzero value (0x%08x)"
523 " in unused subFeatureFlags\n", subFeatureFlags ));
524
525 gxvalid->statetable.optdata = NULL;
526 gxvalid->statetable.optdata_load_func = NULL;
527 gxvalid->statetable.subtable_setup_func = NULL;
528 gxvalid->statetable.entry_glyphoffset_fmt = GXV_GLYPHOFFSET_NONE;
529 gxvalid->statetable.entry_validate_func =
530 gxv_just_classTable_entry_validate;
531
532 gxv_StateTable_validate( p, table + length, gxvalid );
533
534 /* subtable_length is set by gxv_LookupTable_validate() */
535
536 GXV_EXIT;
537 }
538
539
540 static void
541 gxv_just_wdcTable_LookupValue_validate( FT_UShort glyph,
542 GXV_LookupValueCPtr value_p,
543 GXV_Validator gxvalid )
544 {
545 FT_UNUSED( glyph );
546
547 if ( value_p->u > GXV_JUST_DATA( wdc_offset_max ) )
548 GXV_JUST_DATA( wdc_offset_max ) = value_p->u;
549 if ( value_p->u < GXV_JUST_DATA( wdc_offset_min ) )
550 GXV_JUST_DATA( wdc_offset_min ) = value_p->u;
551 }
552
553
554 static void
555 gxv_just_justData_lookuptable_validate( FT_Bytes table,
556 FT_Bytes limit,
557 GXV_Validator gxvalid )
558 {
559 FT_Bytes p = table;
560
561
562 GXV_JUST_DATA( wdc_offset_max ) = 0x0000;
563 GXV_JUST_DATA( wdc_offset_min ) = 0xFFFFU;
564
565 gxvalid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
566 gxvalid->lookupval_func = gxv_just_wdcTable_LookupValue_validate;
567
568 gxv_LookupTable_validate( p, limit, gxvalid );
569
570 /* subtable_length is set by gxv_LookupTable_validate() */
571
572 GXV_EXIT;
573 }
574
575
576 /*
577 * gxv_just_justData_validate() parses and validates horizData, vertData.
578 */
579 static void
580 gxv_just_justData_validate( FT_Bytes table,
581 FT_Bytes limit,
582 GXV_Validator gxvalid )
583 {
584 /*
585 * following 3 offsets are measured from the start of `just'
586 * (which table points to), not justData
587 */
588 FT_UShort justClassTableOffset;
589 FT_UShort wdcTableOffset;
590 FT_UShort pcTableOffset;
591 FT_Bytes p = table;
592
593 GXV_ODTECT( 4, odtect );
594
595
596 GXV_NAME_ENTER( "just justData" );
597
598 GXV_ODTECT_INIT( odtect );
599 GXV_LIMIT_CHECK( 2 + 2 + 2 );
600 justClassTableOffset = FT_NEXT_USHORT( p );
601 wdcTableOffset = FT_NEXT_USHORT( p );
602 pcTableOffset = FT_NEXT_USHORT( p );
603
604 GXV_TRACE(( " (justClassTableOffset = 0x%04x)\n", justClassTableOffset ));
605 GXV_TRACE(( " (wdcTableOffset = 0x%04x)\n", wdcTableOffset ));
606 GXV_TRACE(( " (pcTableOffset = 0x%04x)\n", pcTableOffset ));
607
608 gxv_just_justData_lookuptable_validate( p, limit, gxvalid );
609 gxv_odtect_add_range( p, gxvalid->subtable_length,
610 "just_LookupTable", odtect );
611
612 if ( wdcTableOffset )
613 {
614 gxv_just_widthDeltaClusters_validate(
615 gxvalid->root->base + wdcTableOffset, limit, gxvalid );
616 gxv_odtect_add_range( gxvalid->root->base + wdcTableOffset,
617 gxvalid->subtable_length, "just_wdcTable", odtect );
618 }
619
620 if ( pcTableOffset )
621 {
622 gxv_just_postcompTable_validate( gxvalid->root->base + pcTableOffset,
623 limit, gxvalid );
624 gxv_odtect_add_range( gxvalid->root->base + pcTableOffset,
625 gxvalid->subtable_length, "just_pcTable", odtect );
626 }
627
628 if ( justClassTableOffset )
629 {
630 gxv_just_justClassTable_validate(
631 gxvalid->root->base + justClassTableOffset, limit, gxvalid );
632 gxv_odtect_add_range( gxvalid->root->base + justClassTableOffset,
633 gxvalid->subtable_length, "just_justClassTable",
634 odtect );
635 }
636
637 gxv_odtect_validate( odtect, gxvalid );
638
639 GXV_EXIT;
640 }
641
642
643 FT_LOCAL_DEF( void )
644 gxv_just_validate( FT_Bytes table,
645 FT_Face face,
646 FT_Validator ftvalid )
647 {
648 FT_Bytes p = table;
649 FT_Bytes limit = 0;
650
651 GXV_ValidatorRec gxvalidrec;
652 GXV_Validator gxvalid = &gxvalidrec;
653 GXV_just_DataRec justrec;
654 GXV_just_Data just = &justrec;
655
656 FT_ULong version;
657 FT_UShort format;
658 FT_UShort horizOffset;
659 FT_UShort vertOffset;
660
661 GXV_ODTECT( 3, odtect );
662
663
664 GXV_ODTECT_INIT( odtect );
665
666 gxvalid->root = ftvalid;
667 gxvalid->table_data = just;
668 gxvalid->face = face;
669
670 FT_TRACE3(( "validating `just' table\n" ));
671 GXV_INIT;
672
673 limit = gxvalid->root->limit;
674
675 GXV_LIMIT_CHECK( 4 + 2 + 2 + 2 );
676 version = FT_NEXT_ULONG( p );
677 format = FT_NEXT_USHORT( p );
678 horizOffset = FT_NEXT_USHORT( p );
679 vertOffset = FT_NEXT_USHORT( p );
680 gxv_odtect_add_range( table, (FT_ULong)( p - table ),
681 "just header", odtect );
682
683
684 /* Version 1.0 (always:2000) */
685 GXV_TRACE(( " (version = 0x%08x)\n", version ));
686 if ( version != 0x00010000UL )
687 FT_INVALID_FORMAT;
688
689 /* format 0 (always:2000) */
690 GXV_TRACE(( " (format = 0x%04x)\n", format ));
691 if ( format != 0x0000 )
692 FT_INVALID_FORMAT;
693
694 GXV_TRACE(( " (horizOffset = %d)\n", horizOffset ));
695 GXV_TRACE(( " (vertOffset = %d)\n", vertOffset ));
696
697
698 /* validate justData */
699 if ( 0 < horizOffset )
700 {
701 gxv_just_justData_validate( table + horizOffset, limit, gxvalid );
702 gxv_odtect_add_range( table + horizOffset, gxvalid->subtable_length,
703 "horizJustData", odtect );
704 }
705
706 if ( 0 < vertOffset )
707 {
708 gxv_just_justData_validate( table + vertOffset, limit, gxvalid );
709 gxv_odtect_add_range( table + vertOffset, gxvalid->subtable_length,
710 "vertJustData", odtect );
711 }
712
713 gxv_odtect_validate( odtect, gxvalid );
714
715 FT_TRACE4(( "\n" ));
716 }
717
718
719 /* END */