2 * Copyright (C) 1998-2004 David Turner and Werner Lemberg
3 * Copyright (C) 2006 Behdad Esfahbod
5 * This is part of HarfBuzz, an OpenType Layout engine library.
7 * Permission is hereby granted, without written agreement and without
8 * license or royalty fees, to use, copy, modify, and distribute this
9 * software and its documentation for any purpose, provided that the
10 * above copyright notice and the following two paragraphs appear in
11 * all copies of this software.
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
26 #include "harfbuzz-impl.h"
27 #include "harfbuzz-open-private.h"
30 /***************************
31 * Script related functions
32 ***************************/
37 static HB_Error
Load_LangSys( HB_LangSys
* ls
,
45 if ( ACCESS_Frame( 6L ) )
48 ls
->LookupOrderOffset
= GET_UShort(); /* should be 0 */
49 ls
->ReqFeatureIndex
= GET_UShort();
50 count
= ls
->FeatureCount
= GET_UShort();
54 ls
->FeatureIndex
= NULL
;
56 if ( ALLOC_ARRAY( ls
->FeatureIndex
, count
, HB_UShort
) )
59 if ( ACCESS_Frame( count
* 2L ) )
61 FREE( ls
->FeatureIndex
);
65 fi
= ls
->FeatureIndex
;
67 for ( n
= 0; n
< count
; n
++ )
76 static void Free_LangSys( HB_LangSys
* ls
)
78 FREE( ls
->FeatureIndex
);
84 static HB_Error
Load_Script( HB_ScriptTable
* s
,
88 HB_UShort n
, m
, count
;
89 HB_UInt cur_offset
, new_offset
, base_offset
;
91 HB_LangSysRecord
* lsr
;
94 base_offset
= FILE_Pos();
96 if ( ACCESS_Frame( 2L ) )
99 new_offset
= GET_UShort() + base_offset
;
103 if ( new_offset
!= base_offset
) /* not a NULL offset */
105 cur_offset
= FILE_Pos();
106 if ( FILE_Seek( new_offset
) ||
107 ( error
= Load_LangSys( &s
->DefaultLangSys
,
108 stream
) ) != HB_Err_Ok
)
110 (void)FILE_Seek( cur_offset
);
114 /* we create a DefaultLangSys table with no entries */
116 s
->DefaultLangSys
.LookupOrderOffset
= 0;
117 s
->DefaultLangSys
.ReqFeatureIndex
= 0xFFFF;
118 s
->DefaultLangSys
.FeatureCount
= 0;
119 s
->DefaultLangSys
.FeatureIndex
= NULL
;
122 if ( ACCESS_Frame( 2L ) )
125 count
= s
->LangSysCount
= GET_UShort();
127 /* safety check; otherwise the official handling of TrueType Open
130 if ( s
->LangSysCount
== 0 && s
->DefaultLangSys
.FeatureCount
== 0 )
132 error
= HB_Err_Not_Covered
;
138 s
->LangSysRecord
= NULL
;
140 if ( ALLOC_ARRAY( s
->LangSysRecord
, count
, HB_LangSysRecord
) )
143 lsr
= s
->LangSysRecord
;
145 for ( n
= 0; n
< count
; n
++ )
147 if ( ACCESS_Frame( 6L ) )
150 lsr
[n
].LangSysTag
= GET_ULong();
151 new_offset
= GET_UShort() + base_offset
;
155 cur_offset
= FILE_Pos();
156 if ( FILE_Seek( new_offset
) ||
157 ( error
= Load_LangSys( &lsr
[n
].LangSys
, stream
) ) != HB_Err_Ok
)
159 (void)FILE_Seek( cur_offset
);
165 for ( m
= 0; m
< n
; m
++ )
166 Free_LangSys( &lsr
[m
].LangSys
);
168 FREE( s
->LangSysRecord
);
171 Free_LangSys( &s
->DefaultLangSys
);
176 static void Free_Script( HB_ScriptTable
* s
)
180 HB_LangSysRecord
* lsr
;
183 Free_LangSys( &s
->DefaultLangSys
);
185 if ( s
->LangSysRecord
)
187 count
= s
->LangSysCount
;
188 lsr
= s
->LangSysRecord
;
190 for ( n
= 0; n
< count
; n
++ )
191 Free_LangSys( &lsr
[n
].LangSys
);
201 _HB_OPEN_Load_ScriptList( HB_ScriptList
* sl
,
206 HB_UShort n
, script_count
;
207 HB_UInt cur_offset
, new_offset
, base_offset
;
212 base_offset
= FILE_Pos();
214 if ( ACCESS_Frame( 2L ) )
217 script_count
= GET_UShort();
221 sl
->ScriptRecord
= NULL
;
223 if ( ALLOC_ARRAY( sl
->ScriptRecord
, script_count
, HB_ScriptRecord
) )
226 sr
= sl
->ScriptRecord
;
229 for ( n
= 0; n
< script_count
; n
++ )
231 if ( ACCESS_Frame( 6L ) )
234 sr
[sl
->ScriptCount
].ScriptTag
= GET_ULong();
235 new_offset
= GET_UShort() + base_offset
;
239 cur_offset
= FILE_Pos();
241 if ( FILE_Seek( new_offset
) )
244 error
= Load_Script( &sr
[sl
->ScriptCount
].Script
, stream
);
245 if ( error
== HB_Err_Ok
)
246 sl
->ScriptCount
+= 1;
247 else if ( error
!= HB_Err_Not_Covered
)
250 (void)FILE_Seek( cur_offset
);
253 /* Empty tables are harmless and generated by fontforge.
254 * See http://bugzilla.gnome.org/show_bug.cgi?id=347073
257 if ( sl
->ScriptCount
== 0 )
259 error
= ERR(HB_Err_Invalid_SubTable
);
267 for ( n
= 0; n
< sl
->ScriptCount
; n
++ )
268 Free_Script( &sr
[n
].Script
);
270 FREE( sl
->ScriptRecord
);
276 _HB_OPEN_Free_ScriptList( HB_ScriptList
* sl
)
283 if ( sl
->ScriptRecord
)
285 count
= sl
->ScriptCount
;
286 sr
= sl
->ScriptRecord
;
288 for ( n
= 0; n
< count
; n
++ )
289 Free_Script( &sr
[n
].Script
);
297 /*********************************
298 * Feature List related functions
299 *********************************/
304 static HB_Error
Load_Feature( HB_Feature
* f
,
314 if ( ACCESS_Frame( 4L ) )
317 f
->FeatureParams
= GET_UShort(); /* should be 0 */
318 count
= f
->LookupListCount
= GET_UShort();
322 f
->LookupListIndex
= NULL
;
324 if ( ALLOC_ARRAY( f
->LookupListIndex
, count
, HB_UShort
) )
327 lli
= f
->LookupListIndex
;
329 if ( ACCESS_Frame( count
* 2L ) )
331 FREE( f
->LookupListIndex
);
335 for ( n
= 0; n
< count
; n
++ )
336 lli
[n
] = GET_UShort();
344 static void Free_Feature( HB_Feature
* f
)
346 FREE( f
->LookupListIndex
);
353 _HB_OPEN_Load_FeatureList( HB_FeatureList
* fl
,
358 HB_UShort n
, m
, count
;
359 HB_UInt cur_offset
, new_offset
, base_offset
;
361 HB_FeatureRecord
* fr
;
364 base_offset
= FILE_Pos();
366 if ( ACCESS_Frame( 2L ) )
369 count
= fl
->FeatureCount
= GET_UShort();
373 fl
->FeatureRecord
= NULL
;
375 if ( ALLOC_ARRAY( fl
->FeatureRecord
, count
, HB_FeatureRecord
) )
377 if ( ALLOC_ARRAY( fl
->ApplyOrder
, count
, HB_UShort
) )
382 fr
= fl
->FeatureRecord
;
384 for ( n
= 0; n
< count
; n
++ )
386 if ( ACCESS_Frame( 6L ) )
389 fr
[n
].FeatureTag
= GET_ULong();
390 new_offset
= GET_UShort() + base_offset
;
394 cur_offset
= FILE_Pos();
395 if ( FILE_Seek( new_offset
) ||
396 ( error
= Load_Feature( &fr
[n
].Feature
, stream
) ) != HB_Err_Ok
)
398 (void)FILE_Seek( cur_offset
);
404 for ( m
= 0; m
< n
; m
++ )
405 Free_Feature( &fr
[m
].Feature
);
407 FREE( fl
->ApplyOrder
);
410 FREE( fl
->FeatureRecord
);
417 _HB_OPEN_Free_FeatureList( HB_FeatureList
* fl
)
421 HB_FeatureRecord
* fr
;
424 if ( fl
->FeatureRecord
)
426 count
= fl
->FeatureCount
;
427 fr
= fl
->FeatureRecord
;
429 for ( n
= 0; n
< count
; n
++ )
430 Free_Feature( &fr
[n
].Feature
);
435 FREE( fl
->ApplyOrder
);
440 /********************************
441 * Lookup List related functions
442 ********************************/
444 /* the subroutines of the following two functions are defined in
445 ftxgsub.c and ftxgpos.c respectively */
450 static HB_Error
Load_SubTable( HB_SubTable
* st
,
453 HB_UShort lookup_type
)
455 if ( table_type
== HB_Type_GSUB
)
456 return _HB_GSUB_Load_SubTable ( &st
->st
.gsub
, stream
, lookup_type
);
458 return _HB_GPOS_Load_SubTable ( &st
->st
.gpos
, stream
, lookup_type
);
462 static void Free_SubTable( HB_SubTable
* st
,
464 HB_UShort lookup_type
)
466 if ( table_type
== HB_Type_GSUB
)
467 _HB_GSUB_Free_SubTable ( &st
->st
.gsub
, lookup_type
);
469 _HB_GPOS_Free_SubTable ( &st
->st
.gpos
, lookup_type
);
475 static HB_Error
Load_Lookup( HB_Lookup
* l
,
481 HB_UShort n
, m
, count
;
482 HB_UInt cur_offset
, new_offset
, base_offset
;
486 HB_Bool is_extension
= FALSE
;
489 base_offset
= FILE_Pos();
491 if ( ACCESS_Frame( 6L ) )
494 l
->LookupType
= GET_UShort();
495 l
->LookupFlag
= GET_UShort();
496 count
= l
->SubTableCount
= GET_UShort();
502 if ( ALLOC_ARRAY( l
->SubTable
, count
, HB_SubTable
) )
507 if ( ( type
== HB_Type_GSUB
&& l
->LookupType
== HB_GSUB_LOOKUP_EXTENSION
) ||
508 ( type
== HB_Type_GPOS
&& l
->LookupType
== HB_GPOS_LOOKUP_EXTENSION
) )
511 for ( n
= 0; n
< count
; n
++ )
513 if ( ACCESS_Frame( 2L ) )
516 new_offset
= GET_UShort() + base_offset
;
520 cur_offset
= FILE_Pos();
524 if ( FILE_Seek( new_offset
) || ACCESS_Frame( 8L ) )
527 if (GET_UShort() != 1) /* format should be 1 */
530 l
->LookupType
= GET_UShort();
531 new_offset
+= GET_ULong();
536 if ( FILE_Seek( new_offset
) ||
537 ( error
= Load_SubTable( &st
[n
], stream
,
538 type
, l
->LookupType
) ) != HB_Err_Ok
)
540 (void)FILE_Seek( cur_offset
);
546 for ( m
= 0; m
< n
; m
++ )
547 Free_SubTable( &st
[m
], type
, l
->LookupType
);
554 static void Free_Lookup( HB_Lookup
* l
,
564 count
= l
->SubTableCount
;
567 for ( n
= 0; n
< count
; n
++ )
568 Free_SubTable( &st
[n
], type
, l
->LookupType
);
578 _HB_OPEN_Load_LookupList( HB_LookupList
* ll
,
584 HB_UShort n
, m
, count
;
585 HB_UInt cur_offset
, new_offset
, base_offset
;
590 base_offset
= FILE_Pos();
592 if ( ACCESS_Frame( 2L ) )
595 count
= ll
->LookupCount
= GET_UShort();
601 if ( ALLOC_ARRAY( ll
->Lookup
, count
, HB_Lookup
) )
603 if ( ALLOC_ARRAY( ll
->Properties
, count
, HB_UInt
) )
608 for ( n
= 0; n
< count
; n
++ )
610 if ( ACCESS_Frame( 2L ) )
613 new_offset
= GET_UShort() + base_offset
;
617 cur_offset
= FILE_Pos();
618 if ( FILE_Seek( new_offset
) ||
619 ( error
= Load_Lookup( &l
[n
], stream
, type
) ) != HB_Err_Ok
)
621 (void)FILE_Seek( cur_offset
);
627 FREE( ll
->Properties
);
629 for ( m
= 0; m
< n
; m
++ )
630 Free_Lookup( &l
[m
], type
);
639 _HB_OPEN_Free_LookupList( HB_LookupList
* ll
,
647 FREE( ll
->Properties
);
651 count
= ll
->LookupCount
;
654 for ( n
= 0; n
< count
; n
++ )
655 Free_Lookup( &l
[n
], type
);
663 /*****************************
664 * Coverage related functions
665 *****************************/
668 /* CoverageFormat1 */
670 static HB_Error
Load_Coverage1( HB_CoverageFormat1
* cf1
,
680 if ( ACCESS_Frame( 2L ) )
683 count
= cf1
->GlyphCount
= GET_UShort();
687 cf1
->GlyphArray
= NULL
;
689 if ( ALLOC_ARRAY( cf1
->GlyphArray
, count
, HB_UShort
) )
692 ga
= cf1
->GlyphArray
;
694 if ( ACCESS_Frame( count
* 2L ) )
696 FREE( cf1
->GlyphArray
);
700 for ( n
= 0; n
< count
; n
++ )
701 ga
[n
] = GET_UShort();
709 static void Free_Coverage1( HB_CoverageFormat1
* cf1
)
711 FREE( cf1
->GlyphArray
);
715 /* CoverageFormat2 */
717 static HB_Error
Load_Coverage2( HB_CoverageFormat2
* cf2
,
727 if ( ACCESS_Frame( 2L ) )
730 count
= cf2
->RangeCount
= GET_UShort();
734 cf2
->RangeRecord
= NULL
;
736 if ( ALLOC_ARRAY( cf2
->RangeRecord
, count
, HB_RangeRecord
) )
739 rr
= cf2
->RangeRecord
;
741 if ( ACCESS_Frame( count
* 6L ) )
744 for ( n
= 0; n
< count
; n
++ )
746 rr
[n
].Start
= GET_UShort();
747 rr
[n
].End
= GET_UShort();
748 rr
[n
].StartCoverageIndex
= GET_UShort();
750 /* sanity check; we are limited to 16bit integers */
751 if ( rr
[n
].Start
> rr
[n
].End
||
752 ( rr
[n
].End
- rr
[n
].Start
+ (long)rr
[n
].StartCoverageIndex
) >=
755 error
= ERR(HB_Err_Invalid_SubTable
);
765 FREE( cf2
->RangeRecord
);
770 static void Free_Coverage2( HB_CoverageFormat2
* cf2
)
772 FREE( cf2
->RangeRecord
);
777 _HB_OPEN_Load_Coverage( HB_Coverage
* c
,
782 if ( ACCESS_Frame( 2L ) )
785 c
->CoverageFormat
= GET_UShort();
789 switch ( c
->CoverageFormat
)
791 case 1: return Load_Coverage1( &c
->cf
.cf1
, stream
);
792 case 2: return Load_Coverage2( &c
->cf
.cf2
, stream
);
793 default: return ERR(HB_Err_Invalid_SubTable_Format
);
796 return HB_Err_Ok
; /* never reached */
801 _HB_OPEN_Free_Coverage( HB_Coverage
* c
)
803 switch ( c
->CoverageFormat
)
805 case 1: Free_Coverage1( &c
->cf
.cf1
); break;
806 case 2: Free_Coverage2( &c
->cf
.cf2
); break;
812 static HB_Error
Coverage_Index1( HB_CoverageFormat1
* cf1
,
816 HB_UShort min
, max
, new_min
, new_max
, middle
;
818 HB_UShort
* array
= cf1
->GlyphArray
;
823 if ( cf1
->GlyphCount
== 0 )
824 return HB_Err_Not_Covered
;
827 new_max
= cf1
->GlyphCount
- 1;
834 /* we use (min + max) / 2 = max - (max - min) / 2 to avoid
835 overflow and rounding errors */
837 middle
= max
- ( ( max
- min
) >> 1 );
839 if ( glyphID
== array
[middle
] )
844 else if ( glyphID
< array
[middle
] )
848 new_max
= middle
- 1;
854 new_min
= middle
+ 1;
856 } while ( min
< max
);
858 return HB_Err_Not_Covered
;
862 static HB_Error
Coverage_Index2( HB_CoverageFormat2
* cf2
,
866 HB_UShort min
, max
, new_min
, new_max
, middle
;
868 HB_RangeRecord
* rr
= cf2
->RangeRecord
;
873 if ( cf2
->RangeCount
== 0 )
874 return HB_Err_Not_Covered
;
877 new_max
= cf2
->RangeCount
- 1;
884 /* we use (min + max) / 2 = max - (max - min) / 2 to avoid
885 overflow and rounding errors */
887 middle
= max
- ( ( max
- min
) >> 1 );
889 if ( glyphID
>= rr
[middle
].Start
&& glyphID
<= rr
[middle
].End
)
891 *index
= rr
[middle
].StartCoverageIndex
+ glyphID
- rr
[middle
].Start
;
894 else if ( glyphID
< rr
[middle
].Start
)
898 new_max
= middle
- 1;
904 new_min
= middle
+ 1;
906 } while ( min
< max
);
908 return HB_Err_Not_Covered
;
913 _HB_OPEN_Coverage_Index( HB_Coverage
* c
,
917 switch ( c
->CoverageFormat
)
919 case 1: return Coverage_Index1( &c
->cf
.cf1
, glyphID
, index
);
920 case 2: return Coverage_Index2( &c
->cf
.cf2
, glyphID
, index
);
921 default: return ERR(HB_Err_Invalid_SubTable_Format
);
924 return HB_Err_Ok
; /* never reached */
929 /*************************************
930 * Class Definition related functions
931 *************************************/
934 /* ClassDefFormat1 */
936 static HB_Error
Load_ClassDef1( HB_ClassDefinition
* cd
,
946 HB_ClassDefFormat1
* cdf1
;
951 if ( ACCESS_Frame( 4L ) )
954 cdf1
->StartGlyph
= GET_UShort();
955 count
= cdf1
->GlyphCount
= GET_UShort();
959 /* sanity check; we are limited to 16bit integers */
961 if ( cdf1
->StartGlyph
+ (long)count
>= 0x10000L
)
962 return ERR(HB_Err_Invalid_SubTable
);
964 cdf1
->ClassValueArray
= NULL
;
966 if ( ALLOC_ARRAY( cdf1
->ClassValueArray
, count
, HB_UShort
) )
969 cva
= cdf1
->ClassValueArray
;
971 if ( ACCESS_Frame( count
* 2L ) )
974 for ( n
= 0; n
< count
; n
++ )
976 cva
[n
] = GET_UShort();
977 if ( cva
[n
] >= limit
)
979 error
= ERR(HB_Err_Invalid_SubTable
);
995 static void Free_ClassDef1( HB_ClassDefFormat1
* cdf1
)
997 FREE( cdf1
->ClassValueArray
);
1001 /* ClassDefFormat2 */
1003 static HB_Error
Load_ClassDef2( HB_ClassDefinition
* cd
,
1011 HB_ClassRangeRecord
* crr
;
1013 HB_ClassDefFormat2
* cdf2
;
1018 if ( ACCESS_Frame( 2L ) )
1021 count
= GET_UShort();
1022 cdf2
->ClassRangeCount
= 0; /* zero for now. we fill with the number of good entries later */
1026 cdf2
->ClassRangeRecord
= NULL
;
1028 if ( ALLOC_ARRAY( cdf2
->ClassRangeRecord
, count
, HB_ClassRangeRecord
) )
1031 crr
= cdf2
->ClassRangeRecord
;
1033 if ( ACCESS_Frame( count
* 6L ) )
1036 for ( n
= 0; n
< count
; n
++ )
1038 crr
[n
].Start
= GET_UShort();
1039 crr
[n
].End
= GET_UShort();
1040 crr
[n
].Class
= GET_UShort();
1044 if ( crr
[n
].Start
> crr
[n
].End
||
1045 crr
[n
].Class
>= limit
)
1048 * Corrupt entry. Skip it.
1049 * This is hit by Nafees Nastaliq font for example
1058 cdf2
->ClassRangeCount
= count
;
1069 static void Free_ClassDef2( HB_ClassDefFormat2
* cdf2
)
1071 FREE( cdf2
->ClassRangeRecord
);
1075 /* ClassDefinition */
1077 HB_INTERNAL HB_Error
1078 _HB_OPEN_Load_ClassDefinition( HB_ClassDefinition
* cd
,
1084 if ( ACCESS_Frame( 2L ) )
1087 cd
->ClassFormat
= GET_UShort();
1091 switch ( cd
->ClassFormat
)
1093 case 1: error
= Load_ClassDef1( cd
, limit
, stream
); break;
1094 case 2: error
= Load_ClassDef2( cd
, limit
, stream
); break;
1095 default: error
= ERR(HB_Err_Invalid_SubTable_Format
); break;
1108 _HB_OPEN_Load_EmptyClassDefinition( HB_ClassDefinition
* cd
)
1112 cd
->ClassFormat
= 1; /* Meaningless */
1114 if ( ALLOC_ARRAY( cd
->cd
.cd1
.ClassValueArray
, 1, HB_UShort
) )
1122 HB_INTERNAL HB_Error
1123 _HB_OPEN_Load_EmptyOrClassDefinition( HB_ClassDefinition
* cd
,
1125 HB_UInt class_offset
,
1126 HB_UInt base_offset
,
1132 cur_offset
= FILE_Pos();
1136 if ( !FILE_Seek( class_offset
+ base_offset
) )
1137 error
= _HB_OPEN_Load_ClassDefinition( cd
, limit
, stream
);
1140 error
= _HB_OPEN_Load_EmptyClassDefinition ( cd
);
1142 if (error
== HB_Err_Ok
)
1143 (void)FILE_Seek( cur_offset
); /* Changes error as a side-effect */
1149 _HB_OPEN_Free_ClassDefinition( HB_ClassDefinition
* cd
)
1154 switch ( cd
->ClassFormat
)
1156 case 1: Free_ClassDef1( &cd
->cd
.cd1
); break;
1157 case 2: Free_ClassDef2( &cd
->cd
.cd2
); break;
1163 static HB_Error
Get_Class1( HB_ClassDefFormat1
* cdf1
,
1168 HB_UShort
* cva
= cdf1
->ClassValueArray
;
1174 if ( glyphID
>= cdf1
->StartGlyph
&&
1175 glyphID
< cdf1
->StartGlyph
+ cdf1
->GlyphCount
)
1177 *klass
= cva
[glyphID
- cdf1
->StartGlyph
];
1183 return HB_Err_Not_Covered
;
1188 /* we need the index value of the last searched class range record
1189 in case of failure for constructed GDEF tables */
1191 static HB_Error
Get_Class2( HB_ClassDefFormat2
* cdf2
,
1196 HB_Error error
= HB_Err_Ok
;
1197 HB_UShort min
, max
, new_min
, new_max
, middle
;
1199 HB_ClassRangeRecord
* crr
= cdf2
->ClassRangeRecord
;
1204 if ( cdf2
->ClassRangeCount
== 0 )
1210 return HB_Err_Not_Covered
;
1214 new_max
= cdf2
->ClassRangeCount
- 1;
1221 /* we use (min + max) / 2 = max - (max - min) / 2 to avoid
1222 overflow and rounding errors */
1224 middle
= max
- ( ( max
- min
) >> 1 );
1226 if ( glyphID
>= crr
[middle
].Start
&& glyphID
<= crr
[middle
].End
)
1228 *klass
= crr
[middle
].Class
;
1232 else if ( glyphID
< crr
[middle
].Start
)
1234 if ( middle
== min
)
1237 error
= HB_Err_Not_Covered
;
1240 new_max
= middle
- 1;
1244 if ( middle
== max
)
1247 error
= HB_Err_Not_Covered
;
1250 new_min
= middle
+ 1;
1252 } while ( min
< max
);
1261 HB_INTERNAL HB_Error
1262 _HB_OPEN_Get_Class( HB_ClassDefinition
* cd
,
1267 switch ( cd
->ClassFormat
)
1269 case 1: return Get_Class1( &cd
->cd
.cd1
, glyphID
, klass
, index
);
1270 case 2: return Get_Class2( &cd
->cd
.cd2
, glyphID
, klass
, index
);
1271 default: return ERR(HB_Err_Invalid_SubTable_Format
);
1274 return HB_Err_Ok
; /* never reached */
1279 /***************************
1280 * Device related functions
1281 ***************************/
1284 HB_INTERNAL HB_Error
1285 _HB_OPEN_Load_Device( HB_Device
** device
,
1296 if ( ACCESS_Frame( 6L ) )
1299 if ( ALLOC( *device
, sizeof(HB_Device
)) )
1307 d
->StartSize
= GET_UShort();
1308 d
->EndSize
= GET_UShort();
1309 d
->DeltaFormat
= GET_UShort();
1313 d
->DeltaValue
= NULL
;
1315 if ( d
->StartSize
> d
->EndSize
||
1316 d
->DeltaFormat
== 0 || d
->DeltaFormat
> 3 )
1319 * I've seen fontforge generate DeltaFormat == 0.
1320 * Just return Ok and let the NULL DeltaValue disable
1326 count
= ( ( d
->EndSize
- d
->StartSize
+ 1 ) >>
1327 ( 4 - d
->DeltaFormat
) ) + 1;
1329 if ( ALLOC_ARRAY( d
->DeltaValue
, count
, HB_UShort
) )
1336 if ( ACCESS_Frame( count
* 2L ) )
1338 FREE( d
->DeltaValue
);
1346 for ( n
= 0; n
< count
; n
++ )
1347 dv
[n
] = GET_UShort();
1356 _HB_OPEN_Free_Device( HB_Device
* d
)
1360 FREE( d
->DeltaValue
);
1366 /* Since we have the delta values stored in compressed form, we must
1367 uncompress it now. To simplify the interface, the function always
1368 returns a meaningful value in `value'; the error is just for
1371 format = 1: 0011223344556677|8899101112131415|...
1375 00: (byte >> 14) & mask
1376 11: (byte >> 12) & mask
1381 format = 2: 0000111122223333|4444555566667777|...
1385 0000: (byte >> 12) & mask
1386 1111: (byte >> 8) & mask
1391 format = 3: 0000000011111111|2222222233333333|...
1395 00000000: (byte >> 8) & mask
1396 11111111: (byte >> 0) & mask
1401 HB_INTERNAL HB_Error
1402 _HB_OPEN_Get_Device( HB_Device
* d
,
1406 HB_UShort byte
, bits
, mask
, s
;
1408 if ( d
&& d
->DeltaValue
&& size
>= d
->StartSize
&& size
<= d
->EndSize
)
1410 HB_UShort f
= d
->DeltaFormat
;
1411 s
= size
- d
->StartSize
;
1412 byte
= d
->DeltaValue
[s
>> ( 4 - f
)];
1413 bits
= byte
>> ( 16 - ( ( s
% ( 1 << ( 4 - f
) ) + 1 ) << f
) );
1414 mask
= 0xFFFF >> ( 16 - ( 1 << f
) );
1416 *value
= (HB_Short
)( bits
& mask
);
1418 /* conversion to a signed value */
1420 if ( *value
>= ( ( mask
+ 1 ) >> 1 ) )
1428 return HB_Err_Not_Covered
;