4 /************************************************************************/
5 /************************************************************************/
7 /***** GSUB LOOKUP TYPE 1 *****/
9 /************************************************************************/
10 /************************************************************************/
13 * 1: Single Substitution - Table format(s)
15 * This table is used to substiture individual glyph indices
16 * with another one. There are only two sub-formats:
18 * Name Offset Size Description
19 * ------------------------------------------
20 * format 0 2 sub-table format (1)
21 * offset 2 2 offset to coverage table
22 * delta 4 2 16-bit delta to apply on all
23 * covered glyph indices
25 * Name Offset Size Description
26 * ------------------------------------------
27 * format 0 2 sub-table format (2)
28 * offset 2 2 offset to coverage table
29 * count 4 2 coverage table count
30 * substs[] 6 2*count substituted glyph indices,
35 otl_gsub_lookup1_validate( OTL_Bytes table
,
42 format
= OTL_NEXT_USHORT( p
);
50 coverage
= OTL_NEXT_USHORT( p
);
52 otl_coverage_validate( table
+ coverage
, valid
);
58 OTL_UInt coverage
, count
;
61 coverage
= OTL_NEXT_USHORT( p
);
62 count
= OTL_NEXT_USHORT( p
);
64 otl_coverage_validate( table
+ coverage
, valid
);
68 /* NB: we don't check that there are at most 'count' */
69 /* elements in the coverage table. This is delayed */
70 /* to the lookup function... */
81 otl_gsub_lookup1_apply( OTL_Bytes table
,
86 OTL_UInt format
, gindex
, property
;
90 if ( parser
->context_len
!= 0xFFFFU
&& parser
->context_len
< 1 )
93 gindex
= otl_parser_get_gindex( parser
);
95 if ( !otl_parser_check_property( parser
, gindex
, &property
) )
98 format
= OTL_NEXT_USHORT(p
);
99 coverage
= table
+ OTL_NEXT_USHORT(p
);
100 index
= otl_coverage_lookup( coverage
, gindex
);
108 OTL_Int delta
= OTL_NEXT_SHORT(p
);
110 gindex
= ( gindex
+ delta
) & 0xFFFFU
;
111 otl_parser_replace_1( parser
, gindex
);
118 OTL_UInt count
= OTL_NEXT_USHORT(p
);
120 if ( (OTL_UInt
) index
< count
)
123 otl_parser_replace_1( parser
, OTL_PEEK_USHORT(p
) );
137 /************************************************************************/
138 /************************************************************************/
140 /***** GSUB LOOKUP TYPE 2 *****/
142 /************************************************************************/
143 /************************************************************************/
146 * 2: Multiple Substitution - Table format(s)
148 * Replaces a single glyph with one or more glyphs.
150 * Name Offset Size Description
151 * -----------------------------------------------------------
152 * format 0 2 sub-table format (1)
153 * offset 2 2 offset to coverage table
154 * count 4 2 coverage table count
155 * sequencess[] 6 2*count offsets to sequence items
157 * each sequence item has the following format:
159 * Name Offset Size Description
160 * -----------------------------------------------------------
161 * count 0 2 number of replacement glyphs
162 * gindices[] 2 2*count string of glyph indices
166 otl_seq_validate( OTL_Bytes table
,
167 OTL_Validator valid
)
173 count
= OTL_NEXT_USHORT( p
);
175 /* XXX: according to the spec, 'count' should be > 0 */
176 /* we can deal with these cases pretty well however */
178 OTL_CHECK( 2*count
);
179 /* check glyph indices */
184 otl_gsub_lookup2_validate( OTL_Bytes table
,
185 OTL_Validator valid
)
188 OTL_UInt format
, coverage
;
191 format
= OTL_NEXT_USHORT( p
);
196 OTL_UInt coverage
, seq_count
;
199 coverage
= OTL_NEXT_USHORT( p
);
200 seq_count
= OTL_NEXT_USHORT( p
);
202 otl_coverage_validate( table
+ coverage
, valid
);
204 OTL_CHECK( seq_count
*2 );
205 for ( ; seq_count
> 0; seq_count
-- )
206 otl_seq_validate( table
+ OTL_NEXT_USHORT( p
), valid
);
217 otl_gsub_lookup2_apply( OTL_Bytes table
,
221 OTL_Bytes coverage
, sequence
;
222 OTL_UInt format
, gindex
, index
, property
;
226 if ( context_len
!= 0xFFFFU
&& context_len
< 1 )
229 gindex
= otl_parser_get_gindex( parser
);
231 if ( !otl_parser_check_property( parser
, gindex
, &property
) )
234 p
+= 2; /* skip format */
235 coverage
= table
+ OTL_NEXT_USHORT(p
);
236 seq_count
= OTL_NEXT_USHORT(p
);
237 index
= otl_coverage_lookup( coverage
, gindex
);
239 if ( (OTL_UInt
) index
>= seq_count
)
243 sequence
= table
+ OTL_PEEK_USHORT(p
);
245 count
= OTL_NEXT_USHORT(p
);
247 otl_parser_replace_n( parser
, count
, p
);
254 /************************************************************************/
255 /************************************************************************/
257 /***** GSUB LOOKUP TYPE 3 *****/
259 /************************************************************************/
260 /************************************************************************/
263 * 3: Alternate Substitution - Table format(s)
265 * Replaces a single glyph by another one taken liberally
266 * in a list of alternatives
268 * Name Offset Size Description
269 * -----------------------------------------------------------
270 * format 0 2 sub-table format (1)
271 * offset 2 2 offset to coverage table
272 * count 4 2 coverage table count
273 * alternates[] 6 2*count offsets to alternate items
275 * each alternate item has the following format:
277 * Name Offset Size Description
278 * -----------------------------------------------------------
279 * count 0 2 number of replacement glyphs
280 * gindices[] 2 2*count string of glyph indices, each one
281 * is a valid alternative
285 otl_alternate_set_validate( OTL_Bytes table
,
286 OTL_Validator valid
)
292 count
= OTL_NEXT_USHORT( p
);
294 OTL_CHECK( 2*count
);
295 /* XXX: check glyph indices */
300 otl_gsub_lookup3_validate( OTL_Bytes table
,
301 OTL_Validator valid
)
304 OTL_UInt format
, coverage
;
307 format
= OTL_NEXT_USHORT( p
);
312 OTL_UInt coverage
, count
;
315 coverage
= OTL_NEXT_USHORT( p
);
316 count
= OTL_NEXT_USHORT( p
);
318 otl_coverage_validate( table
+ coverage
, valid
);
320 OTL_CHECK( 2*count
);
321 for ( ; count
> 0; count
-- )
322 otl_alternate_set_validate( table
+ OTL_NEXT_USHORT( p
), valid
);
333 otl_gsub_lookup3_apply( OTL_Bytes table
,
337 OTL_Bytes coverage
, alternates
;
338 OTL_UInt format
, gindex
, index
, property
;
342 OTL_GSUB_Alternate alternate
= parser
->alternate
;
344 if ( context_len
!= 0xFFFFU
&& context_len
< 1 )
347 if ( alternate
== NULL
)
350 gindex
= otl_parser_get_gindex( parser
);
352 if ( !otl_parser_check_property( parser
, gindex
, &property
) )
355 p
+= 2; /* skip format */
356 coverage
= table
+ OTL_NEXT_USHORT(p
);
357 seq_count
= OTL_NEXT_USHORT(p
);
358 index
= otl_coverage_lookup( coverage
, gindex
);
360 if ( (OTL_UInt
) index
>= seq_count
)
364 alternates
= table
+ OTL_PEEK_USHORT(p
);
366 count
= OTL_NEXT_USHORT(p
);
368 gindex
= alternate
->handler_func(
369 gindex
, count
, p
, alternate
->handler_data
);
371 otl_parser_replace_1( parser
, gindex
);
378 /************************************************************************/
379 /************************************************************************/
381 /***** GSUB LOOKUP TYPE 4 *****/
383 /************************************************************************/
384 /************************************************************************/
387 otl_ligature_validate( OTL_Bytes table
,
388 OTL_Validator valid
)
390 OTL_UInt glyph_id
, count
;
393 glyph_id
= OTL_NEXT_USHORT( p
);
394 count
= OTL_NEXT_USHORT( p
);
399 OTL_CHECK( 2*(count
-1) );
400 /* XXX: check glyph indices */
405 otl_ligature_set_validate( OTL_Bytes table
,
406 OTL_Validator valid
)
412 count
= OTL_NEXT_USHORT( p
);
414 OTL_CHECK( 2*count
);
415 for ( ; count
> 0; count
-- )
416 otl_ligature_validate( table
+ OTL_NEXT_USHORT( p
), valid
);
421 otl_gsub_lookup4_validate( OTL_Bytes table
,
422 OTL_Validator valid
)
425 OTL_UInt format
, coverage
;
428 format
= OTL_NEXT_USHORT( p
);
433 OTL_UInt coverage
, count
;
436 coverage
= OTL_NEXT_USHORT( p
);
437 count
= OTL_NEXT_USHORT( p
);
439 otl_coverage_validate( table
+ coverage
, valid
);
441 OTL_CHECK( 2*count
);
442 for ( ; count
> 0; count
-- )
443 otl_ligature_set_validate( table
+ OTL_NEXT_USHORT( p
), valid
);
453 /************************************************************************/
454 /************************************************************************/
456 /***** GSUB LOOKUP TYPE 5 *****/
458 /************************************************************************/
459 /************************************************************************/
463 otl_sub_rule_validate( OTL_Bytes table
,
464 OTL_Validator valid
)
467 OTL_UInt glyph_count
, subst_count
;
470 glyph_count
= OTL_NEXT_USHORT( p
);
471 subst_count
= OTL_NEXT_USHORT( p
);
473 if ( glyph_count
== 0 )
476 OTL_CHECK( (glyph_count
-1)*2 + substcount
*4 );
478 /* XXX: check glyph indices and subst lookups */
483 otl_sub_rule_set_validate( OTL_Bytes table
,
484 OTL_Validator valid
)
490 count
= OTL_NEXT_USHORT( p
);
492 OTL_CHECK( 2*count
);
493 for ( ; count
> 0; count
-- )
494 otl_sub_rule_validate( table
+ OTL_NEXT_USHORT( p
), valid
);
499 otl_sub_class_rule_validate( OTL_Bytes table
,
500 OTL_Validator valid
)
502 OTL_UInt glyph_count
, subst_count
;
505 glyph_count
= OTL_NEXT_USHORT( p
);
506 subst_count
= OTL_NEXT_USHORT( p
);
508 if ( glyph_count
== 0 )
511 OTL_CHECK( (glyph_count
-1)*2 + substcount
*4 );
513 /* XXX: check glyph indices and subst lookups */
518 otl_sub_class_rule_set_validate( OTL_Bytes table
,
519 OTL_Validator valid
)
525 count
= OTL_NEXT_USHORT( p
);
527 OTL_CHECK( 2*count
);
528 for ( ; count
> 0; count
-- )
529 otl_sub_class_rule_validate( table
+ OTL_NEXT_USHORT( p
), valid
);
534 otl_gsub_lookup5_validate( OTL_Bytes table
,
535 OTL_Validator valid
)
538 OTL_UInt format
, coverage
;
541 format
= OTL_NEXT_USHORT( p
);
546 OTL_UInt coverage
, count
;
549 coverage
= OTL_NEXT_USHORT( p
);
550 count
= OTL_NEXT_USHORT( p
);
552 otl_coverage_validate( table
+ coverage
, valid
);
554 OTL_CHECK( 2*count
);
555 for ( ; count
> 0; count
-- )
556 otl_sub_rule_set_validate( table
+ coverage
, valid
);
562 OTL_UInt coverage
, class_def
, count
;
565 coverage
= OTL_NEXT_USHORT( p
);
566 class_def
= OTL_NEXT_USHORT( p
);
567 count
= OTL_NEXT_USHORT( p
);
569 otl_coverage_validate ( table
+ coverage
, valid
);
570 otl_class_definition_validate( table
+ class_def
, valid
);
572 OTL_CHECK( 2*count
);
573 for ( ; count
> 0; count
-- )
574 otl_sub_class_rule_set_validate( table
+ coveragen valid
);
580 OTL_UInt glyph_count
, subst_count
, count
;
583 glyph_count
= OTL_NEXT_USHORT( p
);
584 subst_count
= OTL_NEXT_USHORT( p
);
586 OTL_CHECK( 2*glyph_count
+ 4*subst_count
);
587 for ( count
= glyph_count
; count
> 0; count
-- )
588 otl_coverage_validate( table
+ OTL_NEXT_USHORT( p
), valid
);
598 /************************************************************************/
599 /************************************************************************/
601 /***** GSUB LOOKUP TYPE 6 *****/
603 /************************************************************************/
604 /************************************************************************/
608 otl_chain_sub_rule_validate( OTL_Bytes table
,
609 OTL_Validator valid
)
612 OTL_UInt back_count
, input_count
, ahead_count
, subst_count
, count
;
615 back_count
= OTL_NEXT_USHORT( p
);
617 OTL_CHECK( 2*back_count
+2 );
620 input_count
= OTL_NEXT_USHORT( p
);
621 if ( input_count
== 0 )
624 OTL_CHECK( 2*input_count
);
625 p
+= 2*(input_count
-1);
627 ahead_count
= OTL_NEXT_USHORT( p
);
628 OTL_CHECK( 2*ahead_count
+ 2 );
631 count
= OTL_NEXT_USHORT( p
);
632 OTL_CHECK( 4*count
);
634 /* XXX: check glyph indices and subst lookups */
639 otl_chain_sub_rule_set_validate( OTL_Bytes table
,
640 OTL_Validator valid
)
646 count
= OTL_NEXT_USHORT( p
);
648 OTL_CHECK( 2*count
);
649 for ( ; count
> 0; count
-- )
650 otl_chain_sub_rule_validate( table
+ OTL_NEXT_USHORT( p
), valid
);
655 otl_chain_sub_class_rule_validate( OTL_Bytes table
,
656 OTL_Validator valid
)
659 OTL_UInt back_count
, input_count
, ahead_count
, subst_count
, count
;
662 back_count
= OTL_NEXT_USHORT( p
);
664 OTL_CHECK( 2*back_count
+2 );
667 input_count
= OTL_NEXT_USHORT( p
);
668 if ( input_count
== 0 )
671 OTL_CHECK( 2*input_count
);
672 p
+= 2*(input_count
-1);
674 ahead_count
= OTL_NEXT_USHORT( p
);
675 OTL_CHECK( 2*ahead_count
+ 2 );
678 count
= OTL_NEXT_USHORT( p
);
679 OTL_CHECK( 4*count
);
681 /* XXX: check class indices and subst lookups */
687 otl_chain_sub_class_set_validate( OTL_Bytes table
,
688 OTL_Validator valid
)
694 count
= OTL_NEXT_USHORT( p
);
696 OTL_CHECK( 2*count
);
697 for ( ; count
> 0; count
-- )
698 otl_chain_sub_rule_validate( table
+ OTL_NEXT_USHORT( p
), valid
);
703 otl_gsub_lookup6_validate( OTL_Bytes table
,
704 OTL_Validator valid
)
707 OTL_UInt format
, coverage
;
710 format
= OTL_NEXT_USHORT( p
);
715 OTL_UInt coverage
, count
;
718 coverage
= OTL_NEXT_USHORT( p
);
719 count
= OTL_NEXT_USHORT( p
);
721 otl_coverage_validate( table
+ coverage
, valid
);
723 OTL_CHECK( 2*count
);
724 for ( ; count
> 0; count
-- )
725 otl_chain_sub_rule_set_validate( table
+ coverage
, valid
);
731 OTL_UInt coverage
, back_class
, input_class
, ahead_class
, count
;
734 coverage
= OTL_NEXT_USHORT( p
);
735 back_class
= OTL_NEXT_USHORT( p
);
736 input_class
= OTL_NEXT_USHORT( p
);
737 ahead_class
= OTL_NEXT_USHORT( p
);
738 count
= OTL_NEXT_USHORT( p
);
740 otl_coverage_validate( table
+ coverage
, valid
);
742 otl_class_definition_validate( table
+ back_class
, valid
);
743 otl_class_definition_validate( table
+ input_class
, valid
);
744 otl_class_definition_validate( table
+ ahead_class
, valid
);
746 OTL_CHECK( 2*count
);
747 for ( ; count
> 0; count
-- )
748 otl_chain_sub_class_set( table
+ OTL_NEXT_USHORT( p
), valid
);
754 OTL_UInt back_count
, input_count
, ahead_count
, subst_count
, count
;
757 back_count
= OTL_NEXT_USHORT( p
);
759 OTL_CHECK( 2*back_count
+2 );
760 for ( count
= back_count
; count
> 0; count
-- )
761 otl_coverage_validate( table
+ OTL_NEXT_USHORT( p
), valid
);
763 input_count
= OTL_NEXT_USHORT( p
);
765 OTL_CHECK( 2*input_count
+2 );
766 for ( count
= input_count
; count
> 0; count
-- )
767 otl_coverage_validate( table
+ OTL_NEXT_USHORT( p
), valid
);
769 ahead_count
= OTL_NEXT_USHORT( p
);
771 OTL_CHECK( 2*ahead_count
+2 );
772 for ( count
= ahead_count
; count
> 0; count
-- )
773 otl_coverage_validate( table
+ OTL_NEXT_USHORT( p
), valid
);
775 subst_count
= OTL_NEXT_USHORT( p
);
776 OTL_CHECK( subst_count
*4 );
785 /************************************************************************/
786 /************************************************************************/
788 /***** GSUB LOOKUP TYPE 6 *****/
790 /************************************************************************/
791 /************************************************************************/
794 otl_gsub_lookup7_validate( OTL_Bytes table
,
795 OTL_Validator valid
)
798 OTL_UInt format
, coverage
;
801 format
= OTL_NEXT_USHORT( p
);
806 OTL_UInt lookup_type
, lookup_offset
;
807 OTL_ValidateFunc validate
;
810 lookup_type
= OTL_NEXT_USHORT( p
);
811 lookup_offset
= OTL_NEXT_ULONG( p
);
813 if ( lookup_type
== 0 || lookup_type
>= 7 )
816 validate
= otl_gsub_validate_funcs
[ lookup_type
-1 ];
817 validate( table
+ lookup_offset
, valid
);
827 static const OTL_ValidateFunc otl_gsub_validate_funcs
[ 7 ] =
829 otl_gsub_lookup1_validate
,
830 otl_gsub_lookup2_validate
,
831 otl_gsub_lookup3_validate
,
832 otl_gsub_lookup4_validate
,
833 otl_gsub_lookup5_validate
,
834 otl_gsub_lookup6_validate
837 /************************************************************************/
838 /************************************************************************/
840 /***** GSUB TABLE *****/
842 /************************************************************************/
843 /************************************************************************/
847 otl_gsub_validate( OTL_Bytes table
,
848 OTL_Validator valid
)
851 OTL_UInt scripts
, features
, lookups
;
855 if ( OTL_NEXT_USHORT( p
) != 0x10000UL
)
858 scripts
= OTL_NEXT_USHORT( p
);
859 features
= OTL_NEXT_USHORT( p
);
860 lookups
= OTL_NEXT_USHORT( p
);
862 otl_script_list_validate ( table
+ scripts
, valid
);
863 otl_feature_list_validate( table
+ features
, valid
);
865 otl_lookup_list_validate( table
+ lookups
, 7, otl_gsub_validate_funcs
,