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(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(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(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(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(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(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(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(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* d,
1295 if ( ACCESS_Frame( 6L ) )
1298 d->StartSize = GET_UShort();
1299 d->EndSize = GET_UShort();
1300 d->DeltaFormat = GET_UShort();
1304 d->DeltaValue = NULL;
1306 if ( d->StartSize > d->EndSize ||
1307 d->DeltaFormat == 0 || d->DeltaFormat > 3 )
1310 * I've seen fontforge generate DeltaFormat == 0.
1311 * Just return Ok and let the NULL DeltaValue disable
1317 count = ( ( d->EndSize - d->StartSize + 1 ) >>
1318 ( 4 - d->DeltaFormat ) ) + 1;
1320 if ( ALLOC_ARRAY( d->DeltaValue, count, HB_UShort ) )
1323 if ( ACCESS_Frame( count * 2L ) )
1325 FREE( d->DeltaValue );
1331 for ( n = 0; n < count; n++ )
1332 dv[n] = GET_UShort();
1341 _HB_OPEN_Free_Device( HB_Device* d )
1343 FREE( d->DeltaValue );
1347 /* Since we have the delta values stored in compressed form, we must
1348 uncompress it now. To simplify the interface, the function always
1349 returns a meaningful value in `value'; the error is just for
1352 format = 1: 0011223344556677|8899101112131415|...
1356 00: (byte >> 14) & mask
1357 11: (byte >> 12) & mask
1362 format = 2: 0000111122223333|4444555566667777|...
1366 0000: (byte >> 12) & mask
1367 1111: (byte >> 8) & mask
1372 format = 3: 0000000011111111|2222222233333333|...
1376 00000000: (byte >> 8) & mask
1377 11111111: (byte >> 0) & mask
1382 HB_INTERNAL HB_Error
1383 _HB_OPEN_Get_Device( HB_Device* d,
1387 HB_UShort byte, bits, mask, f, s;
1392 if ( d->DeltaValue && size >= d->StartSize && size <= d->EndSize )
1394 s = size - d->StartSize;
1395 byte = d->DeltaValue[s >> ( 4 - f )];
1396 bits = byte >> ( 16 - ( ( s % ( 1 << ( 4 - f ) ) + 1 ) << f ) );
1397 mask = 0xFFFF >> ( 16 - ( 1 << f ) );
1399 *value = (HB_Short)( bits & mask );
1401 /* conversion to a signed value */
1403 if ( *value >= ( ( mask + 1 ) >> 1 ) )
1411 return HB_Err_Not_Covered;