Sync with trunk r47367
[reactos.git] / lib / 3rdparty / freetype / src / gxvalid / gxvjust.c
1 /***************************************************************************/
2 /* */
3 /* gxvjust.c */
4 /* */
5 /* TrueTypeGX/AAT just table validation (body). */
6 /* */
7 /* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
9 /* */
10 /* This file is part of the FreeType project, and may only be used, */
11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */
15 /* */
16 /***************************************************************************/
17
18 /***************************************************************************/
19 /* */
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. */
23 /* */
24 /***************************************************************************/
25
26
27 #include "gxvalid.h"
28 #include "gxvcommn.h"
29
30 #include FT_SFNT_NAMES_H
31
32
33 /*************************************************************************/
34 /* */
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. */
38 /* */
39 #undef FT_COMPONENT
40 #define FT_COMPONENT trace_gxvjust
41
42 /*
43 * referred `just' table format specification:
44 * http://developer.apple.com/fonts/TTRefMan/RM06/Chap6just.html
45 * last updated 2000.
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 * ----------------------------------------------
53 */
54
55 typedef struct GXV_just_DataRec_
56 {
57 FT_UShort wdc_offset_max;
58 FT_UShort wdc_offset_min;
59 FT_UShort pc_offset_max;
60 FT_UShort pc_offset_min;
61
62 } GXV_just_DataRec, *GXV_just_Data;
63
64
65 #define GXV_JUST_DATA( a ) GXV_TABLE_DATA( just, a )
66
67
68 static void
69 gxv_just_wdp_entry_validate( FT_Bytes table,
70 FT_Bytes limit,
71 GXV_Validator valid )
72 {
73 FT_Bytes p = table;
74 FT_ULong justClass;
75 FT_Fixed beforeGrowLimit;
76 FT_Fixed beforeShrinkGrowLimit;
77 FT_Fixed afterGrowLimit;
78 FT_Fixed afterShrinkGrowLimit;
79 FT_UShort growFlags;
80 FT_UShort shrinkFlags;
81
82
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 );
91
92 /* TODO: decode flags for human readability */
93
94 valid->subtable_length = p - table;
95 }
96
97
98 static void
99 gxv_just_wdc_entry_validate( FT_Bytes table,
100 FT_Bytes limit,
101 GXV_Validator valid )
102 {
103 FT_Bytes p = table;
104 FT_ULong count, i;
105
106
107 GXV_LIMIT_CHECK( 4 );
108 count = FT_NEXT_ULONG( p );
109 for ( i = 0; i < count; i++ )
110 {
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;
114 }
115
116 valid->subtable_length = p - table;
117 }
118
119
120 static void
121 gxv_just_widthDeltaClusters_validate( FT_Bytes table,
122 FT_Bytes limit,
123 GXV_Validator valid )
124 {
125 FT_Bytes p = table ;
126 FT_Bytes wdc_end = table + GXV_JUST_DATA( wdc_offset_max );
127 FT_UInt i;
128
129
130 GXV_NAME_ENTER( "just justDeltaClusters" );
131
132 if ( limit <= wdc_end )
133 FT_INVALID_OFFSET;
134
135 for ( i = 0; p <= wdc_end; i++ )
136 {
137 gxv_just_wdc_entry_validate( p, limit, valid );
138 p += valid->subtable_length;
139 }
140
141 valid->subtable_length = p - table;
142
143 GXV_EXIT;
144 }
145
146
147 static void
148 gxv_just_actSubrecord_type0_validate( FT_Bytes table,
149 FT_Bytes limit,
150 GXV_Validator valid )
151 {
152 FT_Bytes p = table;
153
154 FT_Fixed lowerLimit;
155 FT_Fixed upperLimit;
156
157 FT_UShort order;
158 FT_UShort decomposedCount;
159
160 FT_UInt i;
161
162
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 );
168
169 for ( i = 0; i < decomposedCount; i++ )
170 {
171 FT_UShort glyphs;
172
173
174 GXV_LIMIT_CHECK( 2 );
175 glyphs = FT_NEXT_USHORT( p );
176 }
177
178 valid->subtable_length = p - table;
179 }
180
181
182 static void
183 gxv_just_actSubrecord_type1_validate( FT_Bytes table,
184 FT_Bytes limit,
185 GXV_Validator valid )
186 {
187 FT_Bytes p = table;
188 FT_UShort addGlyph;
189
190
191 GXV_LIMIT_CHECK( 2 );
192 addGlyph = FT_NEXT_USHORT( p );
193
194 valid->subtable_length = p - table;
195 }
196
197
198 static void
199 gxv_just_actSubrecord_type2_validate( FT_Bytes table,
200 FT_Bytes limit,
201 GXV_Validator valid )
202 {
203 FT_Bytes p = table;
204 FT_Fixed substThreshhold; /* Apple misspelled "Threshhold" */
205 FT_UShort addGlyph;
206 FT_UShort substGlyph;
207
208
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 );
213
214 valid->subtable_length = p - table;
215 }
216
217
218 static void
219 gxv_just_actSubrecord_type4_validate( FT_Bytes table,
220 FT_Bytes limit,
221 GXV_Validator valid )
222 {
223 FT_Bytes p = table;
224 FT_ULong variantsAxis;
225 FT_Fixed minimumLimit;
226 FT_Fixed noStretchValue;
227 FT_Fixed maximumLimit;
228
229
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 );
235
236 valid->subtable_length = p - table;
237 }
238
239
240 static void
241 gxv_just_actSubrecord_type5_validate( FT_Bytes table,
242 FT_Bytes limit,
243 GXV_Validator valid )
244 {
245 FT_Bytes p = table;
246 FT_UShort flags;
247 FT_UShort glyph;
248
249
250 GXV_LIMIT_CHECK( 2 + 2 );
251 flags = FT_NEXT_USHORT( p );
252 glyph = FT_NEXT_USHORT( p );
253
254 valid->subtable_length = p - table;
255 }
256
257
258 /* parse single actSubrecord */
259 static void
260 gxv_just_actSubrecord_validate( FT_Bytes table,
261 FT_Bytes limit,
262 GXV_Validator valid )
263 {
264 FT_Bytes p = table;
265 FT_UShort actionClass;
266 FT_UShort actionType;
267 FT_ULong actionLength;
268
269
270 GXV_NAME_ENTER( "just actSubrecord" );
271
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 );
276
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 );
289 else
290 FT_INVALID_DATA;
291
292 valid->subtable_length = actionLength;
293
294 GXV_EXIT;
295 }
296
297
298 static void
299 gxv_just_pcActionRecord_validate( FT_Bytes table,
300 FT_Bytes limit,
301 GXV_Validator valid )
302 {
303 FT_Bytes p = table;
304 FT_ULong actionCount;
305 FT_ULong i;
306
307
308 GXV_LIMIT_CHECK( 4 );
309 actionCount = FT_NEXT_ULONG( p );
310 GXV_TRACE(( "actionCount = %d\n", actionCount ));
311
312 for ( i = 0; i < actionCount; i++ )
313 {
314 gxv_just_actSubrecord_validate( p, limit, valid );
315 p += valid->subtable_length;
316 }
317
318 valid->subtable_length = p - table;
319
320 GXV_EXIT;
321 }
322
323
324 static void
325 gxv_just_pcTable_LookupValue_entry_validate( FT_UShort glyph,
326 GXV_LookupValueCPtr value_p,
327 GXV_Validator valid )
328 {
329 FT_UNUSED( glyph );
330
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;
335 }
336
337
338 static void
339 gxv_just_pcLookupTable_validate( FT_Bytes table,
340 FT_Bytes limit,
341 GXV_Validator valid )
342 {
343 FT_Bytes p = table;
344
345
346 GXV_NAME_ENTER( "just pcLookupTable" );
347 GXV_JUST_DATA( pc_offset_max ) = 0x0000;
348 GXV_JUST_DATA( pc_offset_min ) = 0xFFFFU;
349
350 valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
351 valid->lookupval_func = gxv_just_pcTable_LookupValue_entry_validate;
352
353 gxv_LookupTable_validate( p, limit, valid );
354
355 /* subtable_length is set by gxv_LookupTable_validate() */
356
357 GXV_EXIT;
358 }
359
360
361 static void
362 gxv_just_postcompTable_validate( FT_Bytes table,
363 FT_Bytes limit,
364 GXV_Validator valid )
365 {
366 FT_Bytes p = table;
367
368
369 GXV_NAME_ENTER( "just postcompTable" );
370
371 gxv_just_pcLookupTable_validate( p, limit, valid );
372 p += valid->subtable_length;
373
374 gxv_just_pcActionRecord_validate( p, limit, valid );
375 p += valid->subtable_length;
376
377 valid->subtable_length = p - table;
378
379 GXV_EXIT;
380 }
381
382
383 static void
384 gxv_just_classTable_entry_validate(
385 FT_Byte state,
386 FT_UShort flags,
387 GXV_StateTable_GlyphOffsetCPtr glyphOffset_p,
388 FT_Bytes table,
389 FT_Bytes limit,
390 GXV_Validator valid )
391 {
392 FT_UShort setMark;
393 FT_UShort dontAdvance;
394 FT_UShort markClass;
395 FT_UShort currentClass;
396
397 FT_UNUSED( state );
398 FT_UNUSED( glyphOffset_p );
399 FT_UNUSED( table );
400 FT_UNUSED( limit );
401 FT_UNUSED( valid );
402
403
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 );
408
409 /* TODO: validate markClass & currentClass */
410 }
411
412
413 static void
414 gxv_just_justClassTable_validate ( FT_Bytes table,
415 FT_Bytes limit,
416 GXV_Validator valid )
417 {
418 FT_Bytes p = table;
419 FT_UShort length;
420 FT_UShort coverage;
421 FT_ULong subFeatureFlags;
422
423
424 GXV_NAME_ENTER( "just justClassTable" );
425
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 );
430
431 GXV_TRACE(( " justClassTable: coverage = 0x%04x (%s)",
432 coverage,
433 ( 0x4000 & coverage ) == 0 ? "ascending" : "descending" ));
434
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;
441
442 gxv_StateTable_validate( p, table + length, valid );
443
444 /* subtable_length is set by gxv_LookupTable_validate() */
445
446 GXV_EXIT;
447 }
448
449
450 static void
451 gxv_just_wdcTable_LookupValue_validate( FT_UShort glyph,
452 GXV_LookupValueCPtr value_p,
453 GXV_Validator valid )
454 {
455 FT_UNUSED( glyph );
456
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;
461 }
462
463
464 static void
465 gxv_just_justData_lookuptable_validate( FT_Bytes table,
466 FT_Bytes limit,
467 GXV_Validator valid )
468 {
469 FT_Bytes p = table;
470
471
472 GXV_JUST_DATA( wdc_offset_max ) = 0x0000;
473 GXV_JUST_DATA( wdc_offset_min ) = 0xFFFFU;
474
475 valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
476 valid->lookupval_func = gxv_just_wdcTable_LookupValue_validate;
477
478 gxv_LookupTable_validate( p, limit, valid );
479
480 /* subtable_length is set by gxv_LookupTable_validate() */
481
482 GXV_EXIT;
483 }
484
485
486 /*
487 * gxv_just_justData_validate() parses and validates horizData, vertData.
488 */
489 static void
490 gxv_just_justData_validate( FT_Bytes table,
491 FT_Bytes limit,
492 GXV_Validator valid )
493 {
494 /*
495 * following 3 offsets are measured from the start of `just'
496 * (which table points to), not justData
497 */
498 FT_UShort justClassTableOffset;
499 FT_UShort wdcTableOffset;
500 FT_UShort pcTableOffset;
501 FT_Bytes p = table;
502
503 GXV_ODTECT( 4, odtect );
504
505
506 GXV_NAME_ENTER( "just justData" );
507
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 );
513
514 GXV_TRACE(( " (justClassTableOffset = 0x%04x)\n", justClassTableOffset ));
515 GXV_TRACE(( " (wdcTableOffset = 0x%04x)\n", wdcTableOffset ));
516 GXV_TRACE(( " (pcTableOffset = 0x%04x)\n", pcTableOffset ));
517
518 gxv_just_justData_lookuptable_validate( p, limit, valid );
519 gxv_odtect_add_range( p, valid->subtable_length,
520 "just_LookupTable", odtect );
521
522 if ( wdcTableOffset )
523 {
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 );
528 }
529
530 if ( pcTableOffset )
531 {
532 gxv_just_postcompTable_validate( valid->root->base + pcTableOffset,
533 limit, valid );
534 gxv_odtect_add_range( valid->root->base + pcTableOffset,
535 valid->subtable_length, "just_pcTable", odtect );
536 }
537
538 if ( justClassTableOffset )
539 {
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",
544 odtect );
545 }
546
547 gxv_odtect_validate( odtect, valid );
548
549 GXV_EXIT;
550 }
551
552
553 FT_LOCAL_DEF( void )
554 gxv_just_validate( FT_Bytes table,
555 FT_Face face,
556 FT_Validator ftvalid )
557 {
558 FT_Bytes p = table;
559 FT_Bytes limit = 0;
560 FT_Offset table_size;
561
562 GXV_ValidatorRec validrec;
563 GXV_Validator valid = &validrec;
564 GXV_just_DataRec justrec;
565 GXV_just_Data just = &justrec;
566
567 FT_ULong version;
568 FT_UShort format;
569 FT_UShort horizOffset;
570 FT_UShort vertOffset;
571
572 GXV_ODTECT( 3, odtect );
573
574
575 GXV_ODTECT_INIT( odtect );
576
577 valid->root = ftvalid;
578 valid->table_data = just;
579 valid->face = face;
580
581 FT_TRACE3(( "validating `just' table\n" ));
582 GXV_INIT;
583
584 limit = valid->root->limit;
585 table_size = limit - table;
586
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 );
593
594
595 /* Version 1.0 (always:2000) */
596 GXV_TRACE(( " (version = 0x%08x)\n", version ));
597 if ( version != 0x00010000UL )
598 FT_INVALID_FORMAT;
599
600 /* format 0 (always:2000) */
601 GXV_TRACE(( " (format = 0x%04x)\n", format ));
602 if ( format != 0x0000 )
603 FT_INVALID_FORMAT;
604
605 GXV_TRACE(( " (horizOffset = %d)\n", horizOffset ));
606 GXV_TRACE(( " (vertOffset = %d)\n", vertOffset ));
607
608
609 /* validate justData */
610 if ( 0 < horizOffset )
611 {
612 gxv_just_justData_validate( table + horizOffset, limit, valid );
613 gxv_odtect_add_range( table + horizOffset, valid->subtable_length,
614 "horizJustData", odtect );
615 }
616
617 if ( 0 < vertOffset )
618 {
619 gxv_just_justData_validate( table + vertOffset, limit, valid );
620 gxv_odtect_add_range( table + vertOffset, valid->subtable_length,
621 "vertJustData", odtect );
622 }
623
624 gxv_odtect_validate( odtect, valid );
625
626 FT_TRACE4(( "\n" ));
627 }
628
629
630 /* END */