1 /*******************************************************************
5 * TrueType Open GPOS table support.
7 * Copyright 1996-1999 by
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 /* XXX There is *a lot* of duplicated code (cf. formats 7 and 8), but
19 I don't care currently. I believe that it would be possible to
20 save about 50% of TTO code by carefully designing the structures,
21 sharing as much as possible with extensive use of macros. This
22 is something for a volunteer :-) */
35 #define GPOS_ID Build_Extension_ID( 'G', 'P', 'O', 'S' )
39 /**********************
41 **********************/
44 static TT_Error
GPOS_Create( void* ext
,
47 DEFINE_LOAD_LOCALS( face
->stream
);
49 TTO_GPOSHeader
* gpos
= (TTO_GPOSHeader
*)ext
;
58 /* a null offset indicates that there is no GPOS table */
62 /* we store the start offset and the size of the subtable */
64 table
= TT_LookUp_Table( face
, TTAG_GPOS
);
66 return TT_Err_Ok
; /* The table is optional */
68 if ( FILE_Seek( face
->dirTables
[table
].Offset
) ||
72 gpos
->offset
= FILE_Pos() - 4L; /* undo ACCESS_Frame() */
73 gpos
->Version
= GET_ULong();
83 static TT_Error
GPOS_Destroy( void* ext
,
86 TTO_GPOSHeader
* gpos
= (TTO_GPOSHeader
*)ext
;
96 Free_LookupList( &gpos
->LookupList
, GPOS
);
97 Free_FeatureList( &gpos
->FeatureList
);
98 Free_ScriptList( &gpos
->ScriptList
);
106 TT_Error
TT_Init_GPOS_Extension( TT_Engine engine
)
108 PEngine_Instance _engine
= HANDLE_Engine( engine
);
112 return TT_Err_Invalid_Engine
;
114 return TT_Register_Extension( _engine
,
116 sizeof ( TTO_GPOSHeader
),
123 TT_Error
TT_Load_GPOS_Table( TT_Face face
,
124 TTO_GPOSHeader
* retptr
,
125 TTO_GDEFHeader
* gdef
)
127 ULong cur_offset
, new_offset
, base_offset
;
129 TT_UShort i
, num_lookups
;
132 TTO_GPOSHeader
* gpos
;
135 PFace faze
= HANDLE_Face( face
);
139 return TT_Err_Invalid_Argument
;
142 return TT_Err_Invalid_Face_Handle
;
144 error
= TT_Extension_Get( faze
, GPOS_ID
, (void**)&gpos
);
148 if ( gpos
->offset
== 0 )
149 return TT_Err_Table_Missing
; /* no GPOS table; nothing to do */
151 /* now access stream */
153 if ( USE_Stream( faze
->stream
, stream
) )
156 base_offset
= gpos
->offset
;
160 if ( FILE_Seek( base_offset
+ 4L ) ||
164 new_offset
= GET_UShort() + base_offset
;
168 cur_offset
= FILE_Pos();
169 if ( FILE_Seek( new_offset
) ||
170 ( error
= Load_ScriptList( &gpos
->ScriptList
,
171 faze
) ) != TT_Err_Ok
)
173 (void)FILE_Seek( cur_offset
);
175 if ( ACCESS_Frame( 2L ) )
178 new_offset
= GET_UShort() + base_offset
;
182 cur_offset
= FILE_Pos();
183 if ( FILE_Seek( new_offset
) ||
184 ( error
= Load_FeatureList( &gpos
->FeatureList
,
185 faze
) ) != TT_Err_Ok
)
187 (void)FILE_Seek( cur_offset
);
189 if ( ACCESS_Frame( 2L ) )
192 new_offset
= GET_UShort() + base_offset
;
196 cur_offset
= FILE_Pos();
197 if ( FILE_Seek( new_offset
) ||
198 ( error
= Load_LookupList( &gpos
->LookupList
,
199 faze
, GPOS
) ) != TT_Err_Ok
)
202 gpos
->gdef
= gdef
; /* can be NULL */
204 /* We now check the LookupFlags for values larger than 0xFF to find
205 out whether we need to load the `MarkAttachClassDef' field of the
206 GDEF table -- this hack is necessary for OpenType 1.2 tables since
207 the version field of the GDEF table hasn't been incremented.
209 For constructed GDEF tables, we only load it if
210 `MarkAttachClassDef_offset' is not zero (nevertheless, a build of
211 a constructed mark attach table is not supported currently). */
214 gdef
->MarkAttachClassDef_offset
&& !gdef
->MarkAttachClassDef
.loaded
)
216 lo
= gpos
->LookupList
.Lookup
;
217 num_lookups
= gpos
->LookupList
.LookupCount
;
219 for ( i
= 0; i
< num_lookups
; i
++ )
221 if ( lo
[i
].LookupFlag
& IGNORE_SPECIAL_MARKS
)
223 if ( FILE_Seek( gdef
->MarkAttachClassDef_offset
) ||
227 new_offset
= GET_UShort();
232 return TTO_Err_Invalid_GDEF_SubTable
;
234 new_offset
+= base_offset
;
236 if ( FILE_Seek( new_offset
) ||
237 ( error
= Load_ClassDefinition( &gdef
->MarkAttachClassDef
,
238 256, faze
) ) != TT_Err_Ok
)
248 DONE_Stream( stream
);
253 Free_LookupList( &gpos
->LookupList
, GPOS
);
256 Free_FeatureList( &gpos
->FeatureList
);
259 Free_ScriptList( &gpos
->ScriptList
);
263 DONE_Stream( stream
);
270 /*****************************
271 * SubTable related functions
272 *****************************/
278 static TT_Error
Load_ValueRecord( TTO_ValueRecord
* vr
,
282 DEFINE_LOAD_LOCALS( input
->stream
);
284 ULong cur_offset
, new_offset
, base_offset
;
287 base_offset
= FILE_Pos();
289 if ( format
& HAVE_X_PLACEMENT
)
291 if ( ACCESS_Frame( 2L ) )
294 vr
->XPlacement
= GET_Short();
301 if ( format
& HAVE_Y_PLACEMENT
)
303 if ( ACCESS_Frame( 2L ) )
306 vr
->YPlacement
= GET_Short();
313 if ( format
& HAVE_X_ADVANCE
)
315 if ( ACCESS_Frame( 2L ) )
318 vr
->XAdvance
= GET_Short();
325 if ( format
& HAVE_Y_ADVANCE
)
327 if ( ACCESS_Frame( 2L ) )
330 vr
->YAdvance
= GET_Short();
337 if ( format
& HAVE_X_PLACEMENT_DEVICE
)
339 if ( ACCESS_Frame( 2L ) )
342 new_offset
= GET_UShort() + base_offset
;
346 cur_offset
= FILE_Pos();
347 if ( FILE_Seek( new_offset
) ||
348 ( error
= Load_Device( &vr
->XPlacementDevice
,
349 input
) ) != TT_Err_Ok
)
351 (void)FILE_Seek( cur_offset
);
355 vr
->XPlacementDevice
.StartSize
= 0;
356 vr
->XPlacementDevice
.EndSize
= 0;
357 vr
->XPlacementDevice
.DeltaValue
= NULL
;
360 if ( format
& HAVE_Y_PLACEMENT_DEVICE
)
362 if ( ACCESS_Frame( 2L ) )
365 new_offset
= GET_UShort() + base_offset
;
369 cur_offset
= FILE_Pos();
370 if ( FILE_Seek( new_offset
) ||
371 ( error
= Load_Device( &vr
->YPlacementDevice
,
372 input
) ) != TT_Err_Ok
)
374 (void)FILE_Seek( cur_offset
);
378 vr
->YPlacementDevice
.StartSize
= 0;
379 vr
->YPlacementDevice
.EndSize
= 0;
380 vr
->YPlacementDevice
.DeltaValue
= NULL
;
383 if ( format
& HAVE_X_ADVANCE_DEVICE
)
385 if ( ACCESS_Frame( 2L ) )
388 new_offset
= GET_UShort() + base_offset
;
392 cur_offset
= FILE_Pos();
393 if ( FILE_Seek( new_offset
) ||
394 ( error
= Load_Device( &vr
->XAdvanceDevice
,
395 input
) ) != TT_Err_Ok
)
397 (void)FILE_Seek( cur_offset
);
401 vr
->XAdvanceDevice
.StartSize
= 0;
402 vr
->XAdvanceDevice
.EndSize
= 0;
403 vr
->XAdvanceDevice
.DeltaValue
= NULL
;
406 if ( format
& HAVE_Y_ADVANCE_DEVICE
)
408 if ( ACCESS_Frame( 2L ) )
411 new_offset
= GET_UShort() + base_offset
;
415 cur_offset
= FILE_Pos();
416 if ( FILE_Seek( new_offset
) ||
417 ( error
= Load_Device( &vr
->YAdvanceDevice
,
418 input
) ) != TT_Err_Ok
)
420 (void)FILE_Seek( cur_offset
);
424 vr
->YAdvanceDevice
.StartSize
= 0;
425 vr
->YAdvanceDevice
.EndSize
= 0;
426 vr
->YAdvanceDevice
.DeltaValue
= NULL
;
429 if ( format
& HAVE_X_ID_PLACEMENT
)
431 if ( ACCESS_Frame( 2L ) )
434 vr
->XIdPlacement
= GET_UShort();
439 vr
->XIdPlacement
= 0;
441 if ( format
& HAVE_Y_ID_PLACEMENT
)
443 if ( ACCESS_Frame( 2L ) )
446 vr
->YIdPlacement
= GET_UShort();
451 vr
->YIdPlacement
= 0;
453 if ( format
& HAVE_X_ID_ADVANCE
)
455 if ( ACCESS_Frame( 2L ) )
458 vr
->XIdAdvance
= GET_UShort();
465 if ( format
& HAVE_Y_ID_ADVANCE
)
467 if ( ACCESS_Frame( 2L ) )
470 vr
->YIdAdvance
= GET_UShort();
480 Free_Device( &vr
->YAdvanceDevice
);
483 Free_Device( &vr
->XAdvanceDevice
);
486 Free_Device( &vr
->YPlacementDevice
);
491 static void Free_ValueRecord( TTO_ValueRecord
* vr
,
494 if ( format
& HAVE_Y_ADVANCE_DEVICE
)
495 Free_Device( &vr
->YAdvanceDevice
);
496 if ( format
& HAVE_X_ADVANCE_DEVICE
)
497 Free_Device( &vr
->XAdvanceDevice
);
498 if ( format
& HAVE_Y_PLACEMENT_DEVICE
)
499 Free_Device( &vr
->YPlacementDevice
);
500 if ( format
& HAVE_X_PLACEMENT_DEVICE
)
501 Free_Device( &vr
->XPlacementDevice
);
510 static TT_Error
Load_Anchor( TTO_Anchor
* an
,
513 DEFINE_LOAD_LOCALS( input
->stream
);
515 ULong cur_offset
, new_offset
, base_offset
;
518 base_offset
= FILE_Pos();
520 if ( ACCESS_Frame( 2L ) )
523 an
->PosFormat
= GET_UShort();
527 switch ( an
->PosFormat
)
530 if ( ACCESS_Frame( 4L ) )
533 an
->af
.af1
.XCoordinate
= GET_Short();
534 an
->af
.af1
.YCoordinate
= GET_Short();
540 if ( ACCESS_Frame( 6L ) )
543 an
->af
.af2
.XCoordinate
= GET_Short();
544 an
->af
.af2
.YCoordinate
= GET_Short();
545 an
->af
.af2
.AnchorPoint
= GET_UShort();
551 if ( ACCESS_Frame( 6L ) )
554 an
->af
.af3
.XCoordinate
= GET_Short();
555 an
->af
.af3
.YCoordinate
= GET_Short();
557 new_offset
= GET_UShort();
563 new_offset
+= base_offset
;
565 cur_offset
= FILE_Pos();
566 if ( FILE_Seek( new_offset
) ||
567 ( error
= Load_Device( &an
->af
.af3
.XDeviceTable
,
568 input
) ) != TT_Err_Ok
)
570 (void)FILE_Seek( cur_offset
);
574 an
->af
.af3
.XDeviceTable
.StartSize
= 0;
575 an
->af
.af3
.XDeviceTable
.EndSize
= 0;
576 an
->af
.af3
.XDeviceTable
.DeltaValue
= 0;
579 if ( ACCESS_Frame( 2L ) )
582 new_offset
= GET_UShort();
588 new_offset
+= base_offset
;
590 cur_offset
= FILE_Pos();
591 if ( FILE_Seek( new_offset
) ||
592 ( error
= Load_Device( &an
->af
.af3
.YDeviceTable
,
593 input
) ) != TT_Err_Ok
)
595 (void)FILE_Seek( cur_offset
);
599 an
->af
.af3
.YDeviceTable
.StartSize
= 0;
600 an
->af
.af3
.YDeviceTable
.EndSize
= 0;
601 an
->af
.af3
.YDeviceTable
.DeltaValue
= 0;
606 if ( ACCESS_Frame( 4L ) )
609 an
->af
.af4
.XIdAnchor
= GET_UShort();
610 an
->af
.af4
.YIdAnchor
= GET_UShort();
616 return TTO_Err_Invalid_GPOS_SubTable_Format
;
622 Free_Device( &an
->af
.af3
.XDeviceTable
);
627 static void Free_Anchor( TTO_Anchor
* an
)
629 if ( an
->PosFormat
== 3 )
631 Free_Device( &an
->af
.af3
.YDeviceTable
);
632 Free_Device( &an
->af
.af3
.XDeviceTable
);
639 static TT_Error
Load_MarkArray ( TTO_MarkArray
* ma
,
642 DEFINE_LOAD_LOCALS( input
->stream
);
645 ULong cur_offset
, new_offset
, base_offset
;
650 base_offset
= FILE_Pos();
652 if ( ACCESS_Frame( 2L ) )
655 count
= ma
->MarkCount
= GET_UShort();
659 ma
->MarkRecord
= NULL
;
661 if ( ALLOC_ARRAY( ma
->MarkRecord
, count
, TTO_MarkRecord
) )
666 for ( n
= 0; n
< count
; n
++ )
668 if ( ACCESS_Frame( 4L ) )
671 mr
[n
].Class
= GET_UShort();
672 new_offset
= GET_UShort() + base_offset
;
676 cur_offset
= FILE_Pos();
677 if ( FILE_Seek( new_offset
) ||
678 ( error
= Load_Anchor( &mr
[n
].MarkAnchor
, input
) ) != TT_Err_Ok
)
680 (void)FILE_Seek( cur_offset
);
686 for ( n
= 0; n
< count
; n
++ )
687 Free_Anchor( &mr
[n
].MarkAnchor
);
694 static void Free_MarkArray( TTO_MarkArray
* ma
)
701 if ( ma
->MarkRecord
)
703 count
= ma
->MarkCount
;
706 for ( n
= 0; n
< count
; n
++ )
707 Free_Anchor( &mr
[n
].MarkAnchor
);
716 /* SinglePosFormat1 */
717 /* SinglePosFormat2 */
719 TT_Error
Load_SinglePos( TTO_SinglePos
* sp
,
722 DEFINE_LOAD_LOCALS( input
->stream
);
724 UShort n
, count
, format
;
725 ULong cur_offset
, new_offset
, base_offset
;
730 base_offset
= FILE_Pos();
732 if ( ACCESS_Frame( 6L ) )
735 sp
->PosFormat
= GET_UShort();
736 new_offset
= GET_UShort() + base_offset
;
738 format
= sp
->ValueFormat
= GET_UShort();
743 return TTO_Err_Invalid_GPOS_SubTable
;
745 cur_offset
= FILE_Pos();
746 if ( FILE_Seek( new_offset
) ||
747 ( error
= Load_Coverage( &sp
->Coverage
, input
) ) != TT_Err_Ok
)
749 (void)FILE_Seek( cur_offset
);
751 switch ( sp
->PosFormat
)
754 error
= Load_ValueRecord( &sp
->spf
.spf1
.Value
, format
, input
);
760 if ( ACCESS_Frame( 2L ) )
763 count
= sp
->spf
.spf2
.ValueCount
= GET_UShort();
767 sp
->spf
.spf2
.Value
= NULL
;
769 if ( ALLOC_ARRAY( sp
->spf
.spf2
.Value
, count
, TTO_ValueRecord
) )
772 v
= sp
->spf
.spf2
.Value
;
774 for ( n
= 0; n
< count
; n
++ )
776 error
= Load_ValueRecord( &v
[n
], format
, input
);
783 return TTO_Err_Invalid_GPOS_SubTable_Format
;
789 for ( n
= 0; n
< count
; n
++ )
790 Free_ValueRecord( &v
[n
], format
);
795 Free_Coverage( &sp
->Coverage
);
800 void Free_SinglePos( TTO_SinglePos
* sp
)
802 UShort n
, count
, format
;
807 format
= sp
->ValueFormat
;
809 switch ( sp
->PosFormat
)
812 Free_ValueRecord( &sp
->spf
.spf1
.Value
, format
);
816 if ( sp
->spf
.spf2
.Value
)
818 count
= sp
->spf
.spf2
.ValueCount
;
819 v
= sp
->spf
.spf2
.Value
;
821 for ( n
= 0; n
< count
; n
++ )
822 Free_ValueRecord( &v
[n
], format
);
829 Free_Coverage( &sp
->Coverage
);
837 static TT_Error
Load_PairSet ( TTO_PairSet
* ps
,
842 DEFINE_LOAD_LOCALS( input
->stream
);
846 TTO_PairValueRecord
* pvr
;
849 if ( ACCESS_Frame( 2L ) )
852 count
= ps
->PairValueCount
= GET_UShort();
856 ps
->PairValueRecord
= NULL
;
858 if ( ALLOC_ARRAY( ps
->PairValueRecord
, count
, TTO_PairValueRecord
) )
861 pvr
= ps
->PairValueRecord
;
863 for ( n
= 0; n
< count
; n
++ )
865 if ( ACCESS_Frame( 2L ) )
868 pvr
[n
].SecondGlyph
= GET_UShort();
874 error
= Load_ValueRecord( &pvr
[n
].Value1
, format1
, input
);
880 error
= Load_ValueRecord( &pvr
[n
].Value2
, format2
, input
);
889 for ( n
= 0; n
< count
; n
++ )
892 Free_ValueRecord( &pvr
[n
].Value1
, format1
);
894 Free_ValueRecord( &pvr
[n
].Value2
, format2
);
902 static void Free_PairSet( TTO_PairSet
* ps
,
908 TTO_PairValueRecord
* pvr
;
911 if ( ps
->PairValueRecord
)
913 count
= ps
->PairValueCount
;
914 pvr
= ps
->PairValueRecord
;
916 for ( n
= 0; n
< count
; n
++ )
919 Free_ValueRecord( &pvr
[n
].Value1
, format1
);
921 Free_ValueRecord( &pvr
[n
].Value2
, format2
);
931 static TT_Error
Load_PairPosFormat1( TTO_PairPosFormat1
* ppf1
,
936 DEFINE_LOAD_LOCALS( input
->stream
);
939 ULong cur_offset
, new_offset
, base_offset
;
944 base_offset
= FILE_Pos() - 8L;
946 if ( ACCESS_Frame( 2L ) )
949 count
= ppf1
->PairSetCount
= GET_UShort();
953 ppf1
->PairSet
= NULL
;
955 if ( ALLOC_ARRAY( ppf1
->PairSet
, count
, TTO_PairSet
) )
960 for ( n
= 0; n
< count
; n
++ )
962 if ( ACCESS_Frame( 2L ) )
965 new_offset
= GET_UShort() + base_offset
;
969 cur_offset
= FILE_Pos();
970 if ( FILE_Seek( new_offset
) ||
971 ( error
= Load_PairSet( &ps
[n
], format1
,
972 format2
, input
) ) != TT_Err_Ok
)
974 (void)FILE_Seek( cur_offset
);
980 for ( n
= 0; n
< count
; n
++ )
981 Free_PairSet( &ps
[n
], format1
, format2
);
988 static void Free_PairPosFormat1( TTO_PairPosFormat1
* ppf1
,
999 count
= ppf1
->PairSetCount
;
1002 for ( n
= 0; n
< count
; n
++ )
1003 Free_PairSet( &ps
[n
], format1
, format2
);
1010 /* PairPosFormat2 */
1012 static TT_Error
Load_PairPosFormat2( TTO_PairPosFormat2
* ppf2
,
1017 DEFINE_LOAD_LOCALS( input
->stream
);
1019 UShort m
, n
, count1
, count2
;
1020 ULong cur_offset
, new_offset1
, new_offset2
, base_offset
;
1022 TTO_Class1Record
* c1r
;
1023 TTO_Class2Record
* c2r
;
1026 base_offset
= FILE_Pos() - 8L;
1028 if ( ACCESS_Frame( 8L ) )
1031 new_offset1
= GET_UShort() + base_offset
;
1032 new_offset2
= GET_UShort() + base_offset
;
1034 /* `Class1Count' and `Class2Count' are the upper limits for class
1035 values, thus we read it now to make additional safety checks. */
1037 count1
= ppf2
->Class1Count
= GET_UShort();
1038 count2
= ppf2
->Class2Count
= GET_UShort();
1042 cur_offset
= FILE_Pos();
1043 if ( FILE_Seek( new_offset1
) ||
1044 ( error
= Load_ClassDefinition( &ppf2
->ClassDef1
, count1
,
1045 input
) ) != TT_Err_Ok
)
1047 (void)FILE_Seek( cur_offset
);
1049 cur_offset
= FILE_Pos();
1050 if ( FILE_Seek( new_offset2
) ||
1051 ( error
= Load_ClassDefinition( &ppf2
->ClassDef2
, count2
,
1052 input
) ) != TT_Err_Ok
)
1054 (void)FILE_Seek( cur_offset
);
1056 ppf2
->Class1Record
= NULL
;
1058 if ( ALLOC_ARRAY( ppf2
->Class1Record
, count1
, TTO_Class1Record
) )
1061 c1r
= ppf2
->Class1Record
;
1063 for ( m
= 0; m
< count1
; m
++ )
1065 c1r
[m
].Class2Record
= NULL
;
1067 if ( ALLOC_ARRAY( c1r
[m
].Class2Record
, count2
, TTO_Class2Record
) )
1070 c2r
= c1r
[m
].Class2Record
;
1072 for ( n
= 0; n
< count2
; n
++ )
1076 Load_ValueRecord( &c2r
[n
].Value1
, format1
, input
);
1082 Load_ValueRecord( &c2r
[n
].Value2
, format2
, input
);
1092 for ( m
= 0; m
< count1
; m
++ )
1094 c2r
= c1r
[m
].Class2Record
;
1096 for ( n
= 0; n
< count2
; n
++ )
1099 Free_ValueRecord( &c2r
[n
].Value1
, format1
);
1101 Free_ValueRecord( &c2r
[n
].Value2
, format2
);
1109 Free_ClassDefinition( &ppf2
->ClassDef2
);
1112 Free_ClassDefinition( &ppf2
->ClassDef1
);
1117 static void Free_PairPosFormat2( TTO_PairPosFormat2
* ppf2
,
1121 UShort m
, n
, count1
, count2
;
1123 TTO_Class1Record
* c1r
;
1124 TTO_Class2Record
* c2r
;
1127 if ( ppf2
->Class1Record
)
1129 c1r
= ppf2
->Class1Record
;
1130 count1
= ppf2
->Class1Count
;
1131 count2
= ppf2
->Class2Count
;
1133 for ( m
= 0; m
< count1
; m
++ )
1135 c2r
= c1r
[m
].Class2Record
;
1137 for ( n
= 0; n
< count2
; n
++ )
1140 Free_ValueRecord( &c2r
[n
].Value1
, format1
);
1142 Free_ValueRecord( &c2r
[n
].Value2
, format2
);
1150 Free_ClassDefinition( &ppf2
->ClassDef2
);
1151 Free_ClassDefinition( &ppf2
->ClassDef1
);
1156 TT_Error
Load_PairPos( TTO_PairPos
* pp
,
1159 DEFINE_LOAD_LOCALS( input
->stream
);
1161 UShort format1
, format2
;
1162 ULong cur_offset
, new_offset
, base_offset
;
1165 base_offset
= FILE_Pos();
1167 if ( ACCESS_Frame( 8L ) )
1170 pp
->PosFormat
= GET_UShort();
1171 new_offset
= GET_UShort() + base_offset
;
1173 format1
= pp
->ValueFormat1
= GET_UShort();
1174 format2
= pp
->ValueFormat2
= GET_UShort();
1178 cur_offset
= FILE_Pos();
1179 if ( FILE_Seek( new_offset
) ||
1180 ( error
= Load_Coverage( &pp
->Coverage
, input
) ) != TT_Err_Ok
)
1182 (void)FILE_Seek( cur_offset
);
1184 switch ( pp
->PosFormat
)
1187 error
= Load_PairPosFormat1( &pp
->ppf
.ppf1
, format1
, format2
, input
);
1193 error
= Load_PairPosFormat2( &pp
->ppf
.ppf2
, format1
, format2
, input
);
1199 return TTO_Err_Invalid_GPOS_SubTable_Format
;
1205 Free_Coverage( &pp
->Coverage
);
1210 void Free_PairPos( TTO_PairPos
* pp
)
1212 UShort format1
, format2
;
1215 format1
= pp
->ValueFormat1
;
1216 format2
= pp
->ValueFormat2
;
1218 switch ( pp
->PosFormat
)
1221 Free_PairPosFormat1( &pp
->ppf
.ppf1
, format1
, format2
);
1225 Free_PairPosFormat2( &pp
->ppf
.ppf2
, format1
, format2
);
1229 Free_Coverage( &pp
->Coverage
);
1235 /* CursivePosFormat1 */
1237 TT_Error
Load_CursivePos( TTO_CursivePos
* cp
,
1240 DEFINE_LOAD_LOCALS( input
->stream
);
1243 ULong cur_offset
, new_offset
, base_offset
;
1245 TTO_EntryExitRecord
* eer
;
1248 base_offset
= FILE_Pos();
1250 if ( ACCESS_Frame( 4L ) )
1253 cp
->PosFormat
= GET_UShort();
1254 new_offset
= GET_UShort() + base_offset
;
1258 cur_offset
= FILE_Pos();
1259 if ( FILE_Seek( new_offset
) ||
1260 ( error
= Load_Coverage( &cp
->Coverage
, input
) ) != TT_Err_Ok
)
1262 (void)FILE_Seek( cur_offset
);
1264 if ( ACCESS_Frame( 2L ) )
1267 count
= cp
->EntryExitCount
= GET_UShort();
1271 cp
->EntryExitRecord
= NULL
;
1273 if ( ALLOC_ARRAY( cp
->EntryExitRecord
, count
, TTO_EntryExitRecord
) )
1276 eer
= cp
->EntryExitRecord
;
1278 for ( n
= 0; n
< count
; n
++ )
1280 if ( ACCESS_Frame( 2L ) )
1283 new_offset
= GET_UShort();
1289 new_offset
+= base_offset
;
1291 cur_offset
= FILE_Pos();
1292 if ( FILE_Seek( new_offset
) ||
1293 ( error
= Load_Anchor( &eer
[n
].EntryAnchor
,
1294 input
) ) != TT_Err_Ok
)
1296 (void)FILE_Seek( cur_offset
);
1299 eer
[n
].EntryAnchor
.PosFormat
= 0;
1301 if ( ACCESS_Frame( 2L ) )
1304 new_offset
= GET_UShort();
1310 new_offset
+= base_offset
;
1312 cur_offset
= FILE_Pos();
1313 if ( FILE_Seek( new_offset
) ||
1314 ( error
= Load_Anchor( &eer
[n
].ExitAnchor
,
1315 input
) ) != TT_Err_Ok
)
1317 (void)FILE_Seek( cur_offset
);
1320 eer
[n
].ExitAnchor
.PosFormat
= 0;
1326 for ( n
= 0; n
< count
; n
++ )
1328 Free_Anchor( &eer
[n
].EntryAnchor
);
1329 Free_Anchor( &eer
[n
].ExitAnchor
);
1335 Free_Coverage( &cp
->Coverage
);
1340 void Free_CursivePos( TTO_CursivePos
* cp
)
1344 TTO_EntryExitRecord
* eer
;
1347 if ( cp
->EntryExitRecord
)
1349 count
= cp
->EntryExitCount
;
1350 eer
= cp
->EntryExitRecord
;
1352 for ( n
= 0; n
< count
; n
++ )
1354 Free_Anchor( &eer
[n
].EntryAnchor
);
1355 Free_Anchor( &eer
[n
].ExitAnchor
);
1361 Free_Coverage( &cp
->Coverage
);
1369 static TT_Error
Load_BaseArray( TTO_BaseArray
* ba
,
1373 DEFINE_LOAD_LOCALS( input
->stream
);
1376 ULong cur_offset
, new_offset
, base_offset
;
1382 base_offset
= FILE_Pos();
1384 if ( ACCESS_Frame( 2L ) )
1387 count
= ba
->BaseCount
= GET_UShort();
1391 ba
->BaseRecord
= NULL
;
1393 if ( ALLOC_ARRAY( ba
->BaseRecord
, count
, TTO_BaseRecord
) )
1396 br
= ba
->BaseRecord
;
1398 for ( m
= 0; m
< count
; m
++ )
1400 br
[m
].BaseAnchor
= NULL
;
1402 if ( ALLOC_ARRAY( br
[m
].BaseAnchor
, num_classes
, TTO_Anchor
) )
1405 ban
= br
[m
].BaseAnchor
;
1407 for ( n
= 0; n
< num_classes
; n
++ )
1409 if ( ACCESS_Frame( 2L ) )
1412 new_offset
= GET_UShort() + base_offset
;
1416 cur_offset
= FILE_Pos();
1417 if ( FILE_Seek( new_offset
) ||
1418 ( error
= Load_Anchor( &ban
[n
], input
) ) != TT_Err_Ok
)
1420 (void)FILE_Seek( cur_offset
);
1427 for ( m
= 0; m
< count
; m
++ )
1429 ban
= br
[m
].BaseAnchor
;
1431 for ( n
= 0; n
< num_classes
; n
++ )
1432 Free_Anchor( &ban
[n
] );
1442 static void Free_BaseArray( TTO_BaseArray
* ba
,
1443 UShort num_classes
)
1451 if ( ba
->BaseRecord
)
1453 count
= ba
->BaseCount
;
1454 br
= ba
->BaseRecord
;
1456 for ( m
= 0; m
< count
; m
++ )
1458 ban
= br
[m
].BaseAnchor
;
1460 for ( n
= 0; n
< num_classes
; n
++ )
1461 Free_Anchor( &ban
[n
] );
1471 /* MarkBasePosFormat1 */
1473 TT_Error
Load_MarkBasePos( TTO_MarkBasePos
* mbp
,
1476 DEFINE_LOAD_LOCALS( input
->stream
);
1478 ULong cur_offset
, new_offset
, base_offset
;
1481 base_offset
= FILE_Pos();
1483 if ( ACCESS_Frame( 4L ) )
1486 mbp
->PosFormat
= GET_UShort();
1487 new_offset
= GET_UShort() + base_offset
;
1491 cur_offset
= FILE_Pos();
1492 if ( FILE_Seek( new_offset
) ||
1493 ( error
= Load_Coverage( &mbp
->MarkCoverage
, input
) ) != TT_Err_Ok
)
1495 (void)FILE_Seek( cur_offset
);
1497 if ( ACCESS_Frame( 2L ) )
1500 new_offset
= GET_UShort() + base_offset
;
1504 cur_offset
= FILE_Pos();
1505 if ( FILE_Seek( new_offset
) ||
1506 ( error
= Load_Coverage( &mbp
->BaseCoverage
, input
) ) != TT_Err_Ok
)
1508 (void)FILE_Seek( cur_offset
);
1510 if ( ACCESS_Frame( 4L ) )
1513 mbp
->ClassCount
= GET_UShort();
1514 new_offset
= GET_UShort() + base_offset
;
1518 cur_offset
= FILE_Pos();
1519 if ( FILE_Seek( new_offset
) ||
1520 ( error
= Load_MarkArray( &mbp
->MarkArray
, input
) ) != TT_Err_Ok
)
1522 (void)FILE_Seek( cur_offset
);
1524 if ( ACCESS_Frame( 2L ) )
1527 new_offset
= GET_UShort() + base_offset
;
1531 cur_offset
= FILE_Pos();
1532 if ( FILE_Seek( new_offset
) ||
1533 ( error
= Load_BaseArray( &mbp
->BaseArray
, mbp
->ClassCount
,
1534 input
) ) != TT_Err_Ok
)
1540 Free_MarkArray( &mbp
->MarkArray
);
1543 Free_Coverage( &mbp
->BaseCoverage
);
1546 Free_Coverage( &mbp
->MarkCoverage
);
1551 void Free_MarkBasePos( TTO_MarkBasePos
* mbp
)
1553 Free_BaseArray( &mbp
->BaseArray
, mbp
->ClassCount
);
1554 Free_MarkArray( &mbp
->MarkArray
);
1555 Free_Coverage( &mbp
->BaseCoverage
);
1556 Free_Coverage( &mbp
->MarkCoverage
);
1562 /* LigatureAttach */
1564 static TT_Error
Load_LigatureAttach( TTO_LigatureAttach
* lat
,
1568 DEFINE_LOAD_LOCALS( input
->stream
);
1571 ULong cur_offset
, new_offset
, base_offset
;
1573 TTO_ComponentRecord
* cr
;
1577 base_offset
= FILE_Pos();
1579 if ( ACCESS_Frame( 2L ) )
1582 count
= lat
->ComponentCount
= GET_UShort();
1586 lat
->ComponentRecord
= NULL
;
1588 if ( ALLOC_ARRAY( lat
->ComponentRecord
, count
, TTO_ComponentRecord
) )
1591 cr
= lat
->ComponentRecord
;
1593 for ( m
= 0; m
< count
; m
++ )
1595 cr
[m
].LigatureAnchor
= NULL
;
1597 if ( ALLOC_ARRAY( cr
[m
].LigatureAnchor
, num_classes
, TTO_Anchor
) )
1600 lan
= cr
[m
].LigatureAnchor
;
1602 for ( n
= 0; n
< num_classes
; n
++ )
1604 if ( ACCESS_Frame( 2L ) )
1607 new_offset
= GET_UShort();
1613 new_offset
+= base_offset
;
1615 cur_offset
= FILE_Pos();
1616 if ( FILE_Seek( new_offset
) ||
1617 ( error
= Load_Anchor( &lan
[n
], input
) ) != TT_Err_Ok
)
1619 (void)FILE_Seek( cur_offset
);
1622 lan
[n
].PosFormat
= 0;
1629 for ( m
= 0; m
< count
; m
++ )
1631 lan
= cr
[m
].LigatureAnchor
;
1633 for ( n
= 0; n
< num_classes
; n
++ )
1634 Free_Anchor( &lan
[n
] );
1644 static void Free_LigatureAttach( TTO_LigatureAttach
* lat
,
1645 UShort num_classes
)
1649 TTO_ComponentRecord
* cr
;
1653 if ( lat
->ComponentRecord
)
1655 count
= lat
->ComponentCount
;
1656 cr
= lat
->ComponentRecord
;
1658 for ( m
= 0; m
< count
; m
++ )
1660 lan
= cr
[m
].LigatureAnchor
;
1662 for ( n
= 0; n
< num_classes
; n
++ )
1663 Free_Anchor( &lan
[n
] );
1675 static TT_Error
Load_LigatureArray( TTO_LigatureArray
* la
,
1679 DEFINE_LOAD_LOCALS( input
->stream
);
1682 ULong cur_offset
, new_offset
, base_offset
;
1684 TTO_LigatureAttach
* lat
;
1687 base_offset
= FILE_Pos();
1689 if ( ACCESS_Frame( 2L ) )
1692 count
= la
->LigatureCount
= GET_UShort();
1696 la
->LigatureAttach
= NULL
;
1698 if ( ALLOC_ARRAY( la
->LigatureAttach
, count
, TTO_LigatureAttach
) )
1701 lat
= la
->LigatureAttach
;
1703 for ( n
= 0; n
< count
; n
++ )
1705 if ( ACCESS_Frame( 2L ) )
1708 new_offset
= GET_UShort() + base_offset
;
1712 cur_offset
= FILE_Pos();
1713 if ( FILE_Seek( new_offset
) ||
1714 ( error
= Load_LigatureAttach( &lat
[n
], num_classes
,
1715 input
) ) != TT_Err_Ok
)
1717 (void)FILE_Seek( cur_offset
);
1723 for ( n
= 0; n
< count
; n
++ )
1724 Free_LigatureAttach( &lat
[n
], num_classes
);
1731 static void Free_LigatureArray( TTO_LigatureArray
* la
,
1732 UShort num_classes
)
1736 TTO_LigatureAttach
* lat
;
1739 if ( la
->LigatureAttach
)
1741 count
= la
->LigatureCount
;
1742 lat
= la
->LigatureAttach
;
1744 for ( n
= 0; n
< count
; n
++ )
1745 Free_LigatureAttach( &lat
[n
], num_classes
);
1752 /* MarkLigPosFormat1 */
1754 TT_Error
Load_MarkLigPos( TTO_MarkLigPos
* mlp
,
1757 DEFINE_LOAD_LOCALS( input
->stream
);
1759 ULong cur_offset
, new_offset
, base_offset
;
1762 base_offset
= FILE_Pos();
1764 if ( ACCESS_Frame( 4L ) )
1767 mlp
->PosFormat
= GET_UShort();
1768 new_offset
= GET_UShort() + base_offset
;
1772 cur_offset
= FILE_Pos();
1773 if ( FILE_Seek( new_offset
) ||
1774 ( error
= Load_Coverage( &mlp
->MarkCoverage
, input
) ) != TT_Err_Ok
)
1776 (void)FILE_Seek( cur_offset
);
1778 if ( ACCESS_Frame( 2L ) )
1781 new_offset
= GET_UShort() + base_offset
;
1785 cur_offset
= FILE_Pos();
1786 if ( FILE_Seek( new_offset
) ||
1787 ( error
= Load_Coverage( &mlp
->LigatureCoverage
,
1788 input
) ) != TT_Err_Ok
)
1790 (void)FILE_Seek( cur_offset
);
1792 if ( ACCESS_Frame( 4L ) )
1795 mlp
->ClassCount
= GET_UShort();
1796 new_offset
= GET_UShort() + base_offset
;
1800 cur_offset
= FILE_Pos();
1801 if ( FILE_Seek( new_offset
) ||
1802 ( error
= Load_MarkArray( &mlp
->MarkArray
, input
) ) != TT_Err_Ok
)
1804 (void)FILE_Seek( cur_offset
);
1806 if ( ACCESS_Frame( 2L ) )
1809 new_offset
= GET_UShort() + base_offset
;
1813 cur_offset
= FILE_Pos();
1814 if ( FILE_Seek( new_offset
) ||
1815 ( error
= Load_LigatureArray( &mlp
->LigatureArray
, mlp
->ClassCount
,
1816 input
) ) != TT_Err_Ok
)
1822 Free_MarkArray( &mlp
->MarkArray
);
1825 Free_Coverage( &mlp
->LigatureCoverage
);
1828 Free_Coverage( &mlp
->MarkCoverage
);
1833 void Free_MarkLigPos( TTO_MarkLigPos
* mlp
)
1835 Free_LigatureArray( &mlp
->LigatureArray
, mlp
->ClassCount
);
1836 Free_MarkArray( &mlp
->MarkArray
);
1837 Free_Coverage( &mlp
->LigatureCoverage
);
1838 Free_Coverage( &mlp
->MarkCoverage
);
1846 static TT_Error
Load_Mark2Array( TTO_Mark2Array
* m2a
,
1850 DEFINE_LOAD_LOCALS( input
->stream
);
1853 ULong cur_offset
, new_offset
, base_offset
;
1855 TTO_Mark2Record
* m2r
;
1859 base_offset
= FILE_Pos();
1861 if ( ACCESS_Frame( 2L ) )
1864 count
= m2a
->Mark2Count
= GET_UShort();
1868 m2a
->Mark2Record
= NULL
;
1870 if ( ALLOC_ARRAY( m2a
->Mark2Record
, count
, TTO_Mark2Record
) )
1873 m2r
= m2a
->Mark2Record
;
1875 for ( m
= 0; m
< count
; m
++ )
1877 m2r
[m
].Mark2Anchor
= NULL
;
1879 if ( ALLOC_ARRAY( m2r
[m
].Mark2Anchor
, num_classes
, TTO_Anchor
) )
1882 m2an
= m2r
[m
].Mark2Anchor
;
1884 for ( n
= 0; n
< num_classes
; n
++ )
1886 if ( ACCESS_Frame( 2L ) )
1889 new_offset
= GET_UShort() + base_offset
;
1893 cur_offset
= FILE_Pos();
1894 if ( FILE_Seek( new_offset
) ||
1895 ( error
= Load_Anchor( &m2an
[n
], input
) ) != TT_Err_Ok
)
1897 (void)FILE_Seek( cur_offset
);
1904 for ( m
= 0; m
< count
; m
++ )
1906 m2an
= m2r
[m
].Mark2Anchor
;
1908 for ( n
= 0; n
< num_classes
; n
++ )
1909 Free_Anchor( &m2an
[n
] );
1919 static void Free_Mark2Array( TTO_Mark2Array
* m2a
,
1920 UShort num_classes
)
1924 TTO_Mark2Record
* m2r
;
1928 if ( m2a
->Mark2Record
)
1930 count
= m2a
->Mark2Count
;
1931 m2r
= m2a
->Mark2Record
;
1933 for ( m
= 0; m
< count
; m
++ )
1935 m2an
= m2r
[m
].Mark2Anchor
;
1937 for ( n
= 0; n
< num_classes
; n
++ )
1938 Free_Anchor( &m2an
[n
] );
1948 /* MarkMarkPosFormat1 */
1950 TT_Error
Load_MarkMarkPos( TTO_MarkMarkPos
* mmp
,
1953 DEFINE_LOAD_LOCALS( input
->stream
);
1955 ULong cur_offset
, new_offset
, base_offset
;
1958 base_offset
= FILE_Pos();
1960 if ( ACCESS_Frame( 4L ) )
1963 mmp
->PosFormat
= GET_UShort();
1964 new_offset
= GET_UShort() + base_offset
;
1968 cur_offset
= FILE_Pos();
1969 if ( FILE_Seek( new_offset
) ||
1970 ( error
= Load_Coverage( &mmp
->Mark1Coverage
,
1971 input
) ) != TT_Err_Ok
)
1973 (void)FILE_Seek( cur_offset
);
1975 if ( ACCESS_Frame( 2L ) )
1978 new_offset
= GET_UShort() + base_offset
;
1982 cur_offset
= FILE_Pos();
1983 if ( FILE_Seek( new_offset
) ||
1984 ( error
= Load_Coverage( &mmp
->Mark2Coverage
,
1985 input
) ) != TT_Err_Ok
)
1987 (void)FILE_Seek( cur_offset
);
1989 if ( ACCESS_Frame( 4L ) )
1992 mmp
->ClassCount
= GET_UShort();
1993 new_offset
= GET_UShort() + base_offset
;
1997 cur_offset
= FILE_Pos();
1998 if ( FILE_Seek( new_offset
) ||
1999 ( error
= Load_MarkArray( &mmp
->Mark1Array
, input
) ) != TT_Err_Ok
)
2001 (void)FILE_Seek( cur_offset
);
2003 if ( ACCESS_Frame( 2L ) )
2006 new_offset
= GET_UShort() + base_offset
;
2010 cur_offset
= FILE_Pos();
2011 if ( FILE_Seek( new_offset
) ||
2012 ( error
= Load_Mark2Array( &mmp
->Mark2Array
, mmp
->ClassCount
,
2013 input
) ) != TT_Err_Ok
)
2019 Free_MarkArray( &mmp
->Mark1Array
);
2022 Free_Coverage( &mmp
->Mark2Coverage
);
2025 Free_Coverage( &mmp
->Mark1Coverage
);
2030 void Free_MarkMarkPos( TTO_MarkMarkPos
* mmp
)
2032 Free_Mark2Array( &mmp
->Mark2Array
, mmp
->ClassCount
);
2033 Free_MarkArray( &mmp
->Mark1Array
);
2034 Free_Coverage( &mmp
->Mark2Coverage
);
2035 Free_Coverage( &mmp
->Mark1Coverage
);
2043 static TT_Error
Load_PosRule( TTO_PosRule
* pr
,
2046 DEFINE_LOAD_LOCALS( input
->stream
);
2051 TTO_PosLookupRecord
* plr
;
2054 if ( ACCESS_Frame( 4L ) )
2057 pr
->GlyphCount
= GET_UShort();
2058 pr
->PosCount
= GET_UShort();
2064 count
= pr
->GlyphCount
- 1; /* only GlyphCount - 1 elements */
2066 if ( ALLOC_ARRAY( pr
->Input
, count
, UShort
) )
2071 if ( ACCESS_Frame( count
* 2L ) )
2074 for ( n
= 0; n
< count
; n
++ )
2075 i
[n
] = GET_UShort();
2079 pr
->PosLookupRecord
= NULL
;
2081 count
= pr
->PosCount
;
2083 if ( ALLOC_ARRAY( pr
->PosLookupRecord
, count
, TTO_PosLookupRecord
) )
2086 plr
= pr
->PosLookupRecord
;
2088 if ( ACCESS_Frame( count
* 4L ) )
2091 for ( n
= 0; n
< count
; n
++ )
2093 plr
[n
].SequenceIndex
= GET_UShort();
2094 plr
[n
].LookupListIndex
= GET_UShort();
2110 static void Free_PosRule( TTO_PosRule
* pr
)
2112 FREE( pr
->PosLookupRecord
);
2119 static TT_Error
Load_PosRuleSet( TTO_PosRuleSet
* prs
,
2122 DEFINE_LOAD_LOCALS( input
->stream
);
2125 ULong cur_offset
, new_offset
, base_offset
;
2130 base_offset
= FILE_Pos();
2132 if ( ACCESS_Frame( 2L ) )
2135 count
= prs
->PosRuleCount
= GET_UShort();
2139 prs
->PosRule
= NULL
;
2141 if ( ALLOC_ARRAY( prs
->PosRule
, count
, TTO_PosRule
) )
2146 for ( n
= 0; n
< count
; n
++ )
2148 if ( ACCESS_Frame( 2L ) )
2151 new_offset
= GET_UShort() + base_offset
;
2155 cur_offset
= FILE_Pos();
2156 if ( FILE_Seek( new_offset
) ||
2157 ( error
= Load_PosRule( &pr
[n
], input
) ) != TT_Err_Ok
)
2159 (void)FILE_Seek( cur_offset
);
2165 for ( n
= 0; n
< count
; n
++ )
2166 Free_PosRule( &pr
[n
] );
2173 static void Free_PosRuleSet( TTO_PosRuleSet
* prs
)
2182 count
= prs
->PosRuleCount
;
2185 for ( n
= 0; n
< count
; n
++ )
2186 Free_PosRule( &pr
[n
] );
2193 /* ContextPosFormat1 */
2195 static TT_Error
Load_ContextPos1( TTO_ContextPosFormat1
* cpf1
,
2198 DEFINE_LOAD_LOCALS( input
->stream
);
2201 ULong cur_offset
, new_offset
, base_offset
;
2203 TTO_PosRuleSet
* prs
;
2206 base_offset
= FILE_Pos() - 2L;
2208 if ( ACCESS_Frame( 2L ) )
2211 new_offset
= GET_UShort() + base_offset
;
2215 cur_offset
= FILE_Pos();
2216 if ( FILE_Seek( new_offset
) ||
2217 ( error
= Load_Coverage( &cpf1
->Coverage
, input
) ) != TT_Err_Ok
)
2219 (void)FILE_Seek( cur_offset
);
2221 if ( ACCESS_Frame( 2L ) )
2224 count
= cpf1
->PosRuleSetCount
= GET_UShort();
2228 cpf1
->PosRuleSet
= NULL
;
2230 if ( ALLOC_ARRAY( cpf1
->PosRuleSet
, count
, TTO_PosRuleSet
) )
2233 prs
= cpf1
->PosRuleSet
;
2235 for ( n
= 0; n
< count
; n
++ )
2237 if ( ACCESS_Frame( 2L ) )
2240 new_offset
= GET_UShort() + base_offset
;
2244 cur_offset
= FILE_Pos();
2245 if ( FILE_Seek( new_offset
) ||
2246 ( error
= Load_PosRuleSet( &prs
[n
], input
) ) != TT_Err_Ok
)
2248 (void)FILE_Seek( cur_offset
);
2254 for ( n
= 0; n
< count
; n
++ )
2255 Free_PosRuleSet( &prs
[n
] );
2260 Free_Coverage( &cpf1
->Coverage
);
2265 static void Free_Context1( TTO_ContextPosFormat1
* cpf1
)
2269 TTO_PosRuleSet
* prs
;
2272 if ( cpf1
->PosRuleSet
)
2274 count
= cpf1
->PosRuleSetCount
;
2275 prs
= cpf1
->PosRuleSet
;
2277 for ( n
= 0; n
< count
; n
++ )
2278 Free_PosRuleSet( &prs
[n
] );
2283 Free_Coverage( &cpf1
->Coverage
);
2289 static TT_Error
Load_PosClassRule( TTO_ContextPosFormat2
* cpf2
,
2290 TTO_PosClassRule
* pcr
,
2293 DEFINE_LOAD_LOCALS( input
->stream
);
2298 TTO_PosLookupRecord
* plr
;
2302 if ( ACCESS_Frame( 4L ) )
2305 pcr
->GlyphCount
= GET_UShort();
2306 pcr
->PosCount
= GET_UShort();
2310 if ( pcr
->GlyphCount
> cpf2
->MaxContextLength
)
2311 cpf2
->MaxContextLength
= pcr
->GlyphCount
;
2315 count
= pcr
->GlyphCount
- 1; /* only GlyphCount - 1 elements */
2317 if ( ALLOC_ARRAY( pcr
->Class
, count
, UShort
) )
2321 d
= cpf2
->ClassDef
.Defined
;
2323 if ( ACCESS_Frame( count
* 2L ) )
2326 for ( n
= 0; n
< count
; n
++ )
2328 c
[n
] = GET_UShort();
2330 /* We check whether the specific class is used at all. If not,
2331 class 0 is used instead. */
2339 pcr
->PosLookupRecord
= NULL
;
2341 count
= pcr
->PosCount
;
2343 if ( ALLOC_ARRAY( pcr
->PosLookupRecord
, count
, TTO_PosLookupRecord
) )
2346 plr
= pcr
->PosLookupRecord
;
2348 if ( ACCESS_Frame( count
* 4L ) )
2351 for ( n
= 0; n
< count
; n
++ )
2353 plr
[n
].SequenceIndex
= GET_UShort();
2354 plr
[n
].LookupListIndex
= GET_UShort();
2370 static void Free_PosClassRule( TTO_PosClassRule
* pcr
)
2372 FREE( pcr
->PosLookupRecord
);
2379 static TT_Error
Load_PosClassSet( TTO_ContextPosFormat2
* cpf2
,
2380 TTO_PosClassSet
* pcs
,
2383 DEFINE_LOAD_LOCALS( input
->stream
);
2386 ULong cur_offset
, new_offset
, base_offset
;
2388 TTO_PosClassRule
* pcr
;
2391 base_offset
= FILE_Pos();
2393 if ( ACCESS_Frame( 2L ) )
2396 count
= pcs
->PosClassRuleCount
= GET_UShort();
2400 pcs
->PosClassRule
= NULL
;
2402 if ( ALLOC_ARRAY( pcs
->PosClassRule
, count
, TTO_PosClassRule
) )
2405 pcr
= pcs
->PosClassRule
;
2407 for ( n
= 0; n
< count
; n
++ )
2409 if ( ACCESS_Frame( 2L ) )
2412 new_offset
= GET_UShort() + base_offset
;
2416 cur_offset
= FILE_Pos();
2417 if ( FILE_Seek( new_offset
) ||
2418 ( error
= Load_PosClassRule( cpf2
, &pcr
[n
],
2419 input
) ) != TT_Err_Ok
)
2421 (void)FILE_Seek( cur_offset
);
2427 for ( n
= 0; n
< count
; n
++ )
2428 Free_PosClassRule( &pcr
[n
] );
2435 static void Free_PosClassSet( TTO_PosClassSet
* pcs
)
2439 TTO_PosClassRule
* pcr
;
2442 if ( pcs
->PosClassRule
)
2444 count
= pcs
->PosClassRuleCount
;
2445 pcr
= pcs
->PosClassRule
;
2447 for ( n
= 0; n
< count
; n
++ )
2448 Free_PosClassRule( &pcr
[n
] );
2455 /* ContextPosFormat2 */
2457 static TT_Error
Load_ContextPos2( TTO_ContextPosFormat2
* cpf2
,
2460 DEFINE_LOAD_LOCALS( input
->stream
);
2463 ULong cur_offset
, new_offset
, base_offset
;
2465 TTO_PosClassSet
* pcs
;
2468 base_offset
= FILE_Pos() - 2;
2470 if ( ACCESS_Frame( 2L ) )
2473 new_offset
= GET_UShort() + base_offset
;
2477 cur_offset
= FILE_Pos();
2478 if ( FILE_Seek( new_offset
) ||
2479 ( error
= Load_Coverage( &cpf2
->Coverage
, input
) ) != TT_Err_Ok
)
2481 (void)FILE_Seek( cur_offset
);
2483 if ( ACCESS_Frame( 4L ) )
2486 new_offset
= GET_UShort() + base_offset
;
2488 /* `PosClassSetCount' is the upper limit for class values, thus we
2489 read it now to make an additional safety check. */
2491 count
= cpf2
->PosClassSetCount
= GET_UShort();
2495 cur_offset
= FILE_Pos();
2496 if ( FILE_Seek( new_offset
) ||
2497 ( error
= Load_ClassDefinition( &cpf2
->ClassDef
, count
,
2498 input
) ) != TT_Err_Ok
)
2500 (void)FILE_Seek( cur_offset
);
2502 cpf2
->PosClassSet
= NULL
;
2503 cpf2
->MaxContextLength
= 0;
2505 if ( ALLOC_ARRAY( cpf2
->PosClassSet
, count
, TTO_PosClassSet
) )
2508 pcs
= cpf2
->PosClassSet
;
2510 for ( n
= 0; n
< count
; n
++ )
2512 if ( ACCESS_Frame( 2L ) )
2515 new_offset
= GET_UShort() + base_offset
;
2519 if ( new_offset
!= base_offset
) /* not a NULL offset */
2521 cur_offset
= FILE_Pos();
2522 if ( FILE_Seek( new_offset
) ||
2523 ( error
= Load_PosClassSet( cpf2
, &pcs
[n
],
2524 input
) ) != TT_Err_Ok
)
2526 (void)FILE_Seek( cur_offset
);
2530 /* we create a PosClassSet table with no entries */
2532 cpf2
->PosClassSet
[n
].PosClassRuleCount
= 0;
2533 cpf2
->PosClassSet
[n
].PosClassRule
= NULL
;
2540 for ( n
= 0; n
< count
; n
++ )
2541 Free_PosClassSet( &pcs
[n
] );
2546 Free_ClassDefinition( &cpf2
->ClassDef
);
2549 Free_Coverage( &cpf2
->Coverage
);
2554 static void Free_Context2( TTO_ContextPosFormat2
* cpf2
)
2558 TTO_PosClassSet
* pcs
;
2561 if ( cpf2
->PosClassSet
)
2563 count
= cpf2
->PosClassSetCount
;
2564 pcs
= cpf2
->PosClassSet
;
2566 for ( n
= 0; n
< count
; n
++ )
2567 Free_PosClassSet( &pcs
[n
] );
2572 Free_ClassDefinition( &cpf2
->ClassDef
);
2573 Free_Coverage( &cpf2
->Coverage
);
2577 /* ContextPosFormat3 */
2579 static TT_Error
Load_ContextPos3( TTO_ContextPosFormat3
* cpf3
,
2582 DEFINE_LOAD_LOCALS( input
->stream
);
2585 ULong cur_offset
, new_offset
, base_offset
;
2588 TTO_PosLookupRecord
* plr
;
2591 base_offset
= FILE_Pos() - 2L;
2593 if ( ACCESS_Frame( 4L ) )
2596 cpf3
->GlyphCount
= GET_UShort();
2597 cpf3
->PosCount
= GET_UShort();
2601 cpf3
->Coverage
= NULL
;
2603 count
= cpf3
->GlyphCount
;
2605 if ( ALLOC_ARRAY( cpf3
->Coverage
, count
, TTO_Coverage
) )
2610 for ( n
= 0; n
< count
; n
++ )
2612 if ( ACCESS_Frame( 2L ) )
2615 new_offset
= GET_UShort() + base_offset
;
2619 cur_offset
= FILE_Pos();
2620 if ( FILE_Seek( new_offset
) ||
2621 ( error
= Load_Coverage( &c
[n
], input
) ) != TT_Err_Ok
)
2623 (void)FILE_Seek( cur_offset
);
2626 cpf3
->PosLookupRecord
= NULL
;
2628 count
= cpf3
->PosCount
;
2630 if ( ALLOC_ARRAY( cpf3
->PosLookupRecord
, count
, TTO_PosLookupRecord
) )
2633 plr
= cpf3
->PosLookupRecord
;
2635 if ( ACCESS_Frame( count
* 4L ) )
2638 for ( n
= 0; n
< count
; n
++ )
2640 plr
[n
].SequenceIndex
= GET_UShort();
2641 plr
[n
].LookupListIndex
= GET_UShort();
2652 for ( n
= 0; n
< count
; n
++ )
2653 Free_Coverage( &c
[n
] );
2660 static void Free_Context3( TTO_ContextPosFormat3
* cpf3
)
2667 FREE( cpf3
->PosLookupRecord
);
2669 if ( cpf3
->Coverage
)
2671 count
= cpf3
->GlyphCount
;
2674 for ( n
= 0; n
< count
; n
++ )
2675 Free_Coverage( &c
[n
] );
2684 TT_Error
Load_ContextPos( TTO_ContextPos
* cp
,
2687 DEFINE_LOAD_LOCALS( input
->stream
);
2690 if ( ACCESS_Frame( 2L ) )
2693 cp
->PosFormat
= GET_UShort();
2697 switch ( cp
->PosFormat
)
2700 return Load_ContextPos1( &cp
->cpf
.cpf1
, input
);
2703 return Load_ContextPos2( &cp
->cpf
.cpf2
, input
);
2706 return Load_ContextPos3( &cp
->cpf
.cpf3
, input
);
2709 return TTO_Err_Invalid_GPOS_SubTable_Format
;
2712 return TT_Err_Ok
; /* never reached */
2716 void Free_ContextPos( TTO_ContextPos
* cp
)
2718 switch ( cp
->PosFormat
)
2721 Free_Context1( &cp
->cpf
.cpf1
);
2725 Free_Context2( &cp
->cpf
.cpf2
);
2729 Free_Context3( &cp
->cpf
.cpf3
);
2739 static TT_Error
Load_ChainPosRule( TTO_ChainPosRule
* cpr
,
2742 DEFINE_LOAD_LOCALS( input
->stream
);
2749 TTO_PosLookupRecord
* plr
;
2752 if ( ACCESS_Frame( 2L ) )
2755 cpr
->BacktrackGlyphCount
= GET_UShort();
2759 cpr
->Backtrack
= NULL
;
2761 count
= cpr
->BacktrackGlyphCount
;
2763 if ( ALLOC_ARRAY( cpr
->Backtrack
, count
, UShort
) )
2768 if ( ACCESS_Frame( count
* 2L ) )
2771 for ( n
= 0; n
< count
; n
++ )
2772 b
[n
] = GET_UShort();
2776 if ( ACCESS_Frame( 2L ) )
2779 cpr
->InputGlyphCount
= GET_UShort();
2785 count
= cpr
->InputGlyphCount
- 1; /* only InputGlyphCount - 1 elements */
2787 if ( ALLOC_ARRAY( cpr
->Input
, count
, UShort
) )
2792 if ( ACCESS_Frame( count
* 2L ) )
2795 for ( n
= 0; n
< count
; n
++ )
2796 i
[n
] = GET_UShort();
2800 if ( ACCESS_Frame( 2L ) )
2803 cpr
->LookaheadGlyphCount
= GET_UShort();
2807 cpr
->Lookahead
= NULL
;
2809 count
= cpr
->LookaheadGlyphCount
;
2811 if ( ALLOC_ARRAY( cpr
->Lookahead
, count
, UShort
) )
2816 if ( ACCESS_Frame( count
* 2L ) )
2819 for ( n
= 0; n
< count
; n
++ )
2820 l
[n
] = GET_UShort();
2824 if ( ACCESS_Frame( 2L ) )
2827 cpr
->PosCount
= GET_UShort();
2831 cpr
->PosLookupRecord
= NULL
;
2833 count
= cpr
->PosCount
;
2835 if ( ALLOC_ARRAY( cpr
->PosLookupRecord
, count
, TTO_PosLookupRecord
) )
2838 plr
= cpr
->PosLookupRecord
;
2840 if ( ACCESS_Frame( count
* 4L ) )
2843 for ( n
= 0; n
< count
; n
++ )
2845 plr
[n
].SequenceIndex
= GET_UShort();
2846 plr
[n
].LookupListIndex
= GET_UShort();
2868 static void Free_ChainPosRule( TTO_ChainPosRule
* cpr
)
2870 FREE( cpr
->PosLookupRecord
);
2871 FREE( cpr
->Lookahead
);
2873 FREE( cpr
->Backtrack
);
2877 /* ChainPosRuleSet */
2879 static TT_Error
Load_ChainPosRuleSet( TTO_ChainPosRuleSet
* cprs
,
2882 DEFINE_LOAD_LOCALS( input
->stream
);
2885 ULong cur_offset
, new_offset
, base_offset
;
2887 TTO_ChainPosRule
* cpr
;
2890 base_offset
= FILE_Pos();
2892 if ( ACCESS_Frame( 2L ) )
2895 count
= cprs
->ChainPosRuleCount
= GET_UShort();
2899 cprs
->ChainPosRule
= NULL
;
2901 if ( ALLOC_ARRAY( cprs
->ChainPosRule
, count
, TTO_ChainPosRule
) )
2904 cpr
= cprs
->ChainPosRule
;
2906 for ( n
= 0; n
< count
; n
++ )
2908 if ( ACCESS_Frame( 2L ) )
2911 new_offset
= GET_UShort() + base_offset
;
2915 cur_offset
= FILE_Pos();
2916 if ( FILE_Seek( new_offset
) ||
2917 ( error
= Load_ChainPosRule( &cpr
[n
], input
) ) != TT_Err_Ok
)
2919 (void)FILE_Seek( cur_offset
);
2925 for ( n
= 0; n
< count
; n
++ )
2926 Free_ChainPosRule( &cpr
[n
] );
2933 static void Free_ChainPosRuleSet( TTO_ChainPosRuleSet
* cprs
)
2937 TTO_ChainPosRule
* cpr
;
2940 if ( cprs
->ChainPosRule
)
2942 count
= cprs
->ChainPosRuleCount
;
2943 cpr
= cprs
->ChainPosRule
;
2945 for ( n
= 0; n
< count
; n
++ )
2946 Free_ChainPosRule( &cpr
[n
] );
2953 /* ChainContextPosFormat1 */
2955 static TT_Error
Load_ChainContextPos1( TTO_ChainContextPosFormat1
* ccpf1
,
2958 DEFINE_LOAD_LOCALS( input
->stream
);
2961 ULong cur_offset
, new_offset
, base_offset
;
2963 TTO_ChainPosRuleSet
* cprs
;
2966 base_offset
= FILE_Pos() - 2L;
2968 if ( ACCESS_Frame( 2L ) )
2971 new_offset
= GET_UShort() + base_offset
;
2975 cur_offset
= FILE_Pos();
2976 if ( FILE_Seek( new_offset
) ||
2977 ( error
= Load_Coverage( &ccpf1
->Coverage
, input
) ) != TT_Err_Ok
)
2979 (void)FILE_Seek( cur_offset
);
2981 if ( ACCESS_Frame( 2L ) )
2984 count
= ccpf1
->ChainPosRuleSetCount
= GET_UShort();
2988 ccpf1
->ChainPosRuleSet
= NULL
;
2990 if ( ALLOC_ARRAY( ccpf1
->ChainPosRuleSet
, count
, TTO_ChainPosRuleSet
) )
2993 cprs
= ccpf1
->ChainPosRuleSet
;
2995 for ( n
= 0; n
< count
; n
++ )
2997 if ( ACCESS_Frame( 2L ) )
3000 new_offset
= GET_UShort() + base_offset
;
3004 cur_offset
= FILE_Pos();
3005 if ( FILE_Seek( new_offset
) ||
3006 ( error
= Load_ChainPosRuleSet( &cprs
[n
], input
) ) != TT_Err_Ok
)
3008 (void)FILE_Seek( cur_offset
);
3014 for ( n
= 0; n
< count
; n
++ )
3015 Free_ChainPosRuleSet( &cprs
[n
] );
3020 Free_Coverage( &ccpf1
->Coverage
);
3025 static void Free_ChainContext1( TTO_ChainContextPosFormat1
* ccpf1
)
3029 TTO_ChainPosRuleSet
* cprs
;
3032 if ( ccpf1
->ChainPosRuleSet
)
3034 count
= ccpf1
->ChainPosRuleSetCount
;
3035 cprs
= ccpf1
->ChainPosRuleSet
;
3037 for ( n
= 0; n
< count
; n
++ )
3038 Free_ChainPosRuleSet( &cprs
[n
] );
3043 Free_Coverage( &ccpf1
->Coverage
);
3047 /* ChainPosClassRule */
3049 static TT_Error
Load_ChainPosClassRule(
3050 TTO_ChainContextPosFormat2
* ccpf2
,
3051 TTO_ChainPosClassRule
* cpcr
,
3054 DEFINE_LOAD_LOCALS( input
->stream
);
3061 TTO_PosLookupRecord
* plr
;
3065 if ( ACCESS_Frame( 2L ) )
3068 cpcr
->BacktrackGlyphCount
= GET_UShort();
3072 if ( cpcr
->BacktrackGlyphCount
> ccpf2
->MaxBacktrackLength
)
3073 ccpf2
->MaxBacktrackLength
= cpcr
->BacktrackGlyphCount
;
3075 cpcr
->Backtrack
= NULL
;
3077 count
= cpcr
->BacktrackGlyphCount
;
3079 if ( ALLOC_ARRAY( cpcr
->Backtrack
, count
, UShort
) )
3082 b
= cpcr
->Backtrack
;
3083 d
= ccpf2
->BacktrackClassDef
.Defined
;
3085 if ( ACCESS_Frame( count
* 2L ) )
3088 for ( n
= 0; n
< count
; n
++ )
3090 b
[n
] = GET_UShort();
3092 /* We check whether the specific class is used at all. If not,
3093 class 0 is used instead. */
3101 if ( ACCESS_Frame( 2L ) )
3104 cpcr
->InputGlyphCount
= GET_UShort();
3106 if ( cpcr
->InputGlyphCount
> ccpf2
->MaxInputLength
)
3107 ccpf2
->MaxInputLength
= cpcr
->InputGlyphCount
;
3113 count
= cpcr
->InputGlyphCount
- 1; /* only InputGlyphCount - 1 elements */
3115 if ( ALLOC_ARRAY( cpcr
->Input
, count
, UShort
) )
3119 d
= ccpf2
->InputClassDef
.Defined
;
3121 if ( ACCESS_Frame( count
* 2L ) )
3124 for ( n
= 0; n
< count
; n
++ )
3126 i
[n
] = GET_UShort();
3134 if ( ACCESS_Frame( 2L ) )
3137 cpcr
->LookaheadGlyphCount
= GET_UShort();
3141 if ( cpcr
->LookaheadGlyphCount
> ccpf2
->MaxLookaheadLength
)
3142 ccpf2
->MaxLookaheadLength
= cpcr
->LookaheadGlyphCount
;
3144 cpcr
->Lookahead
= NULL
;
3146 count
= cpcr
->LookaheadGlyphCount
;
3148 if ( ALLOC_ARRAY( cpcr
->Lookahead
, count
, UShort
) )
3151 l
= cpcr
->Lookahead
;
3152 d
= ccpf2
->LookaheadClassDef
.Defined
;
3154 if ( ACCESS_Frame( count
* 2L ) )
3157 for ( n
= 0; n
< count
; n
++ )
3159 l
[n
] = GET_UShort();
3167 if ( ACCESS_Frame( 2L ) )
3170 cpcr
->PosCount
= GET_UShort();
3174 cpcr
->PosLookupRecord
= NULL
;
3176 count
= cpcr
->PosCount
;
3178 if ( ALLOC_ARRAY( cpcr
->PosLookupRecord
, count
, TTO_PosLookupRecord
) )
3181 plr
= cpcr
->PosLookupRecord
;
3183 if ( ACCESS_Frame( count
* 4L ) )
3186 for ( n
= 0; n
< count
; n
++ )
3188 plr
[n
].SequenceIndex
= GET_UShort();
3189 plr
[n
].LookupListIndex
= GET_UShort();
3211 static void Free_ChainPosClassRule( TTO_ChainPosClassRule
* cpcr
)
3213 FREE( cpcr
->PosLookupRecord
);
3214 FREE( cpcr
->Lookahead
);
3215 FREE( cpcr
->Input
);
3216 FREE( cpcr
->Backtrack
);
3222 static TT_Error
Load_ChainPosClassSet(
3223 TTO_ChainContextPosFormat2
* ccpf2
,
3224 TTO_ChainPosClassSet
* cpcs
,
3227 DEFINE_LOAD_LOCALS( input
->stream
);
3230 ULong cur_offset
, new_offset
, base_offset
;
3232 TTO_ChainPosClassRule
* cpcr
;
3235 base_offset
= FILE_Pos();
3237 if ( ACCESS_Frame( 2L ) )
3240 count
= cpcs
->ChainPosClassRuleCount
= GET_UShort();
3244 cpcs
->ChainPosClassRule
= NULL
;
3246 if ( ALLOC_ARRAY( cpcs
->ChainPosClassRule
, count
,
3247 TTO_ChainPosClassRule
) )
3250 cpcr
= cpcs
->ChainPosClassRule
;
3252 for ( n
= 0; n
< count
; n
++ )
3254 if ( ACCESS_Frame( 2L ) )
3257 new_offset
= GET_UShort() + base_offset
;
3261 cur_offset
= FILE_Pos();
3262 if ( FILE_Seek( new_offset
) ||
3263 ( error
= Load_ChainPosClassRule( ccpf2
, &cpcr
[n
],
3264 input
) ) != TT_Err_Ok
)
3266 (void)FILE_Seek( cur_offset
);
3272 for ( n
= 0; n
< count
; n
++ )
3273 Free_ChainPosClassRule( &cpcr
[n
] );
3280 static void Free_ChainPosClassSet( TTO_ChainPosClassSet
* cpcs
)
3284 TTO_ChainPosClassRule
* cpcr
;
3287 if ( cpcs
->ChainPosClassRule
)
3289 count
= cpcs
->ChainPosClassRuleCount
;
3290 cpcr
= cpcs
->ChainPosClassRule
;
3292 for ( n
= 0; n
< count
; n
++ )
3293 Free_ChainPosClassRule( &cpcr
[n
] );
3300 /* ChainContextPosFormat2 */
3302 static TT_Error
Load_ChainContextPos2( TTO_ChainContextPosFormat2
* ccpf2
,
3305 DEFINE_LOAD_LOCALS( input
->stream
);
3308 ULong cur_offset
, new_offset
, base_offset
;
3309 ULong backtrack_offset
, input_offset
, lookahead_offset
;
3311 TTO_ChainPosClassSet
* cpcs
;
3314 base_offset
= FILE_Pos() - 2;
3316 if ( ACCESS_Frame( 2L ) )
3319 new_offset
= GET_UShort() + base_offset
;
3323 cur_offset
= FILE_Pos();
3324 if ( FILE_Seek( new_offset
) ||
3325 ( error
= Load_Coverage( &ccpf2
->Coverage
, input
) ) != TT_Err_Ok
)
3327 (void)FILE_Seek( cur_offset
);
3329 if ( ACCESS_Frame( 8L ) )
3332 backtrack_offset
= GET_UShort() + base_offset
;
3333 input_offset
= GET_UShort() + base_offset
;
3334 lookahead_offset
= GET_UShort() + base_offset
;
3336 /* `ChainPosClassSetCount' is the upper limit for input class values,
3337 thus we read it now to make an additional safety check. */
3339 count
= ccpf2
->ChainPosClassSetCount
= GET_UShort();
3343 cur_offset
= FILE_Pos();
3344 if ( FILE_Seek( backtrack_offset
) ||
3345 ( error
= Load_ClassDefinition( &ccpf2
->BacktrackClassDef
, count
,
3346 input
) ) != TT_Err_Ok
)
3348 if ( FILE_Seek( input_offset
) ||
3349 ( error
= Load_ClassDefinition( &ccpf2
->InputClassDef
, count
,
3350 input
) ) != TT_Err_Ok
)
3352 if ( FILE_Seek( lookahead_offset
) ||
3353 ( error
= Load_ClassDefinition( &ccpf2
->LookaheadClassDef
, count
,
3354 input
) ) != TT_Err_Ok
)
3356 (void)FILE_Seek( cur_offset
);
3358 ccpf2
->ChainPosClassSet
= NULL
;
3359 ccpf2
->MaxBacktrackLength
= 0;
3360 ccpf2
->MaxInputLength
= 0;
3361 ccpf2
->MaxLookaheadLength
= 0;
3363 if ( ALLOC_ARRAY( ccpf2
->ChainPosClassSet
, count
, TTO_ChainPosClassSet
) )
3366 cpcs
= ccpf2
->ChainPosClassSet
;
3368 for ( n
= 0; n
< count
; n
++ )
3370 if ( ACCESS_Frame( 2L ) )
3373 new_offset
= GET_UShort() + base_offset
;
3377 if ( new_offset
!= base_offset
) /* not a NULL offset */
3379 cur_offset
= FILE_Pos();
3380 if ( FILE_Seek( new_offset
) ||
3381 ( error
= Load_ChainPosClassSet( ccpf2
, &cpcs
[n
],
3382 input
) ) != TT_Err_Ok
)
3384 (void)FILE_Seek( cur_offset
);
3388 /* we create a ChainPosClassSet table with no entries */
3390 ccpf2
->ChainPosClassSet
[n
].ChainPosClassRuleCount
= 0;
3391 ccpf2
->ChainPosClassSet
[n
].ChainPosClassRule
= NULL
;
3398 for ( n
= 0; n
< count
; n
++ )
3399 Free_ChainPosClassSet( &cpcs
[n
] );
3404 Free_ClassDefinition( &ccpf2
->LookaheadClassDef
);
3407 Free_ClassDefinition( &ccpf2
->InputClassDef
);
3410 Free_ClassDefinition( &ccpf2
->BacktrackClassDef
);
3413 Free_Coverage( &ccpf2
->Coverage
);
3418 static void Free_ChainContext2( TTO_ChainContextPosFormat2
* ccpf2
)
3422 TTO_ChainPosClassSet
* cpcs
;
3425 if ( ccpf2
->ChainPosClassSet
)
3427 count
= ccpf2
->ChainPosClassSetCount
;
3428 cpcs
= ccpf2
->ChainPosClassSet
;
3430 for ( n
= 0; n
< count
; n
++ )
3431 Free_ChainPosClassSet( &cpcs
[n
] );
3436 Free_ClassDefinition( &ccpf2
->LookaheadClassDef
);
3437 Free_ClassDefinition( &ccpf2
->InputClassDef
);
3438 Free_ClassDefinition( &ccpf2
->BacktrackClassDef
);
3440 Free_Coverage( &ccpf2
->Coverage
);
3444 /* ChainContextPosFormat3 */
3446 static TT_Error
Load_ChainContextPos3( TTO_ChainContextPosFormat3
* ccpf3
,
3449 DEFINE_LOAD_LOCALS( input
->stream
);
3452 UShort backtrack_count
, input_count
, lookahead_count
;
3453 ULong cur_offset
, new_offset
, base_offset
;
3458 TTO_PosLookupRecord
* plr
;
3461 base_offset
= FILE_Pos() - 2L;
3463 if ( ACCESS_Frame( 2L ) )
3466 ccpf3
->BacktrackGlyphCount
= GET_UShort();
3470 ccpf3
->BacktrackCoverage
= NULL
;
3472 backtrack_count
= ccpf3
->BacktrackGlyphCount
;
3474 if ( ALLOC_ARRAY( ccpf3
->BacktrackCoverage
, backtrack_count
,
3478 b
= ccpf3
->BacktrackCoverage
;
3480 for ( n
= 0; n
< backtrack_count
; n
++ )
3482 if ( ACCESS_Frame( 2L ) )
3485 new_offset
= GET_UShort() + base_offset
;
3489 cur_offset
= FILE_Pos();
3490 if ( FILE_Seek( new_offset
) ||
3491 ( error
= Load_Coverage( &b
[n
], input
) ) != TT_Err_Ok
)
3493 (void)FILE_Seek( cur_offset
);
3496 if ( ACCESS_Frame( 2L ) )
3499 ccpf3
->InputGlyphCount
= GET_UShort();
3503 ccpf3
->InputCoverage
= NULL
;
3505 input_count
= ccpf3
->InputGlyphCount
;
3507 if ( ALLOC_ARRAY( ccpf3
->InputCoverage
, input_count
, TTO_Coverage
) )
3510 i
= ccpf3
->InputCoverage
;
3512 for ( n
= 0; n
< input_count
; n
++ )
3514 if ( ACCESS_Frame( 2L ) )
3517 new_offset
= GET_UShort() + base_offset
;
3521 cur_offset
= FILE_Pos();
3522 if ( FILE_Seek( new_offset
) ||
3523 ( error
= Load_Coverage( &i
[n
], input
) ) != TT_Err_Ok
)
3525 (void)FILE_Seek( cur_offset
);
3528 if ( ACCESS_Frame( 2L ) )
3531 ccpf3
->LookaheadGlyphCount
= GET_UShort();
3535 ccpf3
->LookaheadCoverage
= NULL
;
3537 lookahead_count
= ccpf3
->LookaheadGlyphCount
;
3539 if ( ALLOC_ARRAY( ccpf3
->LookaheadCoverage
, lookahead_count
,
3543 l
= ccpf3
->LookaheadCoverage
;
3545 for ( n
= 0; n
< lookahead_count
; n
++ )
3547 if ( ACCESS_Frame( 2L ) )
3550 new_offset
= GET_UShort() + base_offset
;
3554 cur_offset
= FILE_Pos();
3555 if ( FILE_Seek( new_offset
) ||
3556 ( error
= Load_Coverage( &l
[n
], input
) ) != TT_Err_Ok
)
3558 (void)FILE_Seek( cur_offset
);
3561 if ( ACCESS_Frame( 2L ) )
3564 ccpf3
->PosCount
= GET_UShort();
3568 ccpf3
->PosLookupRecord
= NULL
;
3570 count
= ccpf3
->PosCount
;
3572 if ( ALLOC_ARRAY( ccpf3
->PosLookupRecord
, count
, TTO_PosLookupRecord
) )
3575 plr
= ccpf3
->PosLookupRecord
;
3577 if ( ACCESS_Frame( count
* 4L ) )
3580 for ( n
= 0; n
< count
; n
++ )
3582 plr
[n
].SequenceIndex
= GET_UShort();
3583 plr
[n
].LookupListIndex
= GET_UShort();
3594 for ( n
= 0; n
< lookahead_count
; n
++ )
3595 Free_Coverage( &l
[n
] );
3600 for ( n
= 0; n
< input_count
; n
++ )
3601 Free_Coverage( &i
[n
] );
3606 for ( n
= 0; n
< backtrack_count
; n
++ )
3607 Free_Coverage( &b
[n
] );
3614 static void Free_ChainContext3( TTO_ChainContextPosFormat3
* ccpf3
)
3621 FREE( ccpf3
->PosLookupRecord
);
3623 if ( ccpf3
->LookaheadCoverage
)
3625 count
= ccpf3
->LookaheadGlyphCount
;
3626 c
= ccpf3
->LookaheadCoverage
;
3628 for ( n
= 0; n
< count
; n
++ )
3629 Free_Coverage( &c
[n
] );
3634 if ( ccpf3
->InputCoverage
)
3636 count
= ccpf3
->InputGlyphCount
;
3637 c
= ccpf3
->InputCoverage
;
3639 for ( n
= 0; n
< count
; n
++ )
3640 Free_Coverage( &c
[n
] );
3645 if ( ccpf3
->BacktrackCoverage
)
3647 count
= ccpf3
->BacktrackGlyphCount
;
3648 c
= ccpf3
->BacktrackCoverage
;
3650 for ( n
= 0; n
< count
; n
++ )
3651 Free_Coverage( &c
[n
] );
3658 /* ChainContextPos */
3660 TT_Error
Load_ChainContextPos( TTO_ChainContextPos
* ccp
,
3663 DEFINE_LOAD_LOCALS( input
->stream
);
3666 if ( ACCESS_Frame( 2L ) )
3669 ccp
->PosFormat
= GET_UShort();
3673 switch ( ccp
->PosFormat
)
3676 return Load_ChainContextPos1( &ccp
->ccpf
.ccpf1
, input
);
3679 return Load_ChainContextPos2( &ccp
->ccpf
.ccpf2
, input
);
3682 return Load_ChainContextPos3( &ccp
->ccpf
.ccpf3
, input
);
3685 return TTO_Err_Invalid_GPOS_SubTable_Format
;
3688 return TT_Err_Ok
; /* never reached */
3692 void Free_ChainContextPos( TTO_ChainContextPos
* ccp
)
3694 switch ( ccp
->PosFormat
)
3697 Free_ChainContext1( &ccp
->ccpf
.ccpf1
);
3701 Free_ChainContext2( &ccp
->ccpf
.ccpf2
);
3705 Free_ChainContext3( &ccp
->ccpf
.ccpf3
);
3718 TT_Error
TT_GPOS_Select_Script( TTO_GPOSHeader
* gpos
,
3719 TT_ULong script_tag
,
3720 TT_UShort
* script_index
)
3725 TTO_ScriptRecord
* sr
;
3728 if ( !gpos
|| !script_index
)
3729 return TT_Err_Invalid_Argument
;
3731 sl
= &gpos
->ScriptList
;
3732 sr
= sl
->ScriptRecord
;
3734 for ( n
= 0; n
< sl
->ScriptCount
; n
++ )
3735 if ( script_tag
== sr
[n
].ScriptTag
)
3742 return TTO_Err_Not_Covered
;
3747 TT_Error
TT_GPOS_Select_Language( TTO_GPOSHeader
* gpos
,
3748 TT_ULong language_tag
,
3749 TT_UShort script_index
,
3750 TT_UShort
* language_index
,
3751 TT_UShort
* req_feature_index
)
3756 TTO_ScriptRecord
* sr
;
3758 TTO_LangSysRecord
* lsr
;
3761 if ( !gpos
|| !language_index
|| !req_feature_index
)
3762 return TT_Err_Invalid_Argument
;
3764 sl
= &gpos
->ScriptList
;
3765 sr
= sl
->ScriptRecord
;
3767 if ( script_index
>= sl
->ScriptCount
)
3768 return TT_Err_Invalid_Argument
;
3770 s
= &sr
[script_index
].Script
;
3771 lsr
= s
->LangSysRecord
;
3773 for ( n
= 0; n
< s
->LangSysCount
; n
++ )
3774 if ( language_tag
== lsr
[n
].LangSysTag
)
3776 *language_index
= n
;
3777 *req_feature_index
= lsr
[n
].LangSys
.ReqFeatureIndex
;
3782 return TTO_Err_Not_Covered
;
3786 /* selecting 0xFFFF for language_index asks for the values of the
3787 default language (DefaultLangSys) */
3790 TT_Error
TT_GPOS_Select_Feature( TTO_GPOSHeader
* gpos
,
3791 TT_ULong feature_tag
,
3792 TT_UShort script_index
,
3793 TT_UShort language_index
,
3794 TT_UShort
* feature_index
)
3799 TTO_ScriptRecord
* sr
;
3801 TTO_LangSysRecord
* lsr
;
3805 TTO_FeatureList
* fl
;
3806 TTO_FeatureRecord
* fr
;
3809 if ( !gpos
|| !feature_index
)
3810 return TT_Err_Invalid_Argument
;
3812 sl
= &gpos
->ScriptList
;
3813 sr
= sl
->ScriptRecord
;
3815 fl
= &gpos
->FeatureList
;
3816 fr
= fl
->FeatureRecord
;
3818 if ( script_index
>= sl
->ScriptCount
)
3819 return TT_Err_Invalid_Argument
;
3821 s
= &sr
[script_index
].Script
;
3822 lsr
= s
->LangSysRecord
;
3824 if ( language_index
== 0xFFFF )
3825 ls
= &s
->DefaultLangSys
;
3828 if ( language_index
>= s
->LangSysCount
)
3829 return TT_Err_Invalid_Argument
;
3831 ls
= &lsr
[language_index
].LangSys
;
3834 fi
= ls
->FeatureIndex
;
3836 for ( n
= 0; n
< ls
->FeatureCount
; n
++ )
3838 if ( fi
[n
] >= fl
->FeatureCount
)
3839 return TTO_Err_Invalid_GPOS_SubTable_Format
;
3841 if ( feature_tag
== fr
[fi
[n
]].FeatureTag
)
3843 *feature_index
= fi
[n
];
3849 return TTO_Err_Not_Covered
;
3853 /* The next three functions return a null-terminated list */
3856 TT_Error
TT_GPOS_Query_Scripts( TTO_GPOSHeader
* gpos
,
3857 TT_ULong
** script_tag_list
)
3864 TTO_ScriptRecord
* sr
;
3867 if ( !gpos
|| !script_tag_list
)
3868 return TT_Err_Invalid_Argument
;
3870 sl
= &gpos
->ScriptList
;
3871 sr
= sl
->ScriptRecord
;
3873 if ( ALLOC_ARRAY( stl
, sl
->ScriptCount
+ 1, ULong
) )
3876 for ( n
= 0; n
< sl
->ScriptCount
; n
++ )
3877 stl
[n
] = sr
[n
].ScriptTag
;
3880 *script_tag_list
= stl
;
3887 TT_Error
TT_GPOS_Query_Languages( TTO_GPOSHeader
* gpos
,
3888 TT_UShort script_index
,
3889 TT_ULong
** language_tag_list
)
3896 TTO_ScriptRecord
* sr
;
3898 TTO_LangSysRecord
* lsr
;
3901 if ( !gpos
|| !language_tag_list
)
3902 return TT_Err_Invalid_Argument
;
3904 sl
= &gpos
->ScriptList
;
3905 sr
= sl
->ScriptRecord
;
3907 if ( script_index
>= sl
->ScriptCount
)
3908 return TT_Err_Invalid_Argument
;
3910 s
= &sr
[script_index
].Script
;
3911 lsr
= s
->LangSysRecord
;
3913 if ( ALLOC_ARRAY( ltl
, s
->LangSysCount
+ 1, ULong
) )
3916 for ( n
= 0; n
< s
->LangSysCount
; n
++ )
3917 ltl
[n
] = lsr
[n
].LangSysTag
;
3920 *language_tag_list
= ltl
;
3926 /* selecting 0xFFFF for language_index asks for the values of the
3927 default language (DefaultLangSys) */
3930 TT_Error
TT_GPOS_Query_Features( TTO_GPOSHeader
* gpos
,
3931 TT_UShort script_index
,
3932 TT_UShort language_index
,
3933 TT_ULong
** feature_tag_list
)
3940 TTO_ScriptRecord
* sr
;
3942 TTO_LangSysRecord
* lsr
;
3946 TTO_FeatureList
* fl
;
3947 TTO_FeatureRecord
* fr
;
3950 if ( !gpos
|| !feature_tag_list
)
3951 return TT_Err_Invalid_Argument
;
3953 sl
= &gpos
->ScriptList
;
3954 sr
= sl
->ScriptRecord
;
3956 fl
= &gpos
->FeatureList
;
3957 fr
= fl
->FeatureRecord
;
3959 if ( script_index
>= sl
->ScriptCount
)
3960 return TT_Err_Invalid_Argument
;
3962 s
= &sr
[script_index
].Script
;
3963 lsr
= s
->LangSysRecord
;
3965 if ( language_index
== 0xFFFF )
3966 ls
= &s
->DefaultLangSys
;
3969 if ( language_index
>= s
->LangSysCount
)
3970 return TT_Err_Invalid_Argument
;
3972 ls
= &lsr
[language_index
].LangSys
;
3975 fi
= ls
->FeatureIndex
;
3977 if ( ALLOC_ARRAY( ftl
, ls
->FeatureCount
+ 1, ULong
) )
3980 for ( n
= 0; n
< ls
->FeatureCount
; n
++ )
3982 if ( fi
[n
] >= fl
->FeatureCount
)
3985 return TTO_Err_Invalid_GPOS_SubTable_Format
;
3987 ftl
[n
] = fr
[fi
[n
]].FeatureTag
;
3991 *feature_tag_list
= ftl
;
3998 TT_Error
TT_GPOS_Add_Feature( TTO_GPOSHeader
* gpos
,
3999 TT_UShort feature_index
,
4000 TT_UShort property
)
4004 TTO_Feature feature
;
4010 feature_index
>= gpos
->FeatureList
.FeatureCount
)
4011 return TT_Err_Invalid_Argument
;
4013 properties
= gpos
->LookupList
.Properties
;
4015 feature
= gpos
->FeatureList
.FeatureRecord
[feature_index
].Feature
;
4016 index
= feature
.LookupListIndex
;
4018 for ( i
= 0; i
< feature
.LookupListCount
; i
++ )
4019 properties
[index
[i
]] |= property
;
4026 TT_Error
TT_GPOS_Clear_Features( TTO_GPOSHeader
* gpos
)
4034 return TT_Err_Invalid_Argument
;
4036 properties
= gpos
->LookupList
.Properties
;
4038 for ( i
= 0; i
< gpos
->LookupList
.LookupCount
; i
++ )