1 /***************************************************************************/
5 /* TrueTypeGX/AAT just table validation (body). */
7 /* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
10 /* This file is part of the FreeType project, and may only be used, */
11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */
16 /***************************************************************************/
18 /***************************************************************************/
20 /* gxvalid is derived from both gxlayout module and otvalid module. */
21 /* Development of gxlayout is supported by the Information-technology */
22 /* Promotion Agency(IPA), Japan. */
24 /***************************************************************************/
30 #include FT_SFNT_NAMES_H
33 /*************************************************************************/
35 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
36 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
37 /* messages during execution. */
40 #define FT_COMPONENT trace_gxvjust
43 * referred `just' table format specification:
44 * http://developer.apple.com/fonts/TTRefMan/RM06/Chap6just.html
46 * ----------------------------------------------
47 * [JUST HEADER]: GXV_JUST_HEADER_SIZE
48 * version (fixed: 32bit) = 0x00010000
49 * format (uint16: 16bit) = 0 is only defined (2000)
50 * horizOffset (uint16: 16bit)
51 * vertOffset (uint16: 16bit)
52 * ----------------------------------------------
55 typedef struct GXV_just_DataRec_
57 FT_UShort wdc_offset_max
;
58 FT_UShort wdc_offset_min
;
59 FT_UShort pc_offset_max
;
60 FT_UShort pc_offset_min
;
62 } GXV_just_DataRec
, *GXV_just_Data
;
65 #define GXV_JUST_DATA( a ) GXV_TABLE_DATA( just, a )
69 gxv_just_wdp_entry_validate( FT_Bytes table
,
75 FT_Fixed beforeGrowLimit
;
76 FT_Fixed beforeShrinkGrowLimit
;
77 FT_Fixed afterGrowLimit
;
78 FT_Fixed afterShrinkGrowLimit
;
80 FT_UShort shrinkFlags
;
83 GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 + 4 + 2 + 2 );
84 justClass
= FT_NEXT_ULONG( p
);
85 beforeGrowLimit
= FT_NEXT_ULONG( p
);
86 beforeShrinkGrowLimit
= FT_NEXT_ULONG( p
);
87 afterGrowLimit
= FT_NEXT_ULONG( p
);
88 afterShrinkGrowLimit
= FT_NEXT_ULONG( p
);
89 growFlags
= FT_NEXT_USHORT( p
);
90 shrinkFlags
= FT_NEXT_USHORT( p
);
92 /* TODO: decode flags for human readability */
94 valid
->subtable_length
= p
- table
;
99 gxv_just_wdc_entry_validate( FT_Bytes table
,
101 GXV_Validator valid
)
107 GXV_LIMIT_CHECK( 4 );
108 count
= FT_NEXT_ULONG( p
);
109 for ( i
= 0; i
< count
; i
++ )
111 GXV_TRACE(( "validating wdc pair %d/%d\n", i
+ 1, count
));
112 gxv_just_wdp_entry_validate( p
, limit
, valid
);
113 p
+= valid
->subtable_length
;
116 valid
->subtable_length
= p
- table
;
121 gxv_just_widthDeltaClusters_validate( FT_Bytes table
,
123 GXV_Validator valid
)
126 FT_Bytes wdc_end
= table
+ GXV_JUST_DATA( wdc_offset_max
);
130 GXV_NAME_ENTER( "just justDeltaClusters" );
132 if ( limit
<= wdc_end
)
135 for ( i
= 0; p
<= wdc_end
; i
++ )
137 gxv_just_wdc_entry_validate( p
, limit
, valid
);
138 p
+= valid
->subtable_length
;
141 valid
->subtable_length
= p
- table
;
148 gxv_just_actSubrecord_type0_validate( FT_Bytes table
,
150 GXV_Validator valid
)
158 FT_UShort decomposedCount
;
163 GXV_LIMIT_CHECK( 4 + 4 + 2 + 2 );
164 lowerLimit
= FT_NEXT_ULONG( p
);
165 upperLimit
= FT_NEXT_ULONG( p
);
166 order
= FT_NEXT_USHORT( p
);
167 decomposedCount
= FT_NEXT_USHORT( p
);
169 for ( i
= 0; i
< decomposedCount
; i
++ )
174 GXV_LIMIT_CHECK( 2 );
175 glyphs
= FT_NEXT_USHORT( p
);
178 valid
->subtable_length
= p
- table
;
183 gxv_just_actSubrecord_type1_validate( FT_Bytes table
,
185 GXV_Validator valid
)
191 GXV_LIMIT_CHECK( 2 );
192 addGlyph
= FT_NEXT_USHORT( p
);
194 valid
->subtable_length
= p
- table
;
199 gxv_just_actSubrecord_type2_validate( FT_Bytes table
,
201 GXV_Validator valid
)
204 FT_Fixed substThreshhold
; /* Apple misspelled "Threshhold" */
206 FT_UShort substGlyph
;
209 GXV_LIMIT_CHECK( 4 + 2 + 2 );
210 substThreshhold
= FT_NEXT_ULONG( p
);
211 addGlyph
= FT_NEXT_USHORT( p
);
212 substGlyph
= FT_NEXT_USHORT( p
);
214 valid
->subtable_length
= p
- table
;
219 gxv_just_actSubrecord_type4_validate( FT_Bytes table
,
221 GXV_Validator valid
)
224 FT_ULong variantsAxis
;
225 FT_Fixed minimumLimit
;
226 FT_Fixed noStretchValue
;
227 FT_Fixed maximumLimit
;
230 GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 );
231 variantsAxis
= FT_NEXT_ULONG( p
);
232 minimumLimit
= FT_NEXT_ULONG( p
);
233 noStretchValue
= FT_NEXT_ULONG( p
);
234 maximumLimit
= FT_NEXT_ULONG( p
);
236 valid
->subtable_length
= p
- table
;
241 gxv_just_actSubrecord_type5_validate( FT_Bytes table
,
243 GXV_Validator valid
)
250 GXV_LIMIT_CHECK( 2 + 2 );
251 flags
= FT_NEXT_USHORT( p
);
252 glyph
= FT_NEXT_USHORT( p
);
254 valid
->subtable_length
= p
- table
;
258 /* parse single actSubrecord */
260 gxv_just_actSubrecord_validate( FT_Bytes table
,
262 GXV_Validator valid
)
265 FT_UShort actionClass
;
266 FT_UShort actionType
;
267 FT_ULong actionLength
;
270 GXV_NAME_ENTER( "just actSubrecord" );
272 GXV_LIMIT_CHECK( 2 + 2 + 4 );
273 actionClass
= FT_NEXT_USHORT( p
);
274 actionType
= FT_NEXT_USHORT( p
);
275 actionLength
= FT_NEXT_ULONG( p
);
277 if ( actionType
== 0 )
278 gxv_just_actSubrecord_type0_validate( p
, limit
, valid
);
279 else if ( actionType
== 1 )
280 gxv_just_actSubrecord_type1_validate( p
, limit
, valid
);
281 else if ( actionType
== 2 )
282 gxv_just_actSubrecord_type2_validate( p
, limit
, valid
);
283 else if ( actionType
== 3 )
284 ; /* Stretch glyph action: no actionData */
285 else if ( actionType
== 4 )
286 gxv_just_actSubrecord_type4_validate( p
, limit
, valid
);
287 else if ( actionType
== 5 )
288 gxv_just_actSubrecord_type5_validate( p
, limit
, valid
);
292 valid
->subtable_length
= actionLength
;
299 gxv_just_pcActionRecord_validate( FT_Bytes table
,
301 GXV_Validator valid
)
304 FT_ULong actionCount
;
308 GXV_LIMIT_CHECK( 4 );
309 actionCount
= FT_NEXT_ULONG( p
);
310 GXV_TRACE(( "actionCount = %d\n", actionCount
));
312 for ( i
= 0; i
< actionCount
; i
++ )
314 gxv_just_actSubrecord_validate( p
, limit
, valid
);
315 p
+= valid
->subtable_length
;
318 valid
->subtable_length
= p
- table
;
325 gxv_just_pcTable_LookupValue_entry_validate( FT_UShort glyph
,
326 GXV_LookupValueCPtr value_p
,
327 GXV_Validator valid
)
331 if ( value_p
->u
> GXV_JUST_DATA( pc_offset_max
) )
332 GXV_JUST_DATA( pc_offset_max
) = value_p
->u
;
333 if ( value_p
->u
< GXV_JUST_DATA( pc_offset_max
) )
334 GXV_JUST_DATA( pc_offset_min
) = value_p
->u
;
339 gxv_just_pcLookupTable_validate( FT_Bytes table
,
341 GXV_Validator valid
)
346 GXV_NAME_ENTER( "just pcLookupTable" );
347 GXV_JUST_DATA( pc_offset_max
) = 0x0000;
348 GXV_JUST_DATA( pc_offset_min
) = 0xFFFFU
;
350 valid
->lookupval_sign
= GXV_LOOKUPVALUE_UNSIGNED
;
351 valid
->lookupval_func
= gxv_just_pcTable_LookupValue_entry_validate
;
353 gxv_LookupTable_validate( p
, limit
, valid
);
355 /* subtable_length is set by gxv_LookupTable_validate() */
362 gxv_just_postcompTable_validate( FT_Bytes table
,
364 GXV_Validator valid
)
369 GXV_NAME_ENTER( "just postcompTable" );
371 gxv_just_pcLookupTable_validate( p
, limit
, valid
);
372 p
+= valid
->subtable_length
;
374 gxv_just_pcActionRecord_validate( p
, limit
, valid
);
375 p
+= valid
->subtable_length
;
377 valid
->subtable_length
= p
- table
;
384 gxv_just_classTable_entry_validate(
387 GXV_StateTable_GlyphOffsetCPtr glyphOffset_p
,
390 GXV_Validator valid
)
393 FT_UShort dontAdvance
;
395 FT_UShort currentClass
;
398 FT_UNUSED( glyphOffset_p
);
404 setMark
= (FT_UShort
)( ( flags
>> 15 ) & 1 );
405 dontAdvance
= (FT_UShort
)( ( flags
>> 14 ) & 1 );
406 markClass
= (FT_UShort
)( ( flags
>> 7 ) & 0x7F );
407 currentClass
= (FT_UShort
)( flags
& 0x7F );
409 /* TODO: validate markClass & currentClass */
414 gxv_just_justClassTable_validate ( FT_Bytes table
,
416 GXV_Validator valid
)
421 FT_ULong subFeatureFlags
;
424 GXV_NAME_ENTER( "just justClassTable" );
426 GXV_LIMIT_CHECK( 2 + 2 + 4 );
427 length
= FT_NEXT_USHORT( p
);
428 coverage
= FT_NEXT_USHORT( p
);
429 subFeatureFlags
= FT_NEXT_ULONG( p
);
431 GXV_TRACE(( " justClassTable: coverage = 0x%04x (%s)",
433 ( 0x4000 & coverage
) == 0 ? "ascending" : "descending" ));
435 valid
->statetable
.optdata
= NULL
;
436 valid
->statetable
.optdata_load_func
= NULL
;
437 valid
->statetable
.subtable_setup_func
= NULL
;
438 valid
->statetable
.entry_glyphoffset_fmt
= GXV_GLYPHOFFSET_NONE
;
439 valid
->statetable
.entry_validate_func
=
440 gxv_just_classTable_entry_validate
;
442 gxv_StateTable_validate( p
, table
+ length
, valid
);
444 /* subtable_length is set by gxv_LookupTable_validate() */
451 gxv_just_wdcTable_LookupValue_validate( FT_UShort glyph
,
452 GXV_LookupValueCPtr value_p
,
453 GXV_Validator valid
)
457 if ( value_p
->u
> GXV_JUST_DATA( wdc_offset_max
) )
458 GXV_JUST_DATA( wdc_offset_max
) = value_p
->u
;
459 if ( value_p
->u
< GXV_JUST_DATA( wdc_offset_min
) )
460 GXV_JUST_DATA( wdc_offset_min
) = value_p
->u
;
465 gxv_just_justData_lookuptable_validate( FT_Bytes table
,
467 GXV_Validator valid
)
472 GXV_JUST_DATA( wdc_offset_max
) = 0x0000;
473 GXV_JUST_DATA( wdc_offset_min
) = 0xFFFFU
;
475 valid
->lookupval_sign
= GXV_LOOKUPVALUE_UNSIGNED
;
476 valid
->lookupval_func
= gxv_just_wdcTable_LookupValue_validate
;
478 gxv_LookupTable_validate( p
, limit
, valid
);
480 /* subtable_length is set by gxv_LookupTable_validate() */
487 * gxv_just_justData_validate() parses and validates horizData, vertData.
490 gxv_just_justData_validate( FT_Bytes table
,
492 GXV_Validator valid
)
495 * following 3 offsets are measured from the start of `just'
496 * (which table points to), not justData
498 FT_UShort justClassTableOffset
;
499 FT_UShort wdcTableOffset
;
500 FT_UShort pcTableOffset
;
503 GXV_ODTECT( 4, odtect
);
506 GXV_NAME_ENTER( "just justData" );
508 GXV_ODTECT_INIT( odtect
);
509 GXV_LIMIT_CHECK( 2 + 2 + 2 );
510 justClassTableOffset
= FT_NEXT_USHORT( p
);
511 wdcTableOffset
= FT_NEXT_USHORT( p
);
512 pcTableOffset
= FT_NEXT_USHORT( p
);
514 GXV_TRACE(( " (justClassTableOffset = 0x%04x)\n", justClassTableOffset
));
515 GXV_TRACE(( " (wdcTableOffset = 0x%04x)\n", wdcTableOffset
));
516 GXV_TRACE(( " (pcTableOffset = 0x%04x)\n", pcTableOffset
));
518 gxv_just_justData_lookuptable_validate( p
, limit
, valid
);
519 gxv_odtect_add_range( p
, valid
->subtable_length
,
520 "just_LookupTable", odtect
);
522 if ( wdcTableOffset
)
524 gxv_just_widthDeltaClusters_validate(
525 valid
->root
->base
+ wdcTableOffset
, limit
, valid
);
526 gxv_odtect_add_range( valid
->root
->base
+ wdcTableOffset
,
527 valid
->subtable_length
, "just_wdcTable", odtect
);
532 gxv_just_postcompTable_validate( valid
->root
->base
+ pcTableOffset
,
534 gxv_odtect_add_range( valid
->root
->base
+ pcTableOffset
,
535 valid
->subtable_length
, "just_pcTable", odtect
);
538 if ( justClassTableOffset
)
540 gxv_just_justClassTable_validate(
541 valid
->root
->base
+ justClassTableOffset
, limit
, valid
);
542 gxv_odtect_add_range( valid
->root
->base
+ justClassTableOffset
,
543 valid
->subtable_length
, "just_justClassTable",
547 gxv_odtect_validate( odtect
, valid
);
554 gxv_just_validate( FT_Bytes table
,
556 FT_Validator ftvalid
)
560 FT_Offset table_size
;
562 GXV_ValidatorRec validrec
;
563 GXV_Validator valid
= &validrec
;
564 GXV_just_DataRec justrec
;
565 GXV_just_Data just
= &justrec
;
569 FT_UShort horizOffset
;
570 FT_UShort vertOffset
;
572 GXV_ODTECT( 3, odtect
);
575 GXV_ODTECT_INIT( odtect
);
577 valid
->root
= ftvalid
;
578 valid
->table_data
= just
;
581 FT_TRACE3(( "validating `just' table\n" ));
584 limit
= valid
->root
->limit
;
585 table_size
= limit
- table
;
587 GXV_LIMIT_CHECK( 4 + 2 + 2 + 2 );
588 version
= FT_NEXT_ULONG( p
);
589 format
= FT_NEXT_USHORT( p
);
590 horizOffset
= FT_NEXT_USHORT( p
);
591 vertOffset
= FT_NEXT_USHORT( p
);
592 gxv_odtect_add_range( table
, p
- table
, "just header", odtect
);
595 /* Version 1.0 (always:2000) */
596 GXV_TRACE(( " (version = 0x%08x)\n", version
));
597 if ( version
!= 0x00010000UL
)
600 /* format 0 (always:2000) */
601 GXV_TRACE(( " (format = 0x%04x)\n", format
));
602 if ( format
!= 0x0000 )
605 GXV_TRACE(( " (horizOffset = %d)\n", horizOffset
));
606 GXV_TRACE(( " (vertOffset = %d)\n", vertOffset
));
609 /* validate justData */
610 if ( 0 < horizOffset
)
612 gxv_just_justData_validate( table
+ horizOffset
, limit
, valid
);
613 gxv_odtect_add_range( table
+ horizOffset
, valid
->subtable_length
,
614 "horizJustData", odtect
);
617 if ( 0 < vertOffset
)
619 gxv_just_justData_validate( table
+ vertOffset
, limit
, valid
);
620 gxv_odtect_add_range( table
+ vertOffset
, valid
->subtable_length
,
621 "vertJustData", odtect
);
624 gxv_odtect_validate( odtect
, valid
);