mgh: fix for default HDD DMA mode, that wasn't correctly set
[open-ps2-loader.git] / thirdparty / freetype-2.3.12 / src / gxvalid / gxvkern.c
blob2137db842a41e77298782919ce48deab3d12e647
1 /***************************************************************************/
2 /* */
3 /* gxvkern.c */
4 /* */
5 /* TrueTypeGX/AAT kern table validation (body). */
6 /* */
7 /* Copyright 2004, 2005, 2006, 2007 */
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 /***************************************************************************/
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 /***************************************************************************/
28 #include "gxvalid.h"
29 #include "gxvcommn.h"
31 #include FT_SFNT_NAMES_H
32 #include FT_SERVICE_GX_VALIDATE_H
35 /*************************************************************************/
36 /* */
37 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
38 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
39 /* messages during execution. */
40 /* */
41 #undef FT_COMPONENT
42 #define FT_COMPONENT trace_gxvkern
45 /*************************************************************************/
46 /*************************************************************************/
47 /***** *****/
48 /***** Data and Types *****/
49 /***** *****/
50 /*************************************************************************/
51 /*************************************************************************/
53 typedef enum GXV_kern_Version_
55 KERN_VERSION_CLASSIC = 0x0000,
56 KERN_VERSION_NEW = 0x0001
58 } GXV_kern_Version;
61 typedef enum GXV_kern_Dialect_
63 KERN_DIALECT_UNKNOWN = 0,
64 KERN_DIALECT_MS = FT_VALIDATE_MS,
65 KERN_DIALECT_APPLE = FT_VALIDATE_APPLE,
66 KERN_DIALECT_ANY = FT_VALIDATE_CKERN
68 } GXV_kern_Dialect;
71 typedef struct GXV_kern_DataRec_
73 GXV_kern_Version version;
74 void *subtable_data;
75 GXV_kern_Dialect dialect_request;
77 } GXV_kern_DataRec, *GXV_kern_Data;
80 #define GXV_KERN_DATA( field ) GXV_TABLE_DATA( kern, field )
82 #define KERN_IS_CLASSIC( valid ) \
83 ( KERN_VERSION_CLASSIC == GXV_KERN_DATA( version ) )
84 #define KERN_IS_NEW( valid ) \
85 ( KERN_VERSION_NEW == GXV_KERN_DATA( version ) )
87 #define KERN_DIALECT( valid ) \
88 GXV_KERN_DATA( dialect_request )
89 #define KERN_ALLOWS_MS( valid ) \
90 ( KERN_DIALECT( valid ) & KERN_DIALECT_MS )
91 #define KERN_ALLOWS_APPLE( valid ) \
92 ( KERN_DIALECT( valid ) & KERN_DIALECT_APPLE )
94 #define GXV_KERN_HEADER_SIZE ( KERN_IS_NEW( valid ) ? 8 : 4 )
95 #define GXV_KERN_SUBTABLE_HEADER_SIZE ( KERN_IS_NEW( valid ) ? 8 : 6 )
98 /*************************************************************************/
99 /*************************************************************************/
100 /***** *****/
101 /***** SUBTABLE VALIDATORS *****/
102 /***** *****/
103 /*************************************************************************/
104 /*************************************************************************/
107 /* ============================= format 0 ============================== */
109 static void
110 gxv_kern_subtable_fmt0_pairs_validate( FT_Bytes table,
111 FT_Bytes limit,
112 FT_UShort nPairs,
113 GXV_Validator valid )
115 FT_Bytes p = table;
116 FT_UShort i;
118 FT_UShort last_gid_left = 0;
119 FT_UShort last_gid_right = 0;
121 FT_UNUSED( limit );
124 GXV_NAME_ENTER( "kern format 0 pairs" );
126 for ( i = 0; i < nPairs; i++ )
128 FT_UShort gid_left;
129 FT_UShort gid_right;
130 FT_Short kernValue;
133 /* left */
134 gid_left = FT_NEXT_USHORT( p );
135 gxv_glyphid_validate( gid_left, valid );
137 /* right */
138 gid_right = FT_NEXT_USHORT( p );
139 gxv_glyphid_validate( gid_right, valid );
141 /* Pairs of left and right GIDs must be unique and sorted. */
142 GXV_TRACE(( "left gid = %u, right gid = %u\n", gid_left, gid_right ));
143 if ( gid_left == last_gid_left )
145 if ( last_gid_right < gid_right )
146 last_gid_right = gid_right;
147 else
148 FT_INVALID_DATA;
150 else if ( last_gid_left < gid_left )
152 last_gid_left = gid_left;
153 last_gid_right = gid_right;
155 else
156 FT_INVALID_DATA;
158 /* skip the kern value */
159 kernValue = FT_NEXT_SHORT( p );
162 GXV_EXIT;
165 static void
166 gxv_kern_subtable_fmt0_validate( FT_Bytes table,
167 FT_Bytes limit,
168 GXV_Validator valid )
170 FT_Bytes p = table + GXV_KERN_SUBTABLE_HEADER_SIZE;
172 FT_UShort nPairs;
173 FT_UShort unitSize;
176 GXV_NAME_ENTER( "kern subtable format 0" );
178 unitSize = 2 + 2 + 2;
179 nPairs = 0;
181 /* nPairs, searchRange, entrySelector, rangeShift */
182 GXV_LIMIT_CHECK( 2 + 2 + 2 + 2 );
183 gxv_BinSrchHeader_validate( p, limit, &unitSize, &nPairs, valid );
184 p += 2 + 2 + 2 + 2;
186 gxv_kern_subtable_fmt0_pairs_validate( p, limit, nPairs, valid );
188 GXV_EXIT;
192 /* ============================= format 1 ============================== */
195 typedef struct GXV_kern_fmt1_StateOptRec_
197 FT_UShort valueTable;
198 FT_UShort valueTable_length;
200 } GXV_kern_fmt1_StateOptRec, *GXV_kern_fmt1_StateOptRecData;
203 static void
204 gxv_kern_subtable_fmt1_valueTable_load( FT_Bytes table,
205 FT_Bytes limit,
206 GXV_Validator valid )
208 FT_Bytes p = table;
209 GXV_kern_fmt1_StateOptRecData optdata =
210 (GXV_kern_fmt1_StateOptRecData)valid->statetable.optdata;
213 GXV_LIMIT_CHECK( 2 );
214 optdata->valueTable = FT_NEXT_USHORT( p );
219 * passed tables_size covers whole StateTable, including kern fmt1 header
221 static void
222 gxv_kern_subtable_fmt1_subtable_setup( FT_UShort table_size,
223 FT_UShort classTable,
224 FT_UShort stateArray,
225 FT_UShort entryTable,
226 FT_UShort* classTable_length_p,
227 FT_UShort* stateArray_length_p,
228 FT_UShort* entryTable_length_p,
229 GXV_Validator valid )
231 FT_UShort o[4];
232 FT_UShort *l[4];
233 FT_UShort buff[5];
235 GXV_kern_fmt1_StateOptRecData optdata =
236 (GXV_kern_fmt1_StateOptRecData)valid->statetable.optdata;
239 o[0] = classTable;
240 o[1] = stateArray;
241 o[2] = entryTable;
242 o[3] = optdata->valueTable;
243 l[0] = classTable_length_p;
244 l[1] = stateArray_length_p;
245 l[2] = entryTable_length_p;
246 l[3] = &(optdata->valueTable_length);
248 gxv_set_length_by_ushort_offset( o, l, buff, 4, table_size, valid );
253 * passed table & limit are of whole StateTable, not including subtables
255 static void
256 gxv_kern_subtable_fmt1_entry_validate(
257 FT_Byte state,
258 FT_UShort flags,
259 GXV_StateTable_GlyphOffsetCPtr glyphOffset_p,
260 FT_Bytes table,
261 FT_Bytes limit,
262 GXV_Validator valid )
264 FT_UShort push;
265 FT_UShort dontAdvance;
266 FT_UShort valueOffset;
267 FT_UShort kernAction;
268 FT_UShort kernValue;
270 FT_UNUSED( state );
271 FT_UNUSED( glyphOffset_p );
274 push = (FT_UShort)( ( flags >> 15 ) & 1 );
275 dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
276 valueOffset = (FT_UShort)( flags & 0x3FFF );
279 GXV_kern_fmt1_StateOptRecData vt_rec =
280 (GXV_kern_fmt1_StateOptRecData)valid->statetable.optdata;
281 FT_Bytes p;
284 if ( valueOffset < vt_rec->valueTable )
285 FT_INVALID_OFFSET;
287 p = table + valueOffset;
288 limit = table + vt_rec->valueTable + vt_rec->valueTable_length;
290 GXV_LIMIT_CHECK( 2 + 2 );
291 kernAction = FT_NEXT_USHORT( p );
292 kernValue = FT_NEXT_USHORT( p );
297 static void
298 gxv_kern_subtable_fmt1_validate( FT_Bytes table,
299 FT_Bytes limit,
300 GXV_Validator valid )
302 FT_Bytes p = table;
303 GXV_kern_fmt1_StateOptRec vt_rec;
306 GXV_NAME_ENTER( "kern subtable format 1" );
308 valid->statetable.optdata =
309 &vt_rec;
310 valid->statetable.optdata_load_func =
311 gxv_kern_subtable_fmt1_valueTable_load;
312 valid->statetable.subtable_setup_func =
313 gxv_kern_subtable_fmt1_subtable_setup;
314 valid->statetable.entry_glyphoffset_fmt =
315 GXV_GLYPHOFFSET_NONE;
316 valid->statetable.entry_validate_func =
317 gxv_kern_subtable_fmt1_entry_validate;
319 gxv_StateTable_validate( p, limit, valid );
321 GXV_EXIT;
325 /* ================ Data for Class-Based Subtables 2, 3 ================ */
327 typedef enum GXV_kern_ClassSpec_
329 GXV_KERN_CLS_L = 0,
330 GXV_KERN_CLS_R
332 } GXV_kern_ClassSpec;
335 /* ============================= format 2 ============================== */
337 /* ---------------------- format 2 specific data ----------------------- */
339 typedef struct GXV_kern_subtable_fmt2_DataRec_
341 FT_UShort rowWidth;
342 FT_UShort array;
343 FT_UShort offset_min[2];
344 FT_UShort offset_max[2];
345 const FT_String* class_tag[2];
346 GXV_odtect_Range odtect;
348 } GXV_kern_subtable_fmt2_DataRec, *GXV_kern_subtable_fmt2_Data;
351 #define GXV_KERN_FMT2_DATA( field ) \
352 ( ( (GXV_kern_subtable_fmt2_DataRec *) \
353 ( GXV_KERN_DATA( subtable_data ) ) )->field )
356 /* -------------------------- utility functions ----------------------- */
358 static void
359 gxv_kern_subtable_fmt2_clstbl_validate( FT_Bytes table,
360 FT_Bytes limit,
361 GXV_kern_ClassSpec spec,
362 GXV_Validator valid )
364 const FT_String* tag = GXV_KERN_FMT2_DATA( class_tag[spec] );
365 GXV_odtect_Range odtect = GXV_KERN_FMT2_DATA( odtect );
367 FT_Bytes p = table;
368 FT_UShort firstGlyph;
369 FT_UShort nGlyphs;
372 GXV_NAME_ENTER( "kern format 2 classTable" );
374 GXV_LIMIT_CHECK( 2 + 2 );
375 firstGlyph = FT_NEXT_USHORT( p );
376 nGlyphs = FT_NEXT_USHORT( p );
377 GXV_TRACE(( " %s firstGlyph=%d, nGlyphs=%d\n",
378 tag, firstGlyph, nGlyphs ));
380 gxv_glyphid_validate( firstGlyph, valid );
381 gxv_glyphid_validate( (FT_UShort)( firstGlyph + nGlyphs - 1 ), valid );
383 gxv_array_getlimits_ushort( p, p + ( 2 * nGlyphs ),
384 &( GXV_KERN_FMT2_DATA( offset_min[spec] ) ),
385 &( GXV_KERN_FMT2_DATA( offset_max[spec] ) ),
386 valid );
388 gxv_odtect_add_range( table, 2 * nGlyphs, tag, odtect );
390 GXV_EXIT;
394 static void
395 gxv_kern_subtable_fmt2_validate( FT_Bytes table,
396 FT_Bytes limit,
397 GXV_Validator valid )
399 GXV_ODTECT( 3, odtect );
400 GXV_kern_subtable_fmt2_DataRec fmt2_rec =
401 { 0, 0, { 0, 0 }, { 0, 0 }, { "leftClass", "rightClass" }, NULL };
403 FT_Bytes p = table + GXV_KERN_SUBTABLE_HEADER_SIZE;
404 FT_UShort leftOffsetTable;
405 FT_UShort rightOffsetTable;
408 GXV_NAME_ENTER( "kern subtable format 2" );
410 GXV_ODTECT_INIT( odtect );
411 fmt2_rec.odtect = odtect;
412 GXV_KERN_DATA( subtable_data ) = &fmt2_rec;
414 GXV_LIMIT_CHECK( 2 + 2 + 2 + 2 );
415 GXV_KERN_FMT2_DATA( rowWidth ) = FT_NEXT_USHORT( p );
416 leftOffsetTable = FT_NEXT_USHORT( p );
417 rightOffsetTable = FT_NEXT_USHORT( p );
418 GXV_KERN_FMT2_DATA( array ) = FT_NEXT_USHORT( p );
420 GXV_TRACE(( "rowWidth = %d\n", GXV_KERN_FMT2_DATA( rowWidth ) ));
423 GXV_LIMIT_CHECK( leftOffsetTable );
424 GXV_LIMIT_CHECK( rightOffsetTable );
425 GXV_LIMIT_CHECK( GXV_KERN_FMT2_DATA( array ) );
427 gxv_kern_subtable_fmt2_clstbl_validate( table + leftOffsetTable, limit,
428 GXV_KERN_CLS_L, valid );
430 gxv_kern_subtable_fmt2_clstbl_validate( table + rightOffsetTable, limit,
431 GXV_KERN_CLS_R, valid );
433 if ( GXV_KERN_FMT2_DATA( offset_min[GXV_KERN_CLS_L] ) +
434 GXV_KERN_FMT2_DATA( offset_min[GXV_KERN_CLS_R] )
435 < GXV_KERN_FMT2_DATA( array ) )
436 FT_INVALID_OFFSET;
438 gxv_odtect_add_range( table + GXV_KERN_FMT2_DATA( array ),
439 GXV_KERN_FMT2_DATA( offset_max[GXV_KERN_CLS_L] )
440 + GXV_KERN_FMT2_DATA( offset_max[GXV_KERN_CLS_R] )
441 - GXV_KERN_FMT2_DATA( array ),
442 "array", odtect );
444 gxv_odtect_validate( odtect, valid );
446 GXV_EXIT;
450 /* ============================= format 3 ============================== */
452 static void
453 gxv_kern_subtable_fmt3_validate( FT_Bytes table,
454 FT_Bytes limit,
455 GXV_Validator valid )
457 FT_Bytes p = table + GXV_KERN_SUBTABLE_HEADER_SIZE;
458 FT_UShort glyphCount;
459 FT_Byte kernValueCount;
460 FT_Byte leftClassCount;
461 FT_Byte rightClassCount;
462 FT_Byte flags;
465 GXV_NAME_ENTER( "kern subtable format 3" );
467 GXV_LIMIT_CHECK( 2 + 1 + 1 + 1 + 1 );
468 glyphCount = FT_NEXT_USHORT( p );
469 kernValueCount = FT_NEXT_BYTE( p );
470 leftClassCount = FT_NEXT_BYTE( p );
471 rightClassCount = FT_NEXT_BYTE( p );
472 flags = FT_NEXT_BYTE( p );
474 if ( valid->face->num_glyphs != glyphCount )
476 GXV_TRACE(( "maxGID=%d, but glyphCount=%d\n",
477 valid->face->num_glyphs, glyphCount ));
478 if ( valid->root->level >= FT_VALIDATE_PARANOID )
479 FT_INVALID_GLYPH_ID;
483 * just skip kernValue[kernValueCount]
485 GXV_LIMIT_CHECK( 2 * kernValueCount );
486 p += 2 * kernValueCount;
489 * check leftClass[gid] < leftClassCount
492 FT_Byte min, max;
495 GXV_LIMIT_CHECK( glyphCount );
496 gxv_array_getlimits_byte( p, p + glyphCount, &min, &max, valid );
497 p += valid->subtable_length;
499 if ( leftClassCount < max )
500 FT_INVALID_DATA;
504 * check rightClass[gid] < rightClassCount
507 FT_Byte min, max;
510 GXV_LIMIT_CHECK( glyphCount );
511 gxv_array_getlimits_byte( p, p + glyphCount, &min, &max, valid );
512 p += valid->subtable_length;
514 if ( rightClassCount < max )
515 FT_INVALID_DATA;
519 * check kernIndex[i, j] < kernValueCount
522 FT_UShort i, j;
525 for ( i = 0; i < leftClassCount; i++ )
527 for ( j = 0; j < rightClassCount; j++ )
529 GXV_LIMIT_CHECK( 1 );
530 if ( kernValueCount < FT_NEXT_BYTE( p ) )
531 FT_INVALID_OFFSET;
536 valid->subtable_length = p - table;
538 GXV_EXIT;
542 static FT_Bool
543 gxv_kern_coverage_new_apple_validate( FT_UShort coverage,
544 FT_UShort* format,
545 GXV_Validator valid )
547 /* new Apple-dialect */
548 FT_Bool kernVertical;
549 FT_Bool kernCrossStream;
550 FT_Bool kernVariation;
552 FT_UNUSED( valid );
555 /* reserved bits = 0 */
556 if ( coverage & 0x1FFC )
557 return 0;
559 kernVertical = FT_BOOL( ( coverage >> 15 ) & 1 );
560 kernCrossStream = FT_BOOL( ( coverage >> 14 ) & 1 );
561 kernVariation = FT_BOOL( ( coverage >> 13 ) & 1 );
563 *format = (FT_UShort)( coverage & 0x0003 );
565 GXV_TRACE(( "new Apple-dialect: "
566 "horizontal=%d, cross-stream=%d, variation=%d, format=%d\n",
567 !kernVertical, kernCrossStream, kernVariation, *format ));
569 GXV_TRACE(( "kerning values in Apple format subtable are ignored\n" ));
571 return 1;
575 static FT_Bool
576 gxv_kern_coverage_classic_apple_validate( FT_UShort coverage,
577 FT_UShort* format,
578 GXV_Validator valid )
580 /* classic Apple-dialect */
581 FT_Bool horizontal;
582 FT_Bool cross_stream;
585 /* check expected flags, but don't check if MS-dialect is impossible */
586 if ( !( coverage & 0xFD00 ) && KERN_ALLOWS_MS( valid ) )
587 return 0;
589 /* reserved bits = 0 */
590 if ( coverage & 0x02FC )
591 return 0;
593 horizontal = FT_BOOL( ( coverage >> 15 ) & 1 );
594 cross_stream = FT_BOOL( ( coverage >> 13 ) & 1 );
596 *format = (FT_UShort)( coverage & 0x0003 );
598 GXV_TRACE(( "classic Apple-dialect: "
599 "horizontal=%d, cross-stream=%d, format=%d\n",
600 horizontal, cross_stream, *format ));
602 /* format 1 requires GX State Machine, too new for classic */
603 if ( *format == 1 )
604 return 0;
606 GXV_TRACE(( "kerning values in Apple format subtable are ignored\n" ));
608 return 1;
612 static FT_Bool
613 gxv_kern_coverage_classic_microsoft_validate( FT_UShort coverage,
614 FT_UShort* format,
615 GXV_Validator valid )
617 /* classic Microsoft-dialect */
618 FT_Bool horizontal;
619 FT_Bool minimum;
620 FT_Bool cross_stream;
621 FT_Bool override;
623 FT_UNUSED( valid );
626 /* reserved bits = 0 */
627 if ( coverage & 0xFDF0 )
628 return 0;
630 horizontal = FT_BOOL( coverage & 1 );
631 minimum = FT_BOOL( ( coverage >> 1 ) & 1 );
632 cross_stream = FT_BOOL( ( coverage >> 2 ) & 1 );
633 override = FT_BOOL( ( coverage >> 3 ) & 1 );
635 *format = (FT_UShort)( ( coverage >> 8 ) & 0x0003 );
637 GXV_TRACE(( "classic Microsoft-dialect: "
638 "horizontal=%d, minimum=%d, cross-stream=%d, "
639 "override=%d, format=%d\n",
640 horizontal, minimum, cross_stream, override, *format ));
642 if ( *format == 2 )
643 GXV_TRACE((
644 "kerning values in Microsoft format 2 subtable are ignored\n" ));
646 return 1;
650 /*************************************************************************/
651 /*************************************************************************/
652 /***** *****/
653 /***** MAIN *****/
654 /***** *****/
655 /*************************************************************************/
656 /*************************************************************************/
658 static GXV_kern_Dialect
659 gxv_kern_coverage_validate( FT_UShort coverage,
660 FT_UShort* format,
661 GXV_Validator valid )
663 GXV_kern_Dialect result = KERN_DIALECT_UNKNOWN;
666 GXV_NAME_ENTER( "validating coverage" );
668 GXV_TRACE(( "interprete coverage 0x%04x by Apple style\n", coverage ));
670 if ( KERN_IS_NEW( valid ) )
672 if ( gxv_kern_coverage_new_apple_validate( coverage,
673 format,
674 valid ) )
676 result = KERN_DIALECT_APPLE;
677 goto Exit;
681 if ( KERN_IS_CLASSIC( valid ) && KERN_ALLOWS_APPLE( valid ) )
683 if ( gxv_kern_coverage_classic_apple_validate( coverage,
684 format,
685 valid ) )
687 result = KERN_DIALECT_APPLE;
688 goto Exit;
692 if ( KERN_IS_CLASSIC( valid ) && KERN_ALLOWS_MS( valid ) )
694 if ( gxv_kern_coverage_classic_microsoft_validate( coverage,
695 format,
696 valid ) )
698 result = KERN_DIALECT_MS;
699 goto Exit;
703 GXV_TRACE(( "cannot interprete coverage, broken kern subtable\n" ));
705 Exit:
706 GXV_EXIT;
707 return result;
711 static void
712 gxv_kern_subtable_validate( FT_Bytes table,
713 FT_Bytes limit,
714 GXV_Validator valid )
716 FT_Bytes p = table;
717 FT_UShort version = 0; /* MS only: subtable version, unused */
718 FT_ULong length; /* MS: 16bit, Apple: 32bit*/
719 FT_UShort coverage;
720 FT_UShort tupleIndex = 0; /* Apple only */
721 FT_UShort u16[2];
722 FT_UShort format = 255; /* subtable format */
725 GXV_NAME_ENTER( "kern subtable" );
727 GXV_LIMIT_CHECK( 2 + 2 + 2 );
728 u16[0] = FT_NEXT_USHORT( p ); /* Apple: length_hi MS: version */
729 u16[1] = FT_NEXT_USHORT( p ); /* Apple: length_lo MS: length */
730 coverage = FT_NEXT_USHORT( p );
732 switch ( gxv_kern_coverage_validate( coverage, &format, valid ) )
734 case KERN_DIALECT_MS:
735 version = u16[0];
736 length = u16[1];
737 tupleIndex = 0;
738 GXV_TRACE(( "Subtable version = %d\n", version ));
739 GXV_TRACE(( "Subtable length = %d\n", length ));
740 break;
742 case KERN_DIALECT_APPLE:
743 version = 0;
744 length = ( u16[0] << 16 ) + u16[1];
745 tupleIndex = 0;
746 GXV_TRACE(( "Subtable length = %d\n", length ));
748 if ( KERN_IS_NEW( valid ) )
750 GXV_LIMIT_CHECK( 2 );
751 tupleIndex = FT_NEXT_USHORT( p );
752 GXV_TRACE(( "Subtable tupleIndex = %d\n", tupleIndex ));
754 break;
756 default:
757 length = u16[1];
758 GXV_TRACE(( "cannot detect subtable dialect, "
759 "just skip %d byte\n", length ));
760 goto Exit;
763 /* formats 1, 2, 3 require the position of the start of this subtable */
764 if ( format == 0 )
765 gxv_kern_subtable_fmt0_validate( table, table + length, valid );
766 else if ( format == 1 )
767 gxv_kern_subtable_fmt1_validate( table, table + length, valid );
768 else if ( format == 2 )
769 gxv_kern_subtable_fmt2_validate( table, table + length, valid );
770 else if ( format == 3 )
771 gxv_kern_subtable_fmt3_validate( table, table + length, valid );
772 else
773 FT_INVALID_DATA;
775 Exit:
776 valid->subtable_length = length;
777 GXV_EXIT;
781 /*************************************************************************/
782 /*************************************************************************/
783 /***** *****/
784 /***** kern TABLE *****/
785 /***** *****/
786 /*************************************************************************/
787 /*************************************************************************/
789 static void
790 gxv_kern_validate_generic( FT_Bytes table,
791 FT_Face face,
792 FT_Bool classic_only,
793 GXV_kern_Dialect dialect_request,
794 FT_Validator ftvalid )
796 GXV_ValidatorRec validrec;
797 GXV_Validator valid = &validrec;
799 GXV_kern_DataRec kernrec;
800 GXV_kern_Data kern = &kernrec;
802 FT_Bytes p = table;
803 FT_Bytes limit = 0;
805 FT_ULong nTables = 0;
806 FT_UInt i;
809 valid->root = ftvalid;
810 valid->table_data = kern;
811 valid->face = face;
813 FT_TRACE3(( "validating `kern' table\n" ));
814 GXV_INIT;
815 KERN_DIALECT( valid ) = dialect_request;
817 GXV_LIMIT_CHECK( 2 );
818 GXV_KERN_DATA( version ) = (GXV_kern_Version)FT_NEXT_USHORT( p );
819 GXV_TRACE(( "version 0x%04x (higher 16bit)\n",
820 GXV_KERN_DATA( version ) ));
822 if ( 0x0001 < GXV_KERN_DATA( version ) )
823 FT_INVALID_FORMAT;
824 else if ( KERN_IS_CLASSIC( valid ) )
826 GXV_LIMIT_CHECK( 2 );
827 nTables = FT_NEXT_USHORT( p );
829 else if ( KERN_IS_NEW( valid ) )
831 if ( classic_only )
832 FT_INVALID_FORMAT;
834 if ( 0x0000 != FT_NEXT_USHORT( p ) )
835 FT_INVALID_FORMAT;
837 GXV_LIMIT_CHECK( 4 );
838 nTables = FT_NEXT_ULONG( p );
841 for ( i = 0; i < nTables; i++ )
843 GXV_TRACE(( "validating subtable %d/%d\n", i, nTables ));
844 /* p should be 32bit-aligned? */
845 gxv_kern_subtable_validate( p, 0, valid );
846 p += valid->subtable_length;
849 FT_TRACE4(( "\n" ));
853 FT_LOCAL_DEF( void )
854 gxv_kern_validate( FT_Bytes table,
855 FT_Face face,
856 FT_Validator ftvalid )
858 gxv_kern_validate_generic( table, face, 0, KERN_DIALECT_ANY, ftvalid );
862 FT_LOCAL_DEF( void )
863 gxv_kern_validate_classic( FT_Bytes table,
864 FT_Face face,
865 FT_Int dialect_flags,
866 FT_Validator ftvalid )
868 GXV_kern_Dialect dialect_request;
871 dialect_request = (GXV_kern_Dialect)dialect_flags;
872 gxv_kern_validate_generic( table, face, 1, dialect_request, ftvalid );
876 /* END */