Index: third_party/harfbuzz/src/harfbuzz-open.c |
diff --git a/third_party/harfbuzz/src/harfbuzz-open.c b/third_party/harfbuzz/src/harfbuzz-open.c |
deleted file mode 100644 |
index 0fe1e4ddb301a112195b946489f68835238c89bf..0000000000000000000000000000000000000000 |
--- a/third_party/harfbuzz/src/harfbuzz-open.c |
+++ /dev/null |
@@ -1,1416 +0,0 @@ |
-/* |
- * Copyright (C) 1998-2004 David Turner and Werner Lemberg |
- * Copyright (C) 2006 Behdad Esfahbod |
- * |
- * This is part of HarfBuzz, an OpenType Layout engine library. |
- * |
- * Permission is hereby granted, without written agreement and without |
- * license or royalty fees, to use, copy, modify, and distribute this |
- * software and its documentation for any purpose, provided that the |
- * above copyright notice and the following two paragraphs appear in |
- * all copies of this software. |
- * |
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
- * DAMAGE. |
- * |
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
- */ |
- |
-#include "harfbuzz-impl.h" |
-#include "harfbuzz-open-private.h" |
- |
- |
-/*************************** |
- * Script related functions |
- ***************************/ |
- |
- |
-/* LangSys */ |
- |
-static HB_Error Load_LangSys( HB_LangSys* ls, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- HB_UShort n, count; |
- HB_UShort* fi; |
- |
- |
- if ( ACCESS_Frame( 6L ) ) |
- return error; |
- |
- ls->LookupOrderOffset = GET_UShort(); /* should be 0 */ |
- ls->ReqFeatureIndex = GET_UShort(); |
- count = ls->FeatureCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- ls->FeatureIndex = NULL; |
- |
- if ( ALLOC_ARRAY( ls->FeatureIndex, count, HB_UShort ) ) |
- return error; |
- |
- if ( ACCESS_Frame( count * 2L ) ) |
- { |
- FREE( ls->FeatureIndex ); |
- return error; |
- } |
- |
- fi = ls->FeatureIndex; |
- |
- for ( n = 0; n < count; n++ ) |
- fi[n] = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- return HB_Err_Ok; |
-} |
- |
- |
-static void Free_LangSys( HB_LangSys* ls ) |
-{ |
- FREE( ls->FeatureIndex ); |
-} |
- |
- |
-/* Script */ |
- |
-static HB_Error Load_Script( HB_ScriptTable* s, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- HB_UShort n, m, count; |
- HB_UInt cur_offset, new_offset, base_offset; |
- |
- HB_LangSysRecord* lsr; |
- |
- |
- base_offset = FILE_Pos(); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- if ( new_offset != base_offset ) /* not a NULL offset */ |
- { |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = Load_LangSys( &s->DefaultLangSys, |
- stream ) ) != HB_Err_Ok ) |
- return error; |
- (void)FILE_Seek( cur_offset ); |
- } |
- else |
- { |
- /* we create a DefaultLangSys table with no entries */ |
- |
- s->DefaultLangSys.LookupOrderOffset = 0; |
- s->DefaultLangSys.ReqFeatureIndex = 0xFFFF; |
- s->DefaultLangSys.FeatureCount = 0; |
- s->DefaultLangSys.FeatureIndex = NULL; |
- } |
- |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail2; |
- |
- count = s->LangSysCount = GET_UShort(); |
- |
- /* safety check; otherwise the official handling of TrueType Open |
- fonts won't work */ |
- |
- if ( s->LangSysCount == 0 && s->DefaultLangSys.FeatureCount == 0 ) |
- { |
- error = HB_Err_Not_Covered; |
- goto Fail2; |
- } |
- |
- FORGET_Frame(); |
- |
- s->LangSysRecord = NULL; |
- |
- if ( ALLOC_ARRAY( s->LangSysRecord, count, HB_LangSysRecord ) ) |
- goto Fail2; |
- |
- lsr = s->LangSysRecord; |
- |
- for ( n = 0; n < count; n++ ) |
- { |
- if ( ACCESS_Frame( 6L ) ) |
- goto Fail1; |
- |
- lsr[n].LangSysTag = GET_ULong(); |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = Load_LangSys( &lsr[n].LangSys, stream ) ) != HB_Err_Ok ) |
- goto Fail1; |
- (void)FILE_Seek( cur_offset ); |
- } |
- |
- return HB_Err_Ok; |
- |
-Fail1: |
- for ( m = 0; m < n; m++ ) |
- Free_LangSys( &lsr[m].LangSys ); |
- |
- FREE( s->LangSysRecord ); |
- |
-Fail2: |
- Free_LangSys( &s->DefaultLangSys ); |
- return error; |
-} |
- |
- |
-static void Free_Script( HB_ScriptTable* s ) |
-{ |
- HB_UShort n, count; |
- |
- HB_LangSysRecord* lsr; |
- |
- |
- Free_LangSys( &s->DefaultLangSys ); |
- |
- if ( s->LangSysRecord ) |
- { |
- count = s->LangSysCount; |
- lsr = s->LangSysRecord; |
- |
- for ( n = 0; n < count; n++ ) |
- Free_LangSys( &lsr[n].LangSys ); |
- |
- FREE( lsr ); |
- } |
-} |
- |
- |
-/* ScriptList */ |
- |
-HB_INTERNAL HB_Error |
-_HB_OPEN_Load_ScriptList( HB_ScriptList* sl, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n, script_count; |
- HB_UInt cur_offset, new_offset, base_offset; |
- |
- HB_ScriptRecord* sr; |
- |
- |
- base_offset = FILE_Pos(); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- script_count = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- sl->ScriptRecord = NULL; |
- |
- if ( ALLOC_ARRAY( sl->ScriptRecord, script_count, HB_ScriptRecord ) ) |
- return error; |
- |
- sr = sl->ScriptRecord; |
- |
- sl->ScriptCount= 0; |
- for ( n = 0; n < script_count; n++ ) |
- { |
- if ( ACCESS_Frame( 6L ) ) |
- goto Fail; |
- |
- sr[sl->ScriptCount].ScriptTag = GET_ULong(); |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- |
- if ( FILE_Seek( new_offset ) ) |
- goto Fail; |
- |
- error = Load_Script( &sr[sl->ScriptCount].Script, stream ); |
- if ( error == HB_Err_Ok ) |
- sl->ScriptCount += 1; |
- else if ( error != HB_Err_Not_Covered ) |
- goto Fail; |
- |
- (void)FILE_Seek( cur_offset ); |
- } |
- |
- /* Empty tables are harmless and generated by fontforge. |
- * See http://bugzilla.gnome.org/show_bug.cgi?id=347073 |
- */ |
-#if 0 |
- if ( sl->ScriptCount == 0 ) |
- { |
- error = ERR(HB_Err_Invalid_SubTable); |
- goto Fail; |
- } |
-#endif |
- |
- return HB_Err_Ok; |
- |
-Fail: |
- for ( n = 0; n < sl->ScriptCount; n++ ) |
- Free_Script( &sr[n].Script ); |
- |
- FREE( sl->ScriptRecord ); |
- return error; |
-} |
- |
- |
-HB_INTERNAL void |
-_HB_OPEN_Free_ScriptList( HB_ScriptList* sl ) |
-{ |
- HB_UShort n, count; |
- |
- HB_ScriptRecord* sr; |
- |
- |
- if ( sl->ScriptRecord ) |
- { |
- count = sl->ScriptCount; |
- sr = sl->ScriptRecord; |
- |
- for ( n = 0; n < count; n++ ) |
- Free_Script( &sr[n].Script ); |
- |
- FREE( sr ); |
- } |
-} |
- |
- |
- |
-/********************************* |
- * Feature List related functions |
- *********************************/ |
- |
- |
-/* Feature */ |
- |
-static HB_Error Load_Feature( HB_Feature* f, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n, count; |
- |
- HB_UShort* lli; |
- |
- |
- if ( ACCESS_Frame( 4L ) ) |
- return error; |
- |
- f->FeatureParams = GET_UShort(); /* should be 0 */ |
- count = f->LookupListCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- f->LookupListIndex = NULL; |
- |
- if ( ALLOC_ARRAY( f->LookupListIndex, count, HB_UShort ) ) |
- return error; |
- |
- lli = f->LookupListIndex; |
- |
- if ( ACCESS_Frame( count * 2L ) ) |
- { |
- FREE( f->LookupListIndex ); |
- return error; |
- } |
- |
- for ( n = 0; n < count; n++ ) |
- lli[n] = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- return HB_Err_Ok; |
-} |
- |
- |
-static void Free_Feature( HB_Feature* f ) |
-{ |
- FREE( f->LookupListIndex ); |
-} |
- |
- |
-/* FeatureList */ |
- |
-HB_INTERNAL HB_Error |
-_HB_OPEN_Load_FeatureList( HB_FeatureList* fl, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n, m, count; |
- HB_UInt cur_offset, new_offset, base_offset; |
- |
- HB_FeatureRecord* fr; |
- |
- |
- base_offset = FILE_Pos(); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- count = fl->FeatureCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- fl->FeatureRecord = NULL; |
- |
- if ( ALLOC_ARRAY( fl->FeatureRecord, count, HB_FeatureRecord ) ) |
- return error; |
- if ( ALLOC_ARRAY( fl->ApplyOrder, count, HB_UShort ) ) |
- goto Fail2; |
- |
- fl->ApplyCount = 0; |
- |
- fr = fl->FeatureRecord; |
- |
- for ( n = 0; n < count; n++ ) |
- { |
- if ( ACCESS_Frame( 6L ) ) |
- goto Fail1; |
- |
- fr[n].FeatureTag = GET_ULong(); |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = Load_Feature( &fr[n].Feature, stream ) ) != HB_Err_Ok ) |
- goto Fail1; |
- (void)FILE_Seek( cur_offset ); |
- } |
- |
- return HB_Err_Ok; |
- |
-Fail1: |
- for ( m = 0; m < n; m++ ) |
- Free_Feature( &fr[m].Feature ); |
- |
- FREE( fl->ApplyOrder ); |
- |
-Fail2: |
- FREE( fl->FeatureRecord ); |
- |
- return error; |
-} |
- |
- |
-HB_INTERNAL void |
-_HB_OPEN_Free_FeatureList( HB_FeatureList* fl ) |
-{ |
- HB_UShort n, count; |
- |
- HB_FeatureRecord* fr; |
- |
- |
- if ( fl->FeatureRecord ) |
- { |
- count = fl->FeatureCount; |
- fr = fl->FeatureRecord; |
- |
- for ( n = 0; n < count; n++ ) |
- Free_Feature( &fr[n].Feature ); |
- |
- FREE( fr ); |
- } |
- |
- FREE( fl->ApplyOrder ); |
-} |
- |
- |
- |
-/******************************** |
- * Lookup List related functions |
- ********************************/ |
- |
-/* the subroutines of the following two functions are defined in |
- ftxgsub.c and ftxgpos.c respectively */ |
- |
- |
-/* SubTable */ |
- |
-static HB_Error Load_SubTable( HB_SubTable* st, |
- HB_Stream stream, |
- HB_Type table_type, |
- HB_UShort lookup_type ) |
-{ |
- if ( table_type == HB_Type_GSUB ) |
- return _HB_GSUB_Load_SubTable ( &st->st.gsub, stream, lookup_type ); |
- else |
- return _HB_GPOS_Load_SubTable ( &st->st.gpos, stream, lookup_type ); |
-} |
- |
- |
-static void Free_SubTable( HB_SubTable* st, |
- HB_Type table_type, |
- HB_UShort lookup_type ) |
-{ |
- if ( table_type == HB_Type_GSUB ) |
- _HB_GSUB_Free_SubTable ( &st->st.gsub, lookup_type ); |
- else |
- _HB_GPOS_Free_SubTable ( &st->st.gpos, lookup_type ); |
-} |
- |
- |
-/* Lookup */ |
- |
-static HB_Error Load_Lookup( HB_Lookup* l, |
- HB_Stream stream, |
- HB_Type type ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n, m, count; |
- HB_UInt cur_offset, new_offset, base_offset; |
- |
- HB_SubTable* st; |
- |
- HB_Bool is_extension = FALSE; |
- |
- |
- base_offset = FILE_Pos(); |
- |
- if ( ACCESS_Frame( 6L ) ) |
- return error; |
- |
- l->LookupType = GET_UShort(); |
- l->LookupFlag = GET_UShort(); |
- count = l->SubTableCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- l->SubTable = NULL; |
- |
- if ( ALLOC_ARRAY( l->SubTable, count, HB_SubTable ) ) |
- return error; |
- |
- st = l->SubTable; |
- |
- if ( ( type == HB_Type_GSUB && l->LookupType == HB_GSUB_LOOKUP_EXTENSION ) || |
- ( type == HB_Type_GPOS && l->LookupType == HB_GPOS_LOOKUP_EXTENSION ) ) |
- is_extension = TRUE; |
- |
- for ( n = 0; n < count; n++ ) |
- { |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail; |
- |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- |
- if ( is_extension ) |
- { |
- if ( FILE_Seek( new_offset ) || ACCESS_Frame( 8L ) ) |
- goto Fail; |
- |
- if (GET_UShort() != 1) /* format should be 1 */ |
- goto Fail; |
- |
- l->LookupType = GET_UShort(); |
- new_offset += GET_ULong(); |
- |
- FORGET_Frame(); |
- } |
- |
- if ( FILE_Seek( new_offset ) || |
- ( error = Load_SubTable( &st[n], stream, |
- type, l->LookupType ) ) != HB_Err_Ok ) |
- goto Fail; |
- (void)FILE_Seek( cur_offset ); |
- } |
- |
- return HB_Err_Ok; |
- |
-Fail: |
- for ( m = 0; m < n; m++ ) |
- Free_SubTable( &st[m], type, l->LookupType ); |
- |
- FREE( l->SubTable ); |
- return error; |
-} |
- |
- |
-static void Free_Lookup( HB_Lookup* l, |
- HB_Type type) |
-{ |
- HB_UShort n, count; |
- |
- HB_SubTable* st; |
- |
- |
- if ( l->SubTable ) |
- { |
- count = l->SubTableCount; |
- st = l->SubTable; |
- |
- for ( n = 0; n < count; n++ ) |
- Free_SubTable( &st[n], type, l->LookupType ); |
- |
- FREE( st ); |
- } |
-} |
- |
- |
-/* LookupList */ |
- |
-HB_INTERNAL HB_Error |
-_HB_OPEN_Load_LookupList( HB_LookupList* ll, |
- HB_Stream stream, |
- HB_Type type ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n, m, count; |
- HB_UInt cur_offset, new_offset, base_offset; |
- |
- HB_Lookup* l; |
- |
- |
- base_offset = FILE_Pos(); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- count = ll->LookupCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- ll->Lookup = NULL; |
- |
- if ( ALLOC_ARRAY( ll->Lookup, count, HB_Lookup ) ) |
- return error; |
- if ( ALLOC_ARRAY( ll->Properties, count, HB_UInt ) ) |
- goto Fail2; |
- |
- l = ll->Lookup; |
- |
- for ( n = 0; n < count; n++ ) |
- { |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail1; |
- |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = Load_Lookup( &l[n], stream, type ) ) != HB_Err_Ok ) |
- goto Fail1; |
- (void)FILE_Seek( cur_offset ); |
- } |
- |
- return HB_Err_Ok; |
- |
-Fail1: |
- FREE( ll->Properties ); |
- |
- for ( m = 0; m < n; m++ ) |
- Free_Lookup( &l[m], type ); |
- |
-Fail2: |
- FREE( ll->Lookup ); |
- return error; |
-} |
- |
- |
-HB_INTERNAL void |
-_HB_OPEN_Free_LookupList( HB_LookupList* ll, |
- HB_Type type ) |
-{ |
- HB_UShort n, count; |
- |
- HB_Lookup* l; |
- |
- |
- FREE( ll->Properties ); |
- |
- if ( ll->Lookup ) |
- { |
- count = ll->LookupCount; |
- l = ll->Lookup; |
- |
- for ( n = 0; n < count; n++ ) |
- Free_Lookup( &l[n], type ); |
- |
- FREE( l ); |
- } |
-} |
- |
- |
- |
-/***************************** |
- * Coverage related functions |
- *****************************/ |
- |
- |
-/* CoverageFormat1 */ |
- |
-static HB_Error Load_Coverage1( HB_CoverageFormat1* cf1, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n, count; |
- |
- HB_UShort* ga; |
- |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- count = cf1->GlyphCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- cf1->GlyphArray = NULL; |
- |
- if ( ALLOC_ARRAY( cf1->GlyphArray, count, HB_UShort ) ) |
- return error; |
- |
- ga = cf1->GlyphArray; |
- |
- if ( ACCESS_Frame( count * 2L ) ) |
- { |
- FREE( cf1->GlyphArray ); |
- return error; |
- } |
- |
- for ( n = 0; n < count; n++ ) |
- ga[n] = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- return HB_Err_Ok; |
-} |
- |
- |
-static void Free_Coverage1( HB_CoverageFormat1* cf1) |
-{ |
- FREE( cf1->GlyphArray ); |
-} |
- |
- |
-/* CoverageFormat2 */ |
- |
-static HB_Error Load_Coverage2( HB_CoverageFormat2* cf2, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n, count; |
- |
- HB_RangeRecord* rr; |
- |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- count = cf2->RangeCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- cf2->RangeRecord = NULL; |
- |
- if ( ALLOC_ARRAY( cf2->RangeRecord, count, HB_RangeRecord ) ) |
- return error; |
- |
- rr = cf2->RangeRecord; |
- |
- if ( ACCESS_Frame( count * 6L ) ) |
- goto Fail; |
- |
- for ( n = 0; n < count; n++ ) |
- { |
- rr[n].Start = GET_UShort(); |
- rr[n].End = GET_UShort(); |
- rr[n].StartCoverageIndex = GET_UShort(); |
- |
- /* sanity check; we are limited to 16bit integers */ |
- if ( rr[n].Start > rr[n].End || |
- ( rr[n].End - rr[n].Start + (long)rr[n].StartCoverageIndex ) >= |
- 0x10000L ) |
- { |
- error = ERR(HB_Err_Invalid_SubTable); |
- goto Fail; |
- } |
- } |
- |
- FORGET_Frame(); |
- |
- return HB_Err_Ok; |
- |
-Fail: |
- FREE( cf2->RangeRecord ); |
- return error; |
-} |
- |
- |
-static void Free_Coverage2( HB_CoverageFormat2* cf2 ) |
-{ |
- FREE( cf2->RangeRecord ); |
-} |
- |
- |
-HB_INTERNAL HB_Error |
-_HB_OPEN_Load_Coverage( HB_Coverage* c, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- c->CoverageFormat = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- switch ( c->CoverageFormat ) |
- { |
- case 1: return Load_Coverage1( &c->cf.cf1, stream ); |
- case 2: return Load_Coverage2( &c->cf.cf2, stream ); |
- default: return ERR(HB_Err_Invalid_SubTable_Format); |
- } |
- |
- return HB_Err_Ok; /* never reached */ |
-} |
- |
- |
-HB_INTERNAL void |
-_HB_OPEN_Free_Coverage( HB_Coverage* c ) |
-{ |
- switch ( c->CoverageFormat ) |
- { |
- case 1: Free_Coverage1( &c->cf.cf1 ); break; |
- case 2: Free_Coverage2( &c->cf.cf2 ); break; |
- default: break; |
- } |
-} |
- |
- |
-static HB_Error Coverage_Index1( HB_CoverageFormat1* cf1, |
- HB_UShort glyphID, |
- HB_UShort* index ) |
-{ |
- HB_UShort min, max, new_min, new_max, middle; |
- |
- HB_UShort* array = cf1->GlyphArray; |
- |
- |
- /* binary search */ |
- |
- if ( cf1->GlyphCount == 0 ) |
- return HB_Err_Not_Covered; |
- |
- new_min = 0; |
- new_max = cf1->GlyphCount - 1; |
- |
- do |
- { |
- min = new_min; |
- max = new_max; |
- |
- /* we use (min + max) / 2 = max - (max - min) / 2 to avoid |
- overflow and rounding errors */ |
- |
- middle = max - ( ( max - min ) >> 1 ); |
- |
- if ( glyphID == array[middle] ) |
- { |
- *index = middle; |
- return HB_Err_Ok; |
- } |
- else if ( glyphID < array[middle] ) |
- { |
- if ( middle == min ) |
- break; |
- new_max = middle - 1; |
- } |
- else |
- { |
- if ( middle == max ) |
- break; |
- new_min = middle + 1; |
- } |
- } while ( min < max ); |
- |
- return HB_Err_Not_Covered; |
-} |
- |
- |
-static HB_Error Coverage_Index2( HB_CoverageFormat2* cf2, |
- HB_UShort glyphID, |
- HB_UShort* index ) |
-{ |
- HB_UShort min, max, new_min, new_max, middle; |
- |
- HB_RangeRecord* rr = cf2->RangeRecord; |
- |
- |
- /* binary search */ |
- |
- if ( cf2->RangeCount == 0 ) |
- return HB_Err_Not_Covered; |
- |
- new_min = 0; |
- new_max = cf2->RangeCount - 1; |
- |
- do |
- { |
- min = new_min; |
- max = new_max; |
- |
- /* we use (min + max) / 2 = max - (max - min) / 2 to avoid |
- overflow and rounding errors */ |
- |
- middle = max - ( ( max - min ) >> 1 ); |
- |
- if ( glyphID >= rr[middle].Start && glyphID <= rr[middle].End ) |
- { |
- *index = rr[middle].StartCoverageIndex + glyphID - rr[middle].Start; |
- return HB_Err_Ok; |
- } |
- else if ( glyphID < rr[middle].Start ) |
- { |
- if ( middle == min ) |
- break; |
- new_max = middle - 1; |
- } |
- else |
- { |
- if ( middle == max ) |
- break; |
- new_min = middle + 1; |
- } |
- } while ( min < max ); |
- |
- return HB_Err_Not_Covered; |
-} |
- |
- |
-HB_INTERNAL HB_Error |
-_HB_OPEN_Coverage_Index( HB_Coverage* c, |
- HB_UShort glyphID, |
- HB_UShort* index ) |
-{ |
- switch ( c->CoverageFormat ) |
- { |
- case 1: return Coverage_Index1( &c->cf.cf1, glyphID, index ); |
- case 2: return Coverage_Index2( &c->cf.cf2, glyphID, index ); |
- default: return ERR(HB_Err_Invalid_SubTable_Format); |
- } |
- |
- return HB_Err_Ok; /* never reached */ |
-} |
- |
- |
- |
-/************************************* |
- * Class Definition related functions |
- *************************************/ |
- |
- |
-/* ClassDefFormat1 */ |
- |
-static HB_Error Load_ClassDef1( HB_ClassDefinition* cd, |
- HB_UShort limit, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n, count; |
- |
- HB_UShort* cva; |
- |
- HB_ClassDefFormat1* cdf1; |
- |
- |
- cdf1 = &cd->cd.cd1; |
- |
- if ( ACCESS_Frame( 4L ) ) |
- return error; |
- |
- cdf1->StartGlyph = GET_UShort(); |
- count = cdf1->GlyphCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- /* sanity check; we are limited to 16bit integers */ |
- |
- if ( cdf1->StartGlyph + (long)count >= 0x10000L ) |
- return ERR(HB_Err_Invalid_SubTable); |
- |
- cdf1->ClassValueArray = NULL; |
- |
- if ( ALLOC_ARRAY( cdf1->ClassValueArray, count, HB_UShort ) ) |
- return error; |
- |
- cva = cdf1->ClassValueArray; |
- |
- if ( ACCESS_Frame( count * 2L ) ) |
- goto Fail; |
- |
- for ( n = 0; n < count; n++ ) |
- { |
- cva[n] = GET_UShort(); |
- if ( cva[n] >= limit ) |
- { |
- error = ERR(HB_Err_Invalid_SubTable); |
- goto Fail; |
- } |
- } |
- |
- FORGET_Frame(); |
- |
- return HB_Err_Ok; |
- |
-Fail: |
- FREE( cva ); |
- |
- return error; |
-} |
- |
- |
-static void Free_ClassDef1( HB_ClassDefFormat1* cdf1 ) |
-{ |
- FREE( cdf1->ClassValueArray ); |
-} |
- |
- |
-/* ClassDefFormat2 */ |
- |
-static HB_Error Load_ClassDef2( HB_ClassDefinition* cd, |
- HB_UShort limit, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n, count; |
- |
- HB_ClassRangeRecord* crr; |
- |
- HB_ClassDefFormat2* cdf2; |
- |
- |
- cdf2 = &cd->cd.cd2; |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- count = GET_UShort(); |
- cdf2->ClassRangeCount = 0; /* zero for now. we fill with the number of good entries later */ |
- |
- FORGET_Frame(); |
- |
- cdf2->ClassRangeRecord = NULL; |
- |
- if ( ALLOC_ARRAY( cdf2->ClassRangeRecord, count, HB_ClassRangeRecord ) ) |
- return error; |
- |
- crr = cdf2->ClassRangeRecord; |
- |
- if ( ACCESS_Frame( count * 6L ) ) |
- goto Fail; |
- |
- for ( n = 0; n < count; n++ ) |
- { |
- crr[n].Start = GET_UShort(); |
- crr[n].End = GET_UShort(); |
- crr[n].Class = GET_UShort(); |
- |
- /* sanity check */ |
- |
- if ( crr[n].Start > crr[n].End || |
- crr[n].Class >= limit ) |
- { |
- /* XXX |
- * Corrupt entry. Skip it. |
- * This is hit by Nafees Nastaliq font for example |
- */ |
- n--; |
- count--; |
- } |
- } |
- |
- FORGET_Frame(); |
- |
- cdf2->ClassRangeCount = count; |
- |
- return HB_Err_Ok; |
- |
-Fail: |
- FREE( crr ); |
- |
- return error; |
-} |
- |
- |
-static void Free_ClassDef2( HB_ClassDefFormat2* cdf2 ) |
-{ |
- FREE( cdf2->ClassRangeRecord ); |
-} |
- |
- |
-/* ClassDefinition */ |
- |
-HB_INTERNAL HB_Error |
-_HB_OPEN_Load_ClassDefinition( HB_ClassDefinition* cd, |
- HB_UShort limit, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- cd->ClassFormat = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- switch ( cd->ClassFormat ) |
- { |
- case 1: error = Load_ClassDef1( cd, limit, stream ); break; |
- case 2: error = Load_ClassDef2( cd, limit, stream ); break; |
- default: error = ERR(HB_Err_Invalid_SubTable_Format); break; |
- } |
- |
- if ( error ) |
- return error; |
- |
- cd->loaded = TRUE; |
- |
- return HB_Err_Ok; |
-} |
- |
- |
-static HB_Error |
-_HB_OPEN_Load_EmptyClassDefinition( HB_ClassDefinition* cd ) |
-{ |
- HB_Error error; |
- |
- cd->ClassFormat = 1; /* Meaningless */ |
- |
- if ( ALLOC_ARRAY( cd->cd.cd1.ClassValueArray, 1, HB_UShort ) ) |
- return error; |
- |
- cd->loaded = TRUE; |
- |
- return HB_Err_Ok; |
-} |
- |
-HB_INTERNAL HB_Error |
-_HB_OPEN_Load_EmptyOrClassDefinition( HB_ClassDefinition* cd, |
- HB_UShort limit, |
- HB_UInt class_offset, |
- HB_UInt base_offset, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- HB_UInt cur_offset; |
- |
- cur_offset = FILE_Pos(); |
- |
- if ( class_offset ) |
- { |
- if ( !FILE_Seek( class_offset + base_offset ) ) |
- error = _HB_OPEN_Load_ClassDefinition( cd, limit, stream ); |
- } |
- else |
- error = _HB_OPEN_Load_EmptyClassDefinition ( cd ); |
- |
- if (error == HB_Err_Ok) |
- (void)FILE_Seek( cur_offset ); /* Changes error as a side-effect */ |
- |
- return error; |
-} |
- |
-HB_INTERNAL void |
-_HB_OPEN_Free_ClassDefinition( HB_ClassDefinition* cd ) |
-{ |
- if ( !cd->loaded ) |
- return; |
- |
- switch ( cd->ClassFormat ) |
- { |
- case 1: Free_ClassDef1( &cd->cd.cd1 ); break; |
- case 2: Free_ClassDef2( &cd->cd.cd2 ); break; |
- default: break; |
- } |
-} |
- |
- |
-static HB_Error Get_Class1( HB_ClassDefFormat1* cdf1, |
- HB_UShort glyphID, |
- HB_UShort* klass, |
- HB_UShort* index ) |
-{ |
- HB_UShort* cva = cdf1->ClassValueArray; |
- |
- |
- if ( index ) |
- *index = 0; |
- |
- if ( glyphID >= cdf1->StartGlyph && |
- glyphID < cdf1->StartGlyph + cdf1->GlyphCount ) |
- { |
- *klass = cva[glyphID - cdf1->StartGlyph]; |
- return HB_Err_Ok; |
- } |
- else |
- { |
- *klass = 0; |
- return HB_Err_Not_Covered; |
- } |
-} |
- |
- |
-/* we need the index value of the last searched class range record |
- in case of failure for constructed GDEF tables */ |
- |
-static HB_Error Get_Class2( HB_ClassDefFormat2* cdf2, |
- HB_UShort glyphID, |
- HB_UShort* klass, |
- HB_UShort* index ) |
-{ |
- HB_Error error = HB_Err_Ok; |
- HB_UShort min, max, new_min, new_max, middle; |
- |
- HB_ClassRangeRecord* crr = cdf2->ClassRangeRecord; |
- |
- |
- /* binary search */ |
- |
- if ( cdf2->ClassRangeCount == 0 ) |
- { |
- *klass = 0; |
- if ( index ) |
- *index = 0; |
- |
- return HB_Err_Not_Covered; |
- } |
- |
- new_min = 0; |
- new_max = cdf2->ClassRangeCount - 1; |
- |
- do |
- { |
- min = new_min; |
- max = new_max; |
- |
- /* we use (min + max) / 2 = max - (max - min) / 2 to avoid |
- overflow and rounding errors */ |
- |
- middle = max - ( ( max - min ) >> 1 ); |
- |
- if ( glyphID >= crr[middle].Start && glyphID <= crr[middle].End ) |
- { |
- *klass = crr[middle].Class; |
- error = HB_Err_Ok; |
- break; |
- } |
- else if ( glyphID < crr[middle].Start ) |
- { |
- if ( middle == min ) |
- { |
- *klass = 0; |
- error = HB_Err_Not_Covered; |
- break; |
- } |
- new_max = middle - 1; |
- } |
- else |
- { |
- if ( middle == max ) |
- { |
- *klass = 0; |
- error = HB_Err_Not_Covered; |
- break; |
- } |
- new_min = middle + 1; |
- } |
- } while ( min < max ); |
- |
- if ( index ) |
- *index = middle; |
- |
- return error; |
-} |
- |
- |
-HB_INTERNAL HB_Error |
-_HB_OPEN_Get_Class( HB_ClassDefinition* cd, |
- HB_UShort glyphID, |
- HB_UShort* klass, |
- HB_UShort* index ) |
-{ |
- switch ( cd->ClassFormat ) |
- { |
- case 1: return Get_Class1( &cd->cd.cd1, glyphID, klass, index ); |
- case 2: return Get_Class2( &cd->cd.cd2, glyphID, klass, index ); |
- default: return ERR(HB_Err_Invalid_SubTable_Format); |
- } |
- |
- return HB_Err_Ok; /* never reached */ |
-} |
- |
- |
- |
-/*************************** |
- * Device related functions |
- ***************************/ |
- |
- |
-HB_INTERNAL HB_Error |
-_HB_OPEN_Load_Device( HB_Device* d, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n, count; |
- |
- HB_UShort* dv; |
- |
- |
- if ( ACCESS_Frame( 6L ) ) |
- return error; |
- |
- d->StartSize = GET_UShort(); |
- d->EndSize = GET_UShort(); |
- d->DeltaFormat = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- d->DeltaValue = NULL; |
- |
- if ( d->StartSize > d->EndSize || |
- d->DeltaFormat == 0 || d->DeltaFormat > 3 ) |
- { |
- /* XXX |
- * I've seen fontforge generate DeltaFormat == 0. |
- * Just return Ok and let the NULL DeltaValue disable |
- * this table. |
- */ |
- return HB_Err_Ok; |
- } |
- |
- count = ( ( d->EndSize - d->StartSize + 1 ) >> |
- ( 4 - d->DeltaFormat ) ) + 1; |
- |
- if ( ALLOC_ARRAY( d->DeltaValue, count, HB_UShort ) ) |
- return error; |
- |
- if ( ACCESS_Frame( count * 2L ) ) |
- { |
- FREE( d->DeltaValue ); |
- return error; |
- } |
- |
- dv = d->DeltaValue; |
- |
- for ( n = 0; n < count; n++ ) |
- dv[n] = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- return HB_Err_Ok; |
-} |
- |
- |
-HB_INTERNAL void |
-_HB_OPEN_Free_Device( HB_Device* d ) |
-{ |
- FREE( d->DeltaValue ); |
-} |
- |
- |
-/* Since we have the delta values stored in compressed form, we must |
- uncompress it now. To simplify the interface, the function always |
- returns a meaningful value in `value'; the error is just for |
- information. |
- | | |
- format = 1: 0011223344556677|8899101112131415|... |
- | | |
- byte 1 byte 2 |
- |
- 00: (byte >> 14) & mask |
- 11: (byte >> 12) & mask |
- ... |
- |
- mask = 0x0003 |
- | | |
- format = 2: 0000111122223333|4444555566667777|... |
- | | |
- byte 1 byte 2 |
- |
- 0000: (byte >> 12) & mask |
- 1111: (byte >> 8) & mask |
- ... |
- |
- mask = 0x000F |
- | | |
- format = 3: 0000000011111111|2222222233333333|... |
- | | |
- byte 1 byte 2 |
- |
- 00000000: (byte >> 8) & mask |
- 11111111: (byte >> 0) & mask |
- .... |
- |
- mask = 0x00FF */ |
- |
-HB_INTERNAL HB_Error |
-_HB_OPEN_Get_Device( HB_Device* d, |
- HB_UShort size, |
- HB_Short* value ) |
-{ |
- HB_UShort byte, bits, mask, f, s; |
- |
- |
- f = d->DeltaFormat; |
- |
- if ( d->DeltaValue && size >= d->StartSize && size <= d->EndSize ) |
- { |
- s = size - d->StartSize; |
- byte = d->DeltaValue[s >> ( 4 - f )]; |
- bits = byte >> ( 16 - ( ( s % ( 1 << ( 4 - f ) ) + 1 ) << f ) ); |
- mask = 0xFFFF >> ( 16 - ( 1 << f ) ); |
- |
- *value = (HB_Short)( bits & mask ); |
- |
- /* conversion to a signed value */ |
- |
- if ( *value >= ( ( mask + 1 ) >> 1 ) ) |
- *value -= mask + 1; |
- |
- return HB_Err_Ok; |
- } |
- else |
- { |
- *value = 0; |
- return HB_Err_Not_Covered; |
- } |
-} |
- |
- |
-/* END */ |