29#ifdef TT_CONFIG_OPTION_GPOS_KERNING
39#define FT_COMPONENT ttgpos
49 tt_face_validate_coverage( FT_Byte* table,
51 FT_UInt max_num_coverage_indices )
61 if ( table_limit < p + 4 )
64 format = FT_NEXT_USHORT( p );
67 FT_UInt glyphCount = FT_NEXT_USHORT( p );
70 if ( glyphCount > max_num_coverage_indices )
73 limit = p + glyphCount * 2;
74 if ( table_limit < limit )
79 FT_UInt
id = FT_NEXT_USHORT( p );
87 else if ( format == 2 )
89 FT_UInt rangeCount = FT_NEXT_USHORT( p );
92 limit = p + rangeCount * 6;
93 if ( table_limit < limit )
98 FT_UInt startGlyphID = FT_NEXT_USHORT( p );
99 FT_UInt endGlyphID = FT_NEXT_USHORT( p );
100 FT_UInt startCoverageIndex = FT_NEXT_USHORT( p );
103 if ( startGlyphID > endGlyphID )
106 if ( last_id >= startGlyphID )
108 last_id = endGlyphID;
111 if ( startCoverageIndex + endGlyphID - startGlyphID >=
112 max_num_coverage_indices )
124 tt_face_validate_class_def( FT_Byte* table,
125 FT_Byte* table_limit,
126 FT_UInt num_classes )
133 FT_UInt max_class_value = 0;
136 if ( table_limit < p + 2 )
139 format = FT_NEXT_USHORT( p );
145 if ( table_limit < p + 4 )
150 glyphCount = FT_NEXT_USHORT( p );
151 limit = p + glyphCount * 2;
152 if ( table_limit < limit )
157 FT_UInt class_value = FT_NEXT_USHORT( p );
160 if ( class_value > max_class_value )
161 max_class_value = class_value;
164 else if ( format == 2 )
166 FT_UInt classRangeCount;
167 FT_Long last_id = -1;
170 if ( table_limit < p + 2 )
173 classRangeCount = FT_NEXT_USHORT( p );
174 limit = p + classRangeCount * 6;
175 if ( table_limit < limit )
180 FT_UInt startGlyphID = FT_NEXT_USHORT( p );
181 FT_UInt endGlyphID = FT_NEXT_USHORT( p );
182 FT_UInt class_value = FT_NEXT_USHORT( p );
185 if ( startGlyphID > endGlyphID )
188 if ( last_id >= startGlyphID )
190 last_id = endGlyphID;
192 if ( class_value > max_class_value )
193 max_class_value = class_value;
199 if ( max_class_value + 1 != num_classes )
207 tt_face_validate_feature( FT_Byte* table,
208 FT_Byte* table_limit,
209 FT_UInt use_lookup_table_size,
210 FT_Byte* use_lookup_table )
212 FT_UInt lookupIndexCount;
218 if ( table_limit < p + 4 )
223 lookupIndexCount = FT_NEXT_USHORT( p );
224 limit = p + lookupIndexCount * 2;
225 if ( table_limit < limit )
230 FT_UInt lookup_index = FT_NEXT_USHORT( p );
233 if ( lookup_index >= use_lookup_table_size )
236 use_lookup_table[lookup_index] = TRUE;
244 tt_face_validate_feature_table( FT_Byte* table,
245 FT_Byte* table_limit,
246 FT_UInt use_lookup_table_size,
247 FT_Byte* use_lookup_table )
249 FT_UInt featureCount;
255 if ( table_limit < p + 2 )
258 featureCount = FT_NEXT_USHORT( p );
259 limit = p + featureCount * 6;
260 if ( table_limit < limit )
267 FT_ULong featureTag = FT_NEXT_ULONG( p );
268 FT_UInt featureOffset = FT_NEXT_USHORT( p );
271 if ( featureTag == TTAG_kern )
273 if ( !tt_face_validate_feature( table + featureOffset,
275 use_lookup_table_size,
286 tt_face_validate_pair_set( FT_Byte* table,
287 FT_Byte* table_limit )
289 FT_UInt pairValueCount;
294 FT_Long last_id = -1;
297 if ( table_limit < p + 2 )
303 pairValueCount = FT_NEXT_USHORT( p );
304 limit = p + pairValueCount * 4;
305 if ( table_limit < limit )
311 FT_UInt
id = FT_NEXT_USHORT( p );
327 tt_face_validate_pair_pos1( FT_Byte* table,
328 FT_Byte* table_limit,
329 FT_Bool* is_fitting )
332 FT_UInt valueFormat1;
333 FT_UInt valueFormat2;
336 FT_Byte* p = table + 2;
342 coverage = table + FT_NEXT_USHORT( p );
348 valueFormat1 = FT_NEXT_USHORT( p );
349 valueFormat2 = FT_NEXT_USHORT( p );
350 if ( valueFormat1 == 0x4 && valueFormat2 == 0 )
352 FT_UInt pairSetCount;
355 if ( table_limit < p + 2 )
358 pairSetCount = FT_NEXT_USHORT( p );
359 limit = p + pairSetCount * 2;
360 if ( table_limit < limit )
363 if ( !tt_face_validate_coverage( coverage,
370 FT_Byte* pair_set = table + FT_NEXT_USHORT( p );
373 if ( !tt_face_validate_pair_set( pair_set, table_limit ) )
385 tt_face_validate_pair_pos2( FT_Byte* table,
386 FT_Byte* table_limit,
387 FT_Bool* is_fitting )
390 FT_UInt valueFormat1;
391 FT_UInt valueFormat2;
394 FT_Byte* p = table + 2;
400 coverage = table + FT_NEXT_USHORT( p );
402 valueFormat1 = FT_NEXT_USHORT( p );
403 valueFormat2 = FT_NEXT_USHORT( p );
404 if ( valueFormat1 == 0x4 && valueFormat2 == 0 )
413 if ( !tt_face_validate_coverage( coverage, table_limit, FT_UINT_MAX ) )
416 if ( table_limit < p + 8 )
419 class_def1 = table + FT_NEXT_USHORT( p );
420 class_def2 = table + FT_NEXT_USHORT( p );
421 class1Count = FT_NEXT_USHORT( p );
422 class2Count = FT_NEXT_USHORT( p );
424 if ( !tt_face_validate_class_def( class_def1,
428 if ( !tt_face_validate_class_def( class_def2,
435 limit = p + class1Count * class2Count * 2;
436 if ( table_limit < limit )
448 tt_face_validate_lookup_table( FT_Byte* table,
449 FT_Byte* table_limit )
452 FT_UInt real_lookupType = 0;
453 FT_UInt subtableCount;
458 FT_UInt num_fitting_subtables = 0;
461 if ( table_limit < p + 6 )
464 lookupType = FT_NEXT_USHORT( p );
468 subtableCount = FT_NEXT_USHORT( p );
469 limit = p + subtableCount * 2;
470 if ( table_limit < limit )
475 FT_Byte* subtable = table + FT_NEXT_USHORT( p );
478 FT_Bool is_fitting = FALSE;
481 if ( lookupType == 9 )
484 FT_Byte* q = subtable;
487 if ( table_limit < q + 8 )
490 if ( FT_NEXT_USHORT( q ) != 1 )
493 if ( real_lookupType == 0 )
494 real_lookupType = FT_NEXT_USHORT( q );
495 else if ( real_lookupType != FT_NEXT_USHORT( q ) )
498 subtable += FT_PEEK_ULONG( q );
501 real_lookupType = lookupType;
504 if ( table_limit < subtable + 8 )
507 format = FT_PEEK_USHORT( subtable );
509 if ( real_lookupType == 2 )
513 if ( !tt_face_validate_pair_pos1( subtable,
518 else if ( format == 2 )
520 if ( !tt_face_validate_pair_pos2( subtable,
532 num_fitting_subtables++;
535 return num_fitting_subtables;
540 tt_face_get_subtable_offsets( FT_Byte* table,
542 FT_UInt32* gpos_lookups_kerning,
546 FT_UInt subtableCount;
552 lookupType = FT_NEXT_USHORT( p );
556 subtableCount = FT_NEXT_USHORT( p );
557 limit = p + subtableCount * 2;
560 FT_Byte* subtable = table + FT_NEXT_USHORT( p );
561 FT_UInt valueFormat1;
562 FT_UInt valueFormat2;
565 if ( lookupType == 9 )
566 subtable += FT_PEEK_ULONG( subtable + 4 );
570 valueFormat1 = FT_PEEK_USHORT( subtable + 4 );
571 valueFormat2 = FT_PEEK_USHORT( subtable + 6 );
572 if ( valueFormat1 == 0x4 && valueFormat2 == 0 )
575 gpos_lookups_kerning[(*idx)++] = (FT_UInt32)( subtable - gpos );
581 FT_LOCAL_DEF( FT_Error )
582 tt_face_load_gpos( TT_Face face,
586 FT_Memory memory = face->root.memory;
588 FT_ULong gpos_length;
592 FT_UInt32* gpos_lookups_kerning;
594 FT_UInt featureListOffset;
596 FT_UInt lookupListOffset;
597 FT_Byte* lookup_list;
602 FT_Byte* use_lookup_table = NULL;
603 FT_UInt num_fitting_subtables;
609 face->gpos_table = NULL;
610 face->gpos_lookups_kerning = NULL;
611 face->num_gpos_lookups_kerning = 0;
614 gpos_lookups_kerning = NULL;
616 error = face->goto_table( face, TTAG_GPOS, stream, &gpos_length );
620 if ( FT_FRAME_EXTRACT( gpos_length, gpos ) )
623 if ( gpos_length < 10 )
626 gpos_limit = gpos + gpos_length;
629 lookupListOffset = FT_PEEK_USHORT( gpos + 8 );
631 lookup_list = gpos + lookupListOffset;
633 if ( gpos_limit < p + 2 )
636 lookupCount = FT_NEXT_USHORT( p );
637 limit = p + lookupCount * 2;
638 if ( gpos_limit < limit )
643 if ( FT_NEW_ARRAY( use_lookup_table, lookupCount ) )
646 featureListOffset = FT_PEEK_USHORT( gpos + 6 );
648 if ( !tt_face_validate_feature_table( gpos + featureListOffset,
656 num_fitting_subtables = 0;
657 for ( i = 0; i < lookupCount; i++ )
659 FT_UInt lookupOffset;
662 if ( !use_lookup_table[i] )
665 lookupOffset = FT_PEEK_USHORT( p + i * 2 );
667 num_fitting_subtables +=
668 tt_face_validate_lookup_table( lookup_list + lookupOffset,
675 if ( num_fitting_subtables )
680 if ( FT_QNEW_ARRAY( gpos_lookups_kerning, num_fitting_subtables ) )
684 for ( i = 0; i < lookupCount; i++ )
686 FT_UInt lookupOffset;
689 if ( !use_lookup_table[i] )
692 lookupOffset = FT_PEEK_USHORT( p + i * 2 );
694 tt_face_get_subtable_offsets( lookup_list + lookupOffset,
696 gpos_lookups_kerning,
701 FT_FREE( use_lookup_table );
702 use_lookup_table = NULL;
704 face->gpos_table = gpos;
705 face->gpos_lookups_kerning = gpos_lookups_kerning;
706 face->num_gpos_lookups_kerning = num_fitting_subtables;
713 FT_FREE( gpos_lookups_kerning );
714 FT_FREE( use_lookup_table );
718 error = FT_THROW( Invalid_Table );
725 tt_face_done_gpos( TT_Face face )
727 FT_Stream stream = face->root.stream;
728 FT_Memory memory = face->root.memory;
731 FT_FRAME_RELEASE( face->gpos_table );
732 FT_FREE( face->gpos_lookups_kerning );
744 tt_face_get_coverage_index( FT_Byte* table,
745 FT_UInt glyph_index )
748 FT_UInt format = FT_NEXT_USHORT( p );
749 FT_UInt count = FT_NEXT_USHORT( p );
761 FT_UInt mid = min + ( max - min ) / 2;
762 FT_UInt mid_index = FT_PEEK_USHORT( p + mid * 2 );
765 if ( glyph_index > mid_index )
767 else if ( glyph_index < mid_index )
777 FT_UInt mid = min + ( max - min ) / 2;
778 FT_UInt startGlyphID = FT_PEEK_USHORT( p + mid * 6 );
779 FT_UInt endGlyphID = FT_PEEK_USHORT( p + mid * 6 + 2 );
782 if ( glyph_index > endGlyphID )
784 else if ( glyph_index < startGlyphID )
788 FT_UInt startCoverageIndex = FT_PEEK_USHORT( p + mid * 6 + 4 );
791 return startCoverageIndex + glyph_index - startGlyphID;
801 tt_face_get_class( FT_Byte* table,
802 FT_UInt glyph_index )
805 FT_UInt format = FT_NEXT_USHORT( p );
810 FT_UInt startGlyphID = FT_NEXT_USHORT( p );
811 FT_UInt glyphCount = FT_NEXT_USHORT( p );
815 if ( startGlyphID <= glyph_index &&
816 startGlyphID + glyphCount >= glyph_index )
817 return FT_PEEK_USHORT( p + ( glyph_index - startGlyphID ) * 2 );
821 FT_UInt count = FT_NEXT_USHORT( p );
831 FT_UInt mid = min + ( max - min ) / 2;
832 FT_UInt startGlyphID = FT_PEEK_USHORT( p + mid * 6 );
833 FT_UInt endGlyphID = FT_PEEK_USHORT( p + mid * 6 + 2 );
836 if ( glyph_index > endGlyphID )
838 else if ( glyph_index < startGlyphID )
841 return FT_PEEK_USHORT( p + mid * 6 + 4 );
850 tt_face_get_pair_pos1_kerning( FT_Byte* table,
852 FT_UInt second_glyph,
855 FT_Byte* coverage = table + FT_PEEK_USHORT( table + 2 );
856 FT_Long coverage_index = tt_face_get_coverage_index( coverage,
859 FT_UInt pair_set_offset;
866 if ( coverage_index < 0 )
869 pair_set_offset = FT_PEEK_USHORT( table + 10 + coverage_index * 2 );
870 p = table + pair_set_offset;
871 count = FT_NEXT_USHORT( p );
878 FT_UInt mid = min + ( max - min ) / 2;
879 FT_UInt mid_index = FT_PEEK_USHORT( p + mid * 4 );
882 if ( second_glyph > mid_index )
884 else if ( second_glyph < mid_index )
888 *kerning = FT_PEEK_SHORT( p + mid * 4 + 2 );
899 tt_face_get_pair_pos2_kerning( FT_Byte* table,
901 FT_UInt second_glyph,
904 FT_Byte* coverage = table + FT_PEEK_USHORT( table + 2 );
905 FT_Long coverage_index = tt_face_get_coverage_index( coverage,
911 FT_UInt second_class;
915 if ( coverage_index < 0 )
918 class_def1 = table + FT_PEEK_USHORT( table + 8 );
919 class_def2 = table + FT_PEEK_USHORT( table + 10 );
921 class2Count = FT_PEEK_USHORT( table + 14 );
923 first_class = tt_face_get_class( class_def1, first_glyph );
924 second_class = tt_face_get_class( class_def2, second_glyph );
927 FT_PEEK_SHORT( table + 16 +
928 ( first_class * class2Count + second_class ) * 2 );
934 FT_LOCAL_DEF( FT_Int )
935 tt_face_get_gpos_kerning( TT_Face face,
937 FT_UInt second_glyph )
945 for ( i = 0; i < face->num_gpos_lookups_kerning; i++ )
947 FT_Byte* subtable = face->gpos_table + face->gpos_lookups_kerning[i];
948 FT_Byte* p = subtable;
950 FT_UInt format = FT_NEXT_USHORT( p );
955 if ( tt_face_get_pair_pos1_kerning( subtable,
963 if ( tt_face_get_pair_pos2_kerning( subtable,
977 typedef int tt_gpos_dummy_;