Index: third_party/harfbuzz/src/harfbuzz-gsub.c |
diff --git a/third_party/harfbuzz/src/harfbuzz-gsub.c b/third_party/harfbuzz/src/harfbuzz-gsub.c |
deleted file mode 100644 |
index 21fec51924f122a9726ced2bc843a303dc06fac4..0000000000000000000000000000000000000000 |
--- a/third_party/harfbuzz/src/harfbuzz-gsub.c |
+++ /dev/null |
@@ -1,4329 +0,0 @@ |
-/* |
- * Copyright (C) 1998-2004 David Turner and Werner Lemberg |
- * Copyright (C) 2006 Behdad Esfahbod |
- * Copyright (C) 2007 Red Hat, Inc. |
- * |
- * 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. |
- * |
- * Red Hat Author(s): Behdad Esfahbod |
- */ |
- |
-#include "harfbuzz-impl.h" |
-#include "harfbuzz-gsub-private.h" |
-#include "harfbuzz-open-private.h" |
-#include "harfbuzz-gdef-private.h" |
- |
-static HB_Error GSUB_Do_Glyph_Lookup( HB_GSUBHeader* gsub, |
- HB_UShort lookup_index, |
- HB_Buffer buffer, |
- HB_UShort context_length, |
- int nesting_level ); |
- |
- |
- |
-/********************** |
- * Auxiliary functions |
- **********************/ |
- |
- |
- |
-HB_Error HB_Load_GSUB_Table( HB_Stream stream, |
- HB_GSUBHeader** retptr, |
- HB_GDEFHeader* gdef, |
- HB_Stream gdefStream ) |
-{ |
- HB_Error error; |
- HB_UInt cur_offset, new_offset, base_offset; |
- |
- HB_GSUBHeader* gsub; |
- |
- if ( !retptr ) |
- return ERR(HB_Err_Invalid_Argument); |
- |
- if ( GOTO_Table( TTAG_GSUB ) ) |
- return error; |
- |
- base_offset = FILE_Pos(); |
- |
- if ( ALLOC ( gsub, sizeof( *gsub ) ) ) |
- return error; |
- |
- |
- /* skip version */ |
- |
- if ( FILE_Seek( base_offset + 4L ) || |
- ACCESS_Frame( 2L ) ) |
- goto Fail4; |
- |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = _HB_OPEN_Load_ScriptList( &gsub->ScriptList, |
- stream ) ) != HB_Err_Ok ) |
- goto Fail4; |
- (void)FILE_Seek( cur_offset ); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail3; |
- |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = _HB_OPEN_Load_FeatureList( &gsub->FeatureList, |
- stream ) ) != HB_Err_Ok ) |
- goto Fail3; |
- (void)FILE_Seek( cur_offset ); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail2; |
- |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = _HB_OPEN_Load_LookupList( &gsub->LookupList, |
- stream, HB_Type_GSUB ) ) != HB_Err_Ok ) |
- goto Fail2; |
- |
- gsub->gdef = gdef; /* can be NULL */ |
- |
- if ( ( error = _HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( gdef, gdefStream, |
- gsub->LookupList.Lookup, |
- gsub->LookupList.LookupCount ) ) ) |
- goto Fail1; |
- |
- *retptr = gsub; |
- |
- return HB_Err_Ok; |
- |
-Fail1: |
- _HB_OPEN_Free_LookupList( &gsub->LookupList, HB_Type_GSUB ); |
- |
-Fail2: |
- _HB_OPEN_Free_FeatureList( &gsub->FeatureList ); |
- |
-Fail3: |
- _HB_OPEN_Free_ScriptList( &gsub->ScriptList ); |
- |
-Fail4: |
- FREE ( gsub ); |
- |
- |
- return error; |
-} |
- |
- |
-HB_Error HB_Done_GSUB_Table( HB_GSUBHeader* gsub ) |
-{ |
- _HB_OPEN_Free_LookupList( &gsub->LookupList, HB_Type_GSUB ); |
- _HB_OPEN_Free_FeatureList( &gsub->FeatureList ); |
- _HB_OPEN_Free_ScriptList( &gsub->ScriptList ); |
- |
- FREE( gsub ); |
- |
- return HB_Err_Ok; |
-} |
- |
-/***************************** |
- * SubTable related functions |
- *****************************/ |
- |
- |
-/* LookupType 1 */ |
- |
-/* SingleSubstFormat1 */ |
-/* SingleSubstFormat2 */ |
- |
-static HB_Error Load_SingleSubst( HB_GSUB_SubTable* st, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- HB_SingleSubst* ss = &st->single; |
- |
- HB_UShort n, count; |
- HB_UInt cur_offset, new_offset, base_offset; |
- |
- HB_UShort* s; |
- |
- |
- base_offset = FILE_Pos(); |
- |
- if ( ACCESS_Frame( 4L ) ) |
- return error; |
- |
- ss->SubstFormat = GET_UShort(); |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = _HB_OPEN_Load_Coverage( &ss->Coverage, stream ) ) != HB_Err_Ok ) |
- return error; |
- (void)FILE_Seek( cur_offset ); |
- |
- switch ( ss->SubstFormat ) |
- { |
- case 1: |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail2; |
- |
- ss->ssf.ssf1.DeltaGlyphID = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- break; |
- |
- case 2: |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail2; |
- |
- count = ss->ssf.ssf2.GlyphCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- ss->ssf.ssf2.Substitute = NULL; |
- |
- if ( ALLOC_ARRAY( ss->ssf.ssf2.Substitute, count, HB_UShort ) ) |
- goto Fail2; |
- |
- s = ss->ssf.ssf2.Substitute; |
- |
- if ( ACCESS_Frame( count * 2L ) ) |
- goto Fail1; |
- |
- for ( n = 0; n < count; n++ ) |
- s[n] = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- break; |
- |
- default: |
- return ERR(HB_Err_Invalid_SubTable_Format); |
- } |
- |
- return HB_Err_Ok; |
- |
-Fail1: |
- FREE( s ); |
- |
-Fail2: |
- _HB_OPEN_Free_Coverage( &ss->Coverage ); |
- return error; |
-} |
- |
- |
-static void Free_SingleSubst( HB_GSUB_SubTable* st ) |
-{ |
- HB_SingleSubst* ss = &st->single; |
- |
- switch ( ss->SubstFormat ) |
- { |
- case 1: |
- break; |
- |
- case 2: |
- FREE( ss->ssf.ssf2.Substitute ); |
- break; |
- |
- default: |
- break; |
- } |
- |
- _HB_OPEN_Free_Coverage( &ss->Coverage ); |
-} |
- |
- |
-static HB_Error Lookup_SingleSubst( HB_GSUBHeader* gsub, |
- HB_GSUB_SubTable* st, |
- HB_Buffer buffer, |
- HB_UShort flags, |
- HB_UShort context_length, |
- int nesting_level ) |
-{ |
- HB_UShort index, value, property; |
- HB_Error error; |
- HB_SingleSubst* ss = &st->single; |
- HB_GDEFHeader* gdef = gsub->gdef; |
- |
- HB_UNUSED(nesting_level); |
- |
- if ( context_length != 0xFFFF && context_length < 1 ) |
- return HB_Err_Not_Covered; |
- |
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) |
- return error; |
- |
- error = _HB_OPEN_Coverage_Index( &ss->Coverage, IN_CURGLYPH(), &index ); |
- if ( error ) |
- return error; |
- |
- switch ( ss->SubstFormat ) |
- { |
- case 1: |
- value = ( IN_CURGLYPH() + ss->ssf.ssf1.DeltaGlyphID ) & 0xFFFF; |
- if ( REPLACE_Glyph( buffer, value, nesting_level ) ) |
- return error; |
- break; |
- |
- case 2: |
- if ( index >= ss->ssf.ssf2.GlyphCount ) |
- return ERR(HB_Err_Invalid_SubTable); |
- value = ss->ssf.ssf2.Substitute[index]; |
- if ( REPLACE_Glyph( buffer, value, nesting_level ) ) |
- return error; |
- break; |
- |
- default: |
- return ERR(HB_Err_Invalid_SubTable); |
- } |
- |
- if ( gdef && gdef->NewGlyphClasses ) |
- { |
- /* we inherit the old glyph class to the substituted glyph */ |
- |
- error = _HB_GDEF_Add_Glyph_Property( gdef, value, property ); |
- if ( error && error != HB_Err_Not_Covered ) |
- return error; |
- } |
- |
- return HB_Err_Ok; |
-} |
- |
- |
-/* LookupType 2 */ |
- |
-/* Sequence */ |
- |
-static HB_Error Load_Sequence( HB_Sequence* s, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n, count; |
- HB_UShort* sub; |
- |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- count = s->GlyphCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- s->Substitute = NULL; |
- |
- if ( count ) |
- { |
- if ( ALLOC_ARRAY( s->Substitute, count, HB_UShort ) ) |
- return error; |
- |
- sub = s->Substitute; |
- |
- if ( ACCESS_Frame( count * 2L ) ) |
- { |
- FREE( sub ); |
- return error; |
- } |
- |
- for ( n = 0; n < count; n++ ) |
- sub[n] = GET_UShort(); |
- |
- FORGET_Frame(); |
- } |
- |
- return HB_Err_Ok; |
-} |
- |
- |
-static void Free_Sequence( HB_Sequence* s ) |
-{ |
- FREE( s->Substitute ); |
-} |
- |
- |
-/* MultipleSubstFormat1 */ |
- |
-static HB_Error Load_MultipleSubst( HB_GSUB_SubTable* st, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- HB_MultipleSubst* ms = &st->multiple; |
- |
- HB_UShort n = 0, m, count; |
- HB_UInt cur_offset, new_offset, base_offset; |
- |
- HB_Sequence* s; |
- |
- |
- base_offset = FILE_Pos(); |
- |
- if ( ACCESS_Frame( 4L ) ) |
- return error; |
- |
- ms->SubstFormat = GET_UShort(); /* should be 1 */ |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = _HB_OPEN_Load_Coverage( &ms->Coverage, stream ) ) != HB_Err_Ok ) |
- return error; |
- (void)FILE_Seek( cur_offset ); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail2; |
- |
- count = ms->SequenceCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- ms->Sequence = NULL; |
- |
- if ( ALLOC_ARRAY( ms->Sequence, count, HB_Sequence ) ) |
- goto Fail2; |
- |
- s = ms->Sequence; |
- |
- 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_Sequence( &s[n], stream ) ) != HB_Err_Ok ) |
- goto Fail1; |
- (void)FILE_Seek( cur_offset ); |
- } |
- |
- return HB_Err_Ok; |
- |
-Fail1: |
- for ( m = 0; m < n; m++ ) |
- Free_Sequence( &s[m] ); |
- |
- FREE( s ); |
- |
-Fail2: |
- _HB_OPEN_Free_Coverage( &ms->Coverage ); |
- return error; |
-} |
- |
- |
-static void Free_MultipleSubst( HB_GSUB_SubTable* st ) |
-{ |
- HB_UShort n, count; |
- HB_MultipleSubst* ms = &st->multiple; |
- |
- HB_Sequence* s; |
- |
- |
- if ( ms->Sequence ) |
- { |
- count = ms->SequenceCount; |
- s = ms->Sequence; |
- |
- for ( n = 0; n < count; n++ ) |
- Free_Sequence( &s[n] ); |
- |
- FREE( s ); |
- } |
- |
- _HB_OPEN_Free_Coverage( &ms->Coverage ); |
-} |
- |
- |
-static HB_Error Lookup_MultipleSubst( HB_GSUBHeader* gsub, |
- HB_GSUB_SubTable* st, |
- HB_Buffer buffer, |
- HB_UShort flags, |
- HB_UShort context_length, |
- int nesting_level ) |
-{ |
- HB_Error error; |
- HB_UShort index, property, n, count; |
- HB_UShort*s; |
- HB_MultipleSubst* ms = &st->multiple; |
- HB_GDEFHeader* gdef = gsub->gdef; |
- |
- HB_UNUSED(nesting_level); |
- |
- if ( context_length != 0xFFFF && context_length < 1 ) |
- return HB_Err_Not_Covered; |
- |
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) |
- return error; |
- |
- error = _HB_OPEN_Coverage_Index( &ms->Coverage, IN_CURGLYPH(), &index ); |
- if ( error ) |
- return error; |
- |
- if ( index >= ms->SequenceCount ) |
- return ERR(HB_Err_Invalid_SubTable); |
- |
- count = ms->Sequence[index].GlyphCount; |
- s = ms->Sequence[index].Substitute; |
- |
- if ( ADD_String( buffer, 1, count, s, 0xFFFF, 0xFFFF ) ) |
- return error; |
- |
- if ( gdef && gdef->NewGlyphClasses ) |
- { |
- /* this is a guess only ... */ |
- |
- if ( property == HB_GDEF_LIGATURE ) |
- property = HB_GDEF_BASE_GLYPH; |
- |
- for ( n = 0; n < count; n++ ) |
- { |
- error = _HB_GDEF_Add_Glyph_Property( gdef, s[n], property ); |
- if ( error && error != HB_Err_Not_Covered ) |
- return error; |
- } |
- } |
- |
- return HB_Err_Ok; |
-} |
- |
- |
-/* LookupType 3 */ |
- |
-/* AlternateSet */ |
- |
-static HB_Error Load_AlternateSet( HB_AlternateSet* as, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n, count; |
- HB_UShort* a; |
- |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- count = as->GlyphCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- as->Alternate = NULL; |
- |
- if ( ALLOC_ARRAY( as->Alternate, count, HB_UShort ) ) |
- return error; |
- |
- a = as->Alternate; |
- |
- if ( ACCESS_Frame( count * 2L ) ) |
- { |
- FREE( a ); |
- return error; |
- } |
- |
- for ( n = 0; n < count; n++ ) |
- a[n] = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- return HB_Err_Ok; |
-} |
- |
- |
-static void Free_AlternateSet( HB_AlternateSet* as ) |
-{ |
- FREE( as->Alternate ); |
-} |
- |
- |
-/* AlternateSubstFormat1 */ |
- |
-static HB_Error Load_AlternateSubst( HB_GSUB_SubTable* st, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- HB_AlternateSubst* as = &st->alternate; |
- |
- HB_UShort n = 0, m, count; |
- HB_UInt cur_offset, new_offset, base_offset; |
- |
- HB_AlternateSet* aset; |
- |
- |
- base_offset = FILE_Pos(); |
- |
- if ( ACCESS_Frame( 4L ) ) |
- return error; |
- |
- as->SubstFormat = GET_UShort(); /* should be 1 */ |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = _HB_OPEN_Load_Coverage( &as->Coverage, stream ) ) != HB_Err_Ok ) |
- return error; |
- (void)FILE_Seek( cur_offset ); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail2; |
- |
- count = as->AlternateSetCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- as->AlternateSet = NULL; |
- |
- if ( ALLOC_ARRAY( as->AlternateSet, count, HB_AlternateSet ) ) |
- goto Fail2; |
- |
- aset = as->AlternateSet; |
- |
- 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_AlternateSet( &aset[n], stream ) ) != HB_Err_Ok ) |
- goto Fail1; |
- (void)FILE_Seek( cur_offset ); |
- } |
- |
- return HB_Err_Ok; |
- |
-Fail1: |
- for ( m = 0; m < n; m++ ) |
- Free_AlternateSet( &aset[m] ); |
- |
- FREE( aset ); |
- |
-Fail2: |
- _HB_OPEN_Free_Coverage( &as->Coverage ); |
- return error; |
-} |
- |
- |
-static void Free_AlternateSubst( HB_GSUB_SubTable* st ) |
-{ |
- HB_UShort n, count; |
- HB_AlternateSubst* as = &st->alternate; |
- |
- HB_AlternateSet* aset; |
- |
- |
- if ( as->AlternateSet ) |
- { |
- count = as->AlternateSetCount; |
- aset = as->AlternateSet; |
- |
- for ( n = 0; n < count; n++ ) |
- Free_AlternateSet( &aset[n] ); |
- |
- FREE( aset ); |
- } |
- |
- _HB_OPEN_Free_Coverage( &as->Coverage ); |
-} |
- |
- |
-static HB_Error Lookup_AlternateSubst( HB_GSUBHeader* gsub, |
- HB_GSUB_SubTable* st, |
- HB_Buffer buffer, |
- HB_UShort flags, |
- HB_UShort context_length, |
- int nesting_level ) |
-{ |
- HB_Error error; |
- HB_UShort index, value, alt_index, property; |
- HB_AlternateSubst* as = &st->alternate; |
- HB_GDEFHeader* gdef = gsub->gdef; |
- HB_AlternateSet aset; |
- |
- HB_UNUSED(nesting_level); |
- |
- if ( context_length != 0xFFFF && context_length < 1 ) |
- return HB_Err_Not_Covered; |
- |
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) |
- return error; |
- |
- error = _HB_OPEN_Coverage_Index( &as->Coverage, IN_CURGLYPH(), &index ); |
- if ( error ) |
- return error; |
- |
- aset = as->AlternateSet[index]; |
- |
- /* we use a user-defined callback function to get the alternate index */ |
- |
- if ( gsub->altfunc ) |
- alt_index = (gsub->altfunc)( buffer->out_pos, IN_CURGLYPH(), |
- aset.GlyphCount, aset.Alternate, |
- gsub->data ); |
- else |
- alt_index = 0; |
- |
- value = aset.Alternate[alt_index]; |
- if ( REPLACE_Glyph( buffer, value, nesting_level ) ) |
- return error; |
- |
- if ( gdef && gdef->NewGlyphClasses ) |
- { |
- /* we inherit the old glyph class to the substituted glyph */ |
- |
- error = _HB_GDEF_Add_Glyph_Property( gdef, value, property ); |
- if ( error && error != HB_Err_Not_Covered ) |
- return error; |
- } |
- |
- return HB_Err_Ok; |
-} |
- |
- |
-/* LookupType 4 */ |
- |
-/* Ligature */ |
- |
-static HB_Error Load_Ligature( HB_Ligature* l, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n, count; |
- HB_UShort* c; |
- |
- |
- if ( ACCESS_Frame( 4L ) ) |
- return error; |
- |
- l->LigGlyph = GET_UShort(); |
- l->ComponentCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- l->Component = NULL; |
- |
- count = l->ComponentCount - 1; /* only ComponentCount - 1 elements */ |
- |
- if ( ALLOC_ARRAY( l->Component, count, HB_UShort ) ) |
- return error; |
- |
- c = l->Component; |
- |
- if ( ACCESS_Frame( count * 2L ) ) |
- { |
- FREE( c ); |
- return error; |
- } |
- |
- for ( n = 0; n < count; n++ ) |
- c[n] = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- return HB_Err_Ok; |
-} |
- |
- |
-static void Free_Ligature( HB_Ligature* l ) |
-{ |
- FREE( l->Component ); |
-} |
- |
- |
-/* LigatureSet */ |
- |
-static HB_Error Load_LigatureSet( HB_LigatureSet* ls, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n = 0, m, count; |
- HB_UInt cur_offset, new_offset, base_offset; |
- |
- HB_Ligature* l; |
- |
- |
- base_offset = FILE_Pos(); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- count = ls->LigatureCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- ls->Ligature = NULL; |
- |
- if ( ALLOC_ARRAY( ls->Ligature, count, HB_Ligature ) ) |
- return error; |
- |
- l = ls->Ligature; |
- |
- 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 ( FILE_Seek( new_offset ) || |
- ( error = Load_Ligature( &l[n], stream ) ) != HB_Err_Ok ) |
- goto Fail; |
- (void)FILE_Seek( cur_offset ); |
- } |
- |
- return HB_Err_Ok; |
- |
-Fail: |
- for ( m = 0; m < n; m++ ) |
- Free_Ligature( &l[m] ); |
- |
- FREE( l ); |
- return error; |
-} |
- |
- |
-static void Free_LigatureSet( HB_LigatureSet* ls ) |
-{ |
- HB_UShort n, count; |
- |
- HB_Ligature* l; |
- |
- |
- if ( ls->Ligature ) |
- { |
- count = ls->LigatureCount; |
- l = ls->Ligature; |
- |
- for ( n = 0; n < count; n++ ) |
- Free_Ligature( &l[n] ); |
- |
- FREE( l ); |
- } |
-} |
- |
- |
-/* LigatureSubstFormat1 */ |
- |
-static HB_Error Load_LigatureSubst( HB_GSUB_SubTable* st, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- HB_LigatureSubst* ls = &st->ligature; |
- |
- HB_UShort n = 0, m, count; |
- HB_UInt cur_offset, new_offset, base_offset; |
- |
- HB_LigatureSet* lset; |
- |
- |
- base_offset = FILE_Pos(); |
- |
- if ( ACCESS_Frame( 4L ) ) |
- return error; |
- |
- ls->SubstFormat = GET_UShort(); /* should be 1 */ |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = _HB_OPEN_Load_Coverage( &ls->Coverage, stream ) ) != HB_Err_Ok ) |
- return error; |
- (void)FILE_Seek( cur_offset ); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail2; |
- |
- count = ls->LigatureSetCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- ls->LigatureSet = NULL; |
- |
- if ( ALLOC_ARRAY( ls->LigatureSet, count, HB_LigatureSet ) ) |
- goto Fail2; |
- |
- lset = ls->LigatureSet; |
- |
- 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_LigatureSet( &lset[n], stream ) ) != HB_Err_Ok ) |
- goto Fail1; |
- (void)FILE_Seek( cur_offset ); |
- } |
- |
- return HB_Err_Ok; |
- |
-Fail1: |
- for ( m = 0; m < n; m++ ) |
- Free_LigatureSet( &lset[m] ); |
- |
- FREE( lset ); |
- |
-Fail2: |
- _HB_OPEN_Free_Coverage( &ls->Coverage ); |
- return error; |
-} |
- |
- |
-static void Free_LigatureSubst( HB_GSUB_SubTable* st ) |
-{ |
- HB_UShort n, count; |
- HB_LigatureSubst* ls = &st->ligature; |
- |
- HB_LigatureSet* lset; |
- |
- |
- if ( ls->LigatureSet ) |
- { |
- count = ls->LigatureSetCount; |
- lset = ls->LigatureSet; |
- |
- for ( n = 0; n < count; n++ ) |
- Free_LigatureSet( &lset[n] ); |
- |
- FREE( lset ); |
- } |
- |
- _HB_OPEN_Free_Coverage( &ls->Coverage ); |
-} |
- |
- |
-static HB_Error Lookup_LigatureSubst( HB_GSUBHeader* gsub, |
- HB_GSUB_SubTable* st, |
- HB_Buffer buffer, |
- HB_UShort flags, |
- HB_UShort context_length, |
- int nesting_level ) |
-{ |
- HB_UShort index, property; |
- HB_Error error; |
- HB_UShort numlig, i, j, is_mark, first_is_mark = FALSE; |
- HB_UShort* c; |
- HB_LigatureSubst* ls = &st->ligature; |
- HB_GDEFHeader* gdef = gsub->gdef; |
- |
- HB_Ligature* lig; |
- |
- HB_UNUSED(nesting_level); |
- |
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) |
- return error; |
- |
- if ( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) |
- first_is_mark = TRUE; |
- |
- error = _HB_OPEN_Coverage_Index( &ls->Coverage, IN_CURGLYPH(), &index ); |
- if ( error ) |
- return error; |
- |
- if ( index >= ls->LigatureSetCount ) |
- return ERR(HB_Err_Invalid_SubTable); |
- |
- lig = ls->LigatureSet[index].Ligature; |
- |
- for ( numlig = ls->LigatureSet[index].LigatureCount; |
- numlig; |
- numlig--, lig++ ) |
- { |
- if ( buffer->in_pos + lig->ComponentCount > buffer->in_length ) |
- goto next_ligature; /* Not enough glyphs in input */ |
- |
- c = lig->Component; |
- |
- is_mark = first_is_mark; |
- |
- if ( context_length != 0xFFFF && context_length < lig->ComponentCount ) |
- break; |
- |
- for ( i = 1, j = buffer->in_pos + 1; i < lig->ComponentCount; i++, j++ ) |
- { |
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) ) |
- { |
- if ( error && error != HB_Err_Not_Covered ) |
- return error; |
- |
- if ( j + lig->ComponentCount - i == (HB_Int)buffer->in_length ) |
- goto next_ligature; |
- j++; |
- } |
- |
- if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) ) |
- is_mark = FALSE; |
- |
- if ( IN_GLYPH( j ) != c[i - 1] ) |
- goto next_ligature; |
- } |
- |
- if ( gdef && gdef->NewGlyphClasses ) |
- { |
- /* this is just a guess ... */ |
- |
- error = _HB_GDEF_Add_Glyph_Property( gdef, lig->LigGlyph, |
- is_mark ? HB_GDEF_MARK : HB_GDEF_LIGATURE ); |
- if ( error && error != HB_Err_Not_Covered ) |
- return error; |
- } |
- |
- if ( j == buffer->in_pos + i ) /* No input glyphs skipped */ |
- { |
- /* We don't use a new ligature ID if there are no skipped |
- glyphs and the ligature already has an ID. */ |
- |
- if ( IN_LIGID( buffer->in_pos ) ) |
- { |
- if ( ADD_String( buffer, i, 1, &lig->LigGlyph, |
- 0xFFFF, 0xFFFF ) ) |
- return error; |
- } |
- else |
- { |
- HB_UShort ligID = _hb_buffer_allocate_ligid( buffer ); |
- if ( ADD_String( buffer, i, 1, &lig->LigGlyph, |
- 0xFFFF, ligID ) ) |
- return error; |
- } |
- } |
- else |
- { |
- HB_UShort ligID = _hb_buffer_allocate_ligid( buffer ); |
- if ( ADD_Glyph( buffer, lig->LigGlyph, 0xFFFF, ligID ) ) |
- return error; |
- |
- /* Now we must do a second loop to copy the skipped glyphs to |
- `out' and assign component values to it. We start with the |
- glyph after the first component. Glyphs between component |
- i and i+1 belong to component i. Together with the ligID |
- value it is later possible to check whether a specific |
- component value really belongs to a given ligature. */ |
- |
- for ( i = 0; i < lig->ComponentCount - 1; i++ ) |
- { |
- while ( CHECK_Property( gdef, IN_CURITEM(), |
- flags, &property ) ) |
- if ( ADD_Glyph( buffer, IN_CURGLYPH(), i, ligID ) ) |
- return error; |
- |
- (buffer->in_pos)++; |
- } |
- } |
- |
- return HB_Err_Ok; |
- |
- next_ligature: |
- ; |
- } |
- |
- return HB_Err_Not_Covered; |
-} |
- |
- |
-/* Do the actual substitution for a context substitution (either format |
- 5 or 6). This is only called after we've determined that the input |
- matches the subrule. */ |
- |
-static HB_Error Do_ContextSubst( HB_GSUBHeader* gsub, |
- HB_UShort GlyphCount, |
- HB_UShort SubstCount, |
- HB_SubstLookupRecord* subst, |
- HB_Buffer buffer, |
- int nesting_level ) |
-{ |
- HB_Error error; |
- HB_UInt i, old_pos; |
- |
- |
- i = 0; |
- |
- while ( i < GlyphCount ) |
- { |
- if ( SubstCount && i == subst->SequenceIndex ) |
- { |
- old_pos = buffer->in_pos; |
- |
- /* Do a substitution */ |
- |
- error = GSUB_Do_Glyph_Lookup( gsub, subst->LookupListIndex, buffer, |
- GlyphCount, nesting_level ); |
- |
- subst++; |
- SubstCount--; |
- i += buffer->in_pos - old_pos; |
- |
- if ( error == HB_Err_Not_Covered ) |
- { |
- if ( COPY_Glyph( buffer ) ) |
- return error; |
- i++; |
- } |
- else if ( error ) |
- return error; |
- } |
- else |
- { |
- /* No substitution for this index */ |
- |
- if ( COPY_Glyph( buffer ) ) |
- return error; |
- i++; |
- } |
- } |
- |
- return HB_Err_Ok; |
-} |
- |
- |
-/* LookupType 5 */ |
- |
-/* SubRule */ |
- |
-static HB_Error Load_SubRule( HB_SubRule* sr, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n, count; |
- HB_UShort* i; |
- |
- HB_SubstLookupRecord* slr; |
- |
- |
- if ( ACCESS_Frame( 4L ) ) |
- return error; |
- |
- sr->GlyphCount = GET_UShort(); |
- sr->SubstCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- sr->Input = NULL; |
- |
- count = sr->GlyphCount - 1; /* only GlyphCount - 1 elements */ |
- |
- if ( ALLOC_ARRAY( sr->Input, count, HB_UShort ) ) |
- return error; |
- |
- i = sr->Input; |
- |
- if ( ACCESS_Frame( count * 2L ) ) |
- goto Fail2; |
- |
- for ( n = 0; n < count; n++ ) |
- i[n] = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- sr->SubstLookupRecord = NULL; |
- |
- count = sr->SubstCount; |
- |
- if ( ALLOC_ARRAY( sr->SubstLookupRecord, count, HB_SubstLookupRecord ) ) |
- goto Fail2; |
- |
- slr = sr->SubstLookupRecord; |
- |
- if ( ACCESS_Frame( count * 4L ) ) |
- goto Fail1; |
- |
- for ( n = 0; n < count; n++ ) |
- { |
- slr[n].SequenceIndex = GET_UShort(); |
- slr[n].LookupListIndex = GET_UShort(); |
- } |
- |
- FORGET_Frame(); |
- |
- return HB_Err_Ok; |
- |
-Fail1: |
- FREE( slr ); |
- |
-Fail2: |
- FREE( i ); |
- return error; |
-} |
- |
- |
-static void Free_SubRule( HB_SubRule* sr ) |
-{ |
- FREE( sr->SubstLookupRecord ); |
- FREE( sr->Input ); |
-} |
- |
- |
-/* SubRuleSet */ |
- |
-static HB_Error Load_SubRuleSet( HB_SubRuleSet* srs, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n = 0, m, count; |
- HB_UInt cur_offset, new_offset, base_offset; |
- |
- HB_SubRule* sr; |
- |
- |
- base_offset = FILE_Pos(); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- count = srs->SubRuleCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- srs->SubRule = NULL; |
- |
- if ( ALLOC_ARRAY( srs->SubRule, count, HB_SubRule ) ) |
- return error; |
- |
- sr = srs->SubRule; |
- |
- 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 ( FILE_Seek( new_offset ) || |
- ( error = Load_SubRule( &sr[n], stream ) ) != HB_Err_Ok ) |
- goto Fail; |
- (void)FILE_Seek( cur_offset ); |
- } |
- |
- return HB_Err_Ok; |
- |
-Fail: |
- for ( m = 0; m < n; m++ ) |
- Free_SubRule( &sr[m] ); |
- |
- FREE( sr ); |
- return error; |
-} |
- |
- |
-static void Free_SubRuleSet( HB_SubRuleSet* srs ) |
-{ |
- HB_UShort n, count; |
- |
- HB_SubRule* sr; |
- |
- |
- if ( srs->SubRule ) |
- { |
- count = srs->SubRuleCount; |
- sr = srs->SubRule; |
- |
- for ( n = 0; n < count; n++ ) |
- Free_SubRule( &sr[n] ); |
- |
- FREE( sr ); |
- } |
-} |
- |
- |
-/* ContextSubstFormat1 */ |
- |
-static HB_Error Load_ContextSubst1( HB_ContextSubstFormat1* csf1, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n = 0, m, count; |
- HB_UInt cur_offset, new_offset, base_offset; |
- |
- HB_SubRuleSet* srs; |
- |
- |
- base_offset = FILE_Pos() - 2L; |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = _HB_OPEN_Load_Coverage( &csf1->Coverage, stream ) ) != HB_Err_Ok ) |
- return error; |
- (void)FILE_Seek( cur_offset ); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail2; |
- |
- count = csf1->SubRuleSetCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- csf1->SubRuleSet = NULL; |
- |
- if ( ALLOC_ARRAY( csf1->SubRuleSet, count, HB_SubRuleSet ) ) |
- goto Fail2; |
- |
- srs = csf1->SubRuleSet; |
- |
- 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_SubRuleSet( &srs[n], stream ) ) != HB_Err_Ok ) |
- goto Fail1; |
- (void)FILE_Seek( cur_offset ); |
- } |
- |
- return HB_Err_Ok; |
- |
-Fail1: |
- for ( m = 0; m < n; m++ ) |
- Free_SubRuleSet( &srs[m] ); |
- |
- FREE( srs ); |
- |
-Fail2: |
- _HB_OPEN_Free_Coverage( &csf1->Coverage ); |
- return error; |
-} |
- |
- |
-static void Free_ContextSubst1( HB_ContextSubstFormat1* csf1 ) |
-{ |
- HB_UShort n, count; |
- |
- HB_SubRuleSet* srs; |
- |
- |
- if ( csf1->SubRuleSet ) |
- { |
- count = csf1->SubRuleSetCount; |
- srs = csf1->SubRuleSet; |
- |
- for ( n = 0; n < count; n++ ) |
- Free_SubRuleSet( &srs[n] ); |
- |
- FREE( srs ); |
- } |
- |
- _HB_OPEN_Free_Coverage( &csf1->Coverage ); |
-} |
- |
- |
-/* SubClassRule */ |
- |
-static HB_Error Load_SubClassRule( HB_ContextSubstFormat2* csf2, |
- HB_SubClassRule* scr, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n, count; |
- |
- HB_UShort* c; |
- HB_SubstLookupRecord* slr; |
- |
- |
- if ( ACCESS_Frame( 4L ) ) |
- return error; |
- |
- scr->GlyphCount = GET_UShort(); |
- scr->SubstCount = GET_UShort(); |
- |
- if ( scr->GlyphCount > csf2->MaxContextLength ) |
- csf2->MaxContextLength = scr->GlyphCount; |
- |
- FORGET_Frame(); |
- |
- scr->Class = NULL; |
- |
- count = scr->GlyphCount - 1; /* only GlyphCount - 1 elements */ |
- |
- if ( ALLOC_ARRAY( scr->Class, count, HB_UShort ) ) |
- return error; |
- |
- c = scr->Class; |
- |
- if ( ACCESS_Frame( count * 2L ) ) |
- goto Fail2; |
- |
- for ( n = 0; n < count; n++ ) |
- c[n] = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- scr->SubstLookupRecord = NULL; |
- |
- count = scr->SubstCount; |
- |
- if ( ALLOC_ARRAY( scr->SubstLookupRecord, count, HB_SubstLookupRecord ) ) |
- goto Fail2; |
- |
- slr = scr->SubstLookupRecord; |
- |
- if ( ACCESS_Frame( count * 4L ) ) |
- goto Fail1; |
- |
- for ( n = 0; n < count; n++ ) |
- { |
- slr[n].SequenceIndex = GET_UShort(); |
- slr[n].LookupListIndex = GET_UShort(); |
- } |
- |
- FORGET_Frame(); |
- |
- return HB_Err_Ok; |
- |
-Fail1: |
- FREE( slr ); |
- |
-Fail2: |
- FREE( c ); |
- return error; |
-} |
- |
- |
-static void Free_SubClassRule( HB_SubClassRule* scr ) |
-{ |
- FREE( scr->SubstLookupRecord ); |
- FREE( scr->Class ); |
-} |
- |
- |
-/* SubClassSet */ |
- |
-static HB_Error Load_SubClassSet( HB_ContextSubstFormat2* csf2, |
- HB_SubClassSet* scs, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n = 0, m, count; |
- HB_UInt cur_offset, new_offset, base_offset; |
- |
- HB_SubClassRule* scr; |
- |
- |
- base_offset = FILE_Pos(); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- count = scs->SubClassRuleCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- scs->SubClassRule = NULL; |
- |
- if ( ALLOC_ARRAY( scs->SubClassRule, count, HB_SubClassRule ) ) |
- return error; |
- |
- scr = scs->SubClassRule; |
- |
- 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 ( FILE_Seek( new_offset ) || |
- ( error = Load_SubClassRule( csf2, &scr[n], |
- stream ) ) != HB_Err_Ok ) |
- goto Fail; |
- (void)FILE_Seek( cur_offset ); |
- } |
- |
- return HB_Err_Ok; |
- |
-Fail: |
- for ( m = 0; m < n; m++ ) |
- Free_SubClassRule( &scr[m] ); |
- |
- FREE( scr ); |
- return error; |
-} |
- |
- |
-static void Free_SubClassSet( HB_SubClassSet* scs ) |
-{ |
- HB_UShort n, count; |
- |
- HB_SubClassRule* scr; |
- |
- |
- if ( scs->SubClassRule ) |
- { |
- count = scs->SubClassRuleCount; |
- scr = scs->SubClassRule; |
- |
- for ( n = 0; n < count; n++ ) |
- Free_SubClassRule( &scr[n] ); |
- |
- FREE( scr ); |
- } |
-} |
- |
- |
-/* ContextSubstFormat2 */ |
- |
-static HB_Error Load_ContextSubst2( HB_ContextSubstFormat2* csf2, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n = 0, m, count; |
- HB_UInt cur_offset, new_offset, base_offset; |
- |
- HB_SubClassSet* scs; |
- |
- |
- base_offset = FILE_Pos() - 2; |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = _HB_OPEN_Load_Coverage( &csf2->Coverage, stream ) ) != HB_Err_Ok ) |
- return error; |
- (void)FILE_Seek( cur_offset ); |
- |
- if ( ACCESS_Frame( 4L ) ) |
- goto Fail3; |
- |
- new_offset = GET_UShort() + base_offset; |
- |
- /* `SubClassSetCount' is the upper limit for class values, thus we |
- read it now to make an additional safety check. */ |
- |
- count = csf2->SubClassSetCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = _HB_OPEN_Load_ClassDefinition( &csf2->ClassDef, count, |
- stream ) ) != HB_Err_Ok ) |
- goto Fail3; |
- (void)FILE_Seek( cur_offset ); |
- |
- csf2->SubClassSet = NULL; |
- csf2->MaxContextLength = 0; |
- |
- if ( ALLOC_ARRAY( csf2->SubClassSet, count, HB_SubClassSet ) ) |
- goto Fail2; |
- |
- scs = csf2->SubClassSet; |
- |
- for ( n = 0; n < count; n++ ) |
- { |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail1; |
- |
- 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_SubClassSet( csf2, &scs[n], |
- stream ) ) != HB_Err_Ok ) |
- goto Fail1; |
- (void)FILE_Seek( cur_offset ); |
- } |
- else |
- { |
- /* we create a SubClassSet table with no entries */ |
- |
- csf2->SubClassSet[n].SubClassRuleCount = 0; |
- csf2->SubClassSet[n].SubClassRule = NULL; |
- } |
- } |
- |
- return HB_Err_Ok; |
- |
-Fail1: |
- for ( m = 0; m < n; m++ ) |
- Free_SubClassSet( &scs[m] ); |
- |
- FREE( scs ); |
- |
-Fail2: |
- _HB_OPEN_Free_ClassDefinition( &csf2->ClassDef ); |
- |
-Fail3: |
- _HB_OPEN_Free_Coverage( &csf2->Coverage ); |
- return error; |
-} |
- |
- |
-static void Free_ContextSubst2( HB_ContextSubstFormat2* csf2 ) |
-{ |
- HB_UShort n, count; |
- |
- HB_SubClassSet* scs; |
- |
- |
- if ( csf2->SubClassSet ) |
- { |
- count = csf2->SubClassSetCount; |
- scs = csf2->SubClassSet; |
- |
- for ( n = 0; n < count; n++ ) |
- Free_SubClassSet( &scs[n] ); |
- |
- FREE( scs ); |
- } |
- |
- _HB_OPEN_Free_ClassDefinition( &csf2->ClassDef ); |
- _HB_OPEN_Free_Coverage( &csf2->Coverage ); |
-} |
- |
- |
-/* ContextSubstFormat3 */ |
- |
-static HB_Error Load_ContextSubst3( HB_ContextSubstFormat3* csf3, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n = 0, m, count; |
- HB_UInt cur_offset, new_offset, base_offset; |
- |
- HB_Coverage* c; |
- HB_SubstLookupRecord* slr; |
- |
- |
- base_offset = FILE_Pos() - 2L; |
- |
- if ( ACCESS_Frame( 4L ) ) |
- return error; |
- |
- csf3->GlyphCount = GET_UShort(); |
- csf3->SubstCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- csf3->Coverage = NULL; |
- |
- count = csf3->GlyphCount; |
- |
- if ( ALLOC_ARRAY( csf3->Coverage, count, HB_Coverage ) ) |
- return error; |
- |
- c = csf3->Coverage; |
- |
- for ( n = 0; n < count; n++ ) |
- { |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail2; |
- |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = _HB_OPEN_Load_Coverage( &c[n], stream ) ) != HB_Err_Ok ) |
- goto Fail2; |
- (void)FILE_Seek( cur_offset ); |
- } |
- |
- csf3->SubstLookupRecord = NULL; |
- |
- count = csf3->SubstCount; |
- |
- if ( ALLOC_ARRAY( csf3->SubstLookupRecord, count, |
- HB_SubstLookupRecord ) ) |
- goto Fail2; |
- |
- slr = csf3->SubstLookupRecord; |
- |
- if ( ACCESS_Frame( count * 4L ) ) |
- goto Fail1; |
- |
- for ( n = 0; n < count; n++ ) |
- { |
- slr[n].SequenceIndex = GET_UShort(); |
- slr[n].LookupListIndex = GET_UShort(); |
- } |
- |
- FORGET_Frame(); |
- |
- return HB_Err_Ok; |
- |
-Fail1: |
- FREE( slr ); |
- |
-Fail2: |
- for ( m = 0; m < n; m++ ) |
- _HB_OPEN_Free_Coverage( &c[m] ); |
- |
- FREE( c ); |
- return error; |
-} |
- |
- |
-static void Free_ContextSubst3( HB_ContextSubstFormat3* csf3 ) |
-{ |
- HB_UShort n, count; |
- |
- HB_Coverage* c; |
- |
- |
- FREE( csf3->SubstLookupRecord ); |
- |
- if ( csf3->Coverage ) |
- { |
- count = csf3->GlyphCount; |
- c = csf3->Coverage; |
- |
- for ( n = 0; n < count; n++ ) |
- _HB_OPEN_Free_Coverage( &c[n] ); |
- |
- FREE( c ); |
- } |
-} |
- |
- |
-/* ContextSubst */ |
- |
-static HB_Error Load_ContextSubst( HB_GSUB_SubTable* st, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- HB_ContextSubst* cs = &st->context; |
- |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- cs->SubstFormat = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- switch ( cs->SubstFormat ) |
- { |
- case 1: return Load_ContextSubst1( &cs->csf.csf1, stream ); |
- case 2: return Load_ContextSubst2( &cs->csf.csf2, stream ); |
- case 3: return Load_ContextSubst3( &cs->csf.csf3, stream ); |
- default: return ERR(HB_Err_Invalid_SubTable_Format); |
- } |
- |
- return HB_Err_Ok; /* never reached */ |
-} |
- |
- |
-static void Free_ContextSubst( HB_GSUB_SubTable* st ) |
-{ |
- HB_ContextSubst* cs = &st->context; |
- |
- switch ( cs->SubstFormat ) |
- { |
- case 1: Free_ContextSubst1( &cs->csf.csf1 ); break; |
- case 2: Free_ContextSubst2( &cs->csf.csf2 ); break; |
- case 3: Free_ContextSubst3( &cs->csf.csf3 ); break; |
- default: break; |
- } |
-} |
- |
- |
-static HB_Error Lookup_ContextSubst1( HB_GSUBHeader* gsub, |
- HB_ContextSubstFormat1* csf1, |
- HB_Buffer buffer, |
- HB_UShort flags, |
- HB_UShort context_length, |
- int nesting_level ) |
-{ |
- HB_UShort index, property; |
- HB_UShort i, j, k, numsr; |
- HB_Error error; |
- |
- HB_SubRule* sr; |
- HB_GDEFHeader* gdef; |
- |
- |
- gdef = gsub->gdef; |
- |
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) |
- return error; |
- |
- error = _HB_OPEN_Coverage_Index( &csf1->Coverage, IN_CURGLYPH(), &index ); |
- if ( error ) |
- return error; |
- |
- sr = csf1->SubRuleSet[index].SubRule; |
- numsr = csf1->SubRuleSet[index].SubRuleCount; |
- |
- for ( k = 0; k < numsr; k++ ) |
- { |
- if ( context_length != 0xFFFF && context_length < sr[k].GlyphCount ) |
- goto next_subrule; |
- |
- if ( buffer->in_pos + sr[k].GlyphCount > buffer->in_length ) |
- goto next_subrule; /* context is too long */ |
- |
- for ( i = 1, j = buffer->in_pos + 1; i < sr[k].GlyphCount; i++, j++ ) |
- { |
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) ) |
- { |
- if ( error && error != HB_Err_Not_Covered ) |
- return error; |
- |
- if ( j + sr[k].GlyphCount - i == (HB_Int)buffer->in_length ) |
- goto next_subrule; |
- j++; |
- } |
- |
- if ( IN_GLYPH( j ) != sr[k].Input[i - 1] ) |
- goto next_subrule; |
- } |
- |
- return Do_ContextSubst( gsub, sr[k].GlyphCount, |
- sr[k].SubstCount, sr[k].SubstLookupRecord, |
- buffer, |
- nesting_level ); |
- next_subrule: |
- ; |
- } |
- |
- return HB_Err_Not_Covered; |
-} |
- |
- |
-static HB_Error Lookup_ContextSubst2( HB_GSUBHeader* gsub, |
- HB_ContextSubstFormat2* csf2, |
- HB_Buffer buffer, |
- HB_UShort flags, |
- HB_UShort context_length, |
- int nesting_level ) |
-{ |
- HB_UShort index, property; |
- HB_Error error; |
- HB_UShort i, j, k, known_classes; |
- |
- HB_UShort* classes; |
- HB_UShort* cl; |
- |
- HB_SubClassSet* scs; |
- HB_SubClassRule* sr; |
- HB_GDEFHeader* gdef; |
- |
- |
- gdef = gsub->gdef; |
- |
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) |
- return error; |
- |
- /* Note: The coverage table in format 2 doesn't give an index into |
- anything. It just lets us know whether or not we need to |
- do any lookup at all. */ |
- |
- error = _HB_OPEN_Coverage_Index( &csf2->Coverage, IN_CURGLYPH(), &index ); |
- if ( error ) |
- return error; |
- |
- if (csf2->MaxContextLength < 1) |
- return HB_Err_Not_Covered; |
- |
- if ( ALLOC_ARRAY( classes, csf2->MaxContextLength, HB_UShort ) ) |
- return error; |
- |
- error = _HB_OPEN_Get_Class( &csf2->ClassDef, IN_CURGLYPH(), |
- &classes[0], NULL ); |
- if ( error && error != HB_Err_Not_Covered ) |
- goto End; |
- known_classes = 0; |
- |
- scs = &csf2->SubClassSet[classes[0]]; |
- if ( !scs ) |
- { |
- error = ERR(HB_Err_Invalid_SubTable); |
- goto End; |
- } |
- |
- for ( k = 0; k < scs->SubClassRuleCount; k++ ) |
- { |
- sr = &scs->SubClassRule[k]; |
- |
- if ( context_length != 0xFFFF && context_length < sr->GlyphCount ) |
- goto next_subclassrule; |
- |
- if ( buffer->in_pos + sr->GlyphCount > buffer->in_length ) |
- goto next_subclassrule; /* context is too long */ |
- |
- cl = sr->Class; |
- |
- /* Start at 1 because [0] is implied */ |
- |
- for ( i = 1, j = buffer->in_pos + 1; i < sr->GlyphCount; i++, j++ ) |
- { |
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) ) |
- { |
- if ( error && error != HB_Err_Not_Covered ) |
- goto End; |
- |
- if ( j + sr->GlyphCount - i < (HB_Int)buffer->in_length ) |
- goto next_subclassrule; |
- j++; |
- } |
- |
- if ( i > known_classes ) |
- { |
- /* Keeps us from having to do this for each rule */ |
- |
- error = _HB_OPEN_Get_Class( &csf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL ); |
- if ( error && error != HB_Err_Not_Covered ) |
- goto End; |
- known_classes = i; |
- } |
- |
- if ( cl[i - 1] != classes[i] ) |
- goto next_subclassrule; |
- } |
- |
- error = Do_ContextSubst( gsub, sr->GlyphCount, |
- sr->SubstCount, sr->SubstLookupRecord, |
- buffer, |
- nesting_level ); |
- goto End; |
- |
- next_subclassrule: |
- ; |
- } |
- |
- error = HB_Err_Not_Covered; |
- |
-End: |
- FREE( classes ); |
- return error; |
-} |
- |
- |
-static HB_Error Lookup_ContextSubst3( HB_GSUBHeader* gsub, |
- HB_ContextSubstFormat3* csf3, |
- HB_Buffer buffer, |
- HB_UShort flags, |
- HB_UShort context_length, |
- int nesting_level ) |
-{ |
- HB_Error error; |
- HB_UShort index, i, j, property; |
- |
- HB_Coverage* c; |
- HB_GDEFHeader* gdef; |
- |
- |
- gdef = gsub->gdef; |
- |
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) |
- return error; |
- |
- if ( context_length != 0xFFFF && context_length < csf3->GlyphCount ) |
- return HB_Err_Not_Covered; |
- |
- if ( buffer->in_pos + csf3->GlyphCount > buffer->in_length ) |
- return HB_Err_Not_Covered; /* context is too long */ |
- |
- c = csf3->Coverage; |
- |
- for ( i = 1, j = buffer->in_pos + 1; i < csf3->GlyphCount; i++, j++ ) |
- { |
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) ) |
- { |
- if ( error && error != HB_Err_Not_Covered ) |
- return error; |
- |
- if ( j + csf3->GlyphCount - i == (HB_Int)buffer->in_length ) |
- return HB_Err_Not_Covered; |
- j++; |
- } |
- |
- error = _HB_OPEN_Coverage_Index( &c[i], IN_GLYPH( j ), &index ); |
- if ( error ) |
- return error; |
- } |
- |
- return Do_ContextSubst( gsub, csf3->GlyphCount, |
- csf3->SubstCount, csf3->SubstLookupRecord, |
- buffer, |
- nesting_level ); |
-} |
- |
- |
-static HB_Error Lookup_ContextSubst( HB_GSUBHeader* gsub, |
- HB_GSUB_SubTable* st, |
- HB_Buffer buffer, |
- HB_UShort flags, |
- HB_UShort context_length, |
- int nesting_level ) |
-{ |
- HB_ContextSubst* cs = &st->context; |
- |
- switch ( cs->SubstFormat ) |
- { |
- case 1: return Lookup_ContextSubst1( gsub, &cs->csf.csf1, buffer, flags, context_length, nesting_level ); |
- case 2: return Lookup_ContextSubst2( gsub, &cs->csf.csf2, buffer, flags, context_length, nesting_level ); |
- case 3: return Lookup_ContextSubst3( gsub, &cs->csf.csf3, buffer, flags, context_length, nesting_level ); |
- default: return ERR(HB_Err_Invalid_SubTable_Format); |
- } |
- |
- return HB_Err_Ok; /* never reached */ |
-} |
- |
- |
-/* LookupType 6 */ |
- |
-/* ChainSubRule */ |
- |
-static HB_Error Load_ChainSubRule( HB_ChainSubRule* csr, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n, count; |
- HB_UShort* b; |
- HB_UShort* i; |
- HB_UShort* l; |
- |
- HB_SubstLookupRecord* slr; |
- |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- csr->BacktrackGlyphCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- csr->Backtrack = NULL; |
- |
- count = csr->BacktrackGlyphCount; |
- |
- if ( ALLOC_ARRAY( csr->Backtrack, count, HB_UShort ) ) |
- return error; |
- |
- b = csr->Backtrack; |
- |
- if ( ACCESS_Frame( count * 2L ) ) |
- goto Fail4; |
- |
- for ( n = 0; n < count; n++ ) |
- b[n] = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail4; |
- |
- csr->InputGlyphCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- csr->Input = NULL; |
- |
- count = csr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */ |
- |
- if ( ALLOC_ARRAY( csr->Input, count, HB_UShort ) ) |
- goto Fail4; |
- |
- i = csr->Input; |
- |
- if ( ACCESS_Frame( count * 2L ) ) |
- goto Fail3; |
- |
- for ( n = 0; n < count; n++ ) |
- i[n] = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail3; |
- |
- csr->LookaheadGlyphCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- csr->Lookahead = NULL; |
- |
- count = csr->LookaheadGlyphCount; |
- |
- if ( ALLOC_ARRAY( csr->Lookahead, count, HB_UShort ) ) |
- goto Fail3; |
- |
- l = csr->Lookahead; |
- |
- if ( ACCESS_Frame( count * 2L ) ) |
- goto Fail2; |
- |
- for ( n = 0; n < count; n++ ) |
- l[n] = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail2; |
- |
- csr->SubstCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- csr->SubstLookupRecord = NULL; |
- |
- count = csr->SubstCount; |
- |
- if ( ALLOC_ARRAY( csr->SubstLookupRecord, count, HB_SubstLookupRecord ) ) |
- goto Fail2; |
- |
- slr = csr->SubstLookupRecord; |
- |
- if ( ACCESS_Frame( count * 4L ) ) |
- goto Fail1; |
- |
- for ( n = 0; n < count; n++ ) |
- { |
- slr[n].SequenceIndex = GET_UShort(); |
- slr[n].LookupListIndex = GET_UShort(); |
- } |
- |
- FORGET_Frame(); |
- |
- return HB_Err_Ok; |
- |
-Fail1: |
- FREE( slr ); |
- |
-Fail2: |
- FREE( l ); |
- |
-Fail3: |
- FREE( i ); |
- |
-Fail4: |
- FREE( b ); |
- return error; |
-} |
- |
- |
-static void Free_ChainSubRule( HB_ChainSubRule* csr ) |
-{ |
- FREE( csr->SubstLookupRecord ); |
- FREE( csr->Lookahead ); |
- FREE( csr->Input ); |
- FREE( csr->Backtrack ); |
-} |
- |
- |
-/* ChainSubRuleSet */ |
- |
-static HB_Error Load_ChainSubRuleSet( HB_ChainSubRuleSet* csrs, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n = 0, m, count; |
- HB_UInt cur_offset, new_offset, base_offset; |
- |
- HB_ChainSubRule* csr; |
- |
- |
- base_offset = FILE_Pos(); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- count = csrs->ChainSubRuleCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- csrs->ChainSubRule = NULL; |
- |
- if ( ALLOC_ARRAY( csrs->ChainSubRule, count, HB_ChainSubRule ) ) |
- return error; |
- |
- csr = csrs->ChainSubRule; |
- |
- 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 ( FILE_Seek( new_offset ) || |
- ( error = Load_ChainSubRule( &csr[n], stream ) ) != HB_Err_Ok ) |
- goto Fail; |
- (void)FILE_Seek( cur_offset ); |
- } |
- |
- return HB_Err_Ok; |
- |
-Fail: |
- for ( m = 0; m < n; m++ ) |
- Free_ChainSubRule( &csr[m] ); |
- |
- FREE( csr ); |
- return error; |
-} |
- |
- |
-static void Free_ChainSubRuleSet( HB_ChainSubRuleSet* csrs ) |
-{ |
- HB_UShort n, count; |
- |
- HB_ChainSubRule* csr; |
- |
- |
- if ( csrs->ChainSubRule ) |
- { |
- count = csrs->ChainSubRuleCount; |
- csr = csrs->ChainSubRule; |
- |
- for ( n = 0; n < count; n++ ) |
- Free_ChainSubRule( &csr[n] ); |
- |
- FREE( csr ); |
- } |
-} |
- |
- |
-/* ChainContextSubstFormat1 */ |
- |
-static HB_Error Load_ChainContextSubst1( |
- HB_ChainContextSubstFormat1* ccsf1, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n = 0, m, count; |
- HB_UInt cur_offset, new_offset, base_offset; |
- |
- HB_ChainSubRuleSet* csrs; |
- |
- |
- base_offset = FILE_Pos() - 2L; |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = _HB_OPEN_Load_Coverage( &ccsf1->Coverage, stream ) ) != HB_Err_Ok ) |
- return error; |
- (void)FILE_Seek( cur_offset ); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail2; |
- |
- count = ccsf1->ChainSubRuleSetCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- ccsf1->ChainSubRuleSet = NULL; |
- |
- if ( ALLOC_ARRAY( ccsf1->ChainSubRuleSet, count, HB_ChainSubRuleSet ) ) |
- goto Fail2; |
- |
- csrs = ccsf1->ChainSubRuleSet; |
- |
- 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_ChainSubRuleSet( &csrs[n], stream ) ) != HB_Err_Ok ) |
- goto Fail1; |
- (void)FILE_Seek( cur_offset ); |
- } |
- |
- return HB_Err_Ok; |
- |
-Fail1: |
- for ( m = 0; m < n; m++ ) |
- Free_ChainSubRuleSet( &csrs[m] ); |
- |
- FREE( csrs ); |
- |
-Fail2: |
- _HB_OPEN_Free_Coverage( &ccsf1->Coverage ); |
- return error; |
-} |
- |
- |
-static void Free_ChainContextSubst1( HB_ChainContextSubstFormat1* ccsf1 ) |
-{ |
- HB_UShort n, count; |
- |
- HB_ChainSubRuleSet* csrs; |
- |
- |
- if ( ccsf1->ChainSubRuleSet ) |
- { |
- count = ccsf1->ChainSubRuleSetCount; |
- csrs = ccsf1->ChainSubRuleSet; |
- |
- for ( n = 0; n < count; n++ ) |
- Free_ChainSubRuleSet( &csrs[n] ); |
- |
- FREE( csrs ); |
- } |
- |
- _HB_OPEN_Free_Coverage( &ccsf1->Coverage ); |
-} |
- |
- |
-/* ChainSubClassRule */ |
- |
-static HB_Error Load_ChainSubClassRule( |
- HB_ChainContextSubstFormat2* ccsf2, |
- HB_ChainSubClassRule* cscr, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n, count; |
- |
- HB_UShort* b; |
- HB_UShort* i; |
- HB_UShort* l; |
- HB_SubstLookupRecord* slr; |
- |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- cscr->BacktrackGlyphCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- if ( cscr->BacktrackGlyphCount > ccsf2->MaxBacktrackLength ) |
- ccsf2->MaxBacktrackLength = cscr->BacktrackGlyphCount; |
- |
- cscr->Backtrack = NULL; |
- |
- count = cscr->BacktrackGlyphCount; |
- |
- if ( ALLOC_ARRAY( cscr->Backtrack, count, HB_UShort ) ) |
- return error; |
- |
- b = cscr->Backtrack; |
- |
- if ( ACCESS_Frame( count * 2L ) ) |
- goto Fail4; |
- |
- for ( n = 0; n < count; n++ ) |
- b[n] = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail4; |
- |
- cscr->InputGlyphCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- if ( cscr->InputGlyphCount > ccsf2->MaxInputLength ) |
- ccsf2->MaxInputLength = cscr->InputGlyphCount; |
- |
- cscr->Input = NULL; |
- |
- count = cscr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */ |
- |
- if ( ALLOC_ARRAY( cscr->Input, count, HB_UShort ) ) |
- goto Fail4; |
- |
- i = cscr->Input; |
- |
- if ( ACCESS_Frame( count * 2L ) ) |
- goto Fail3; |
- |
- for ( n = 0; n < count; n++ ) |
- i[n] = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail3; |
- |
- cscr->LookaheadGlyphCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- if ( cscr->LookaheadGlyphCount > ccsf2->MaxLookaheadLength ) |
- ccsf2->MaxLookaheadLength = cscr->LookaheadGlyphCount; |
- |
- cscr->Lookahead = NULL; |
- |
- count = cscr->LookaheadGlyphCount; |
- |
- if ( ALLOC_ARRAY( cscr->Lookahead, count, HB_UShort ) ) |
- goto Fail3; |
- |
- l = cscr->Lookahead; |
- |
- if ( ACCESS_Frame( count * 2L ) ) |
- goto Fail2; |
- |
- for ( n = 0; n < count; n++ ) |
- l[n] = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail2; |
- |
- cscr->SubstCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- cscr->SubstLookupRecord = NULL; |
- |
- count = cscr->SubstCount; |
- |
- if ( ALLOC_ARRAY( cscr->SubstLookupRecord, count, |
- HB_SubstLookupRecord ) ) |
- goto Fail2; |
- |
- slr = cscr->SubstLookupRecord; |
- |
- if ( ACCESS_Frame( count * 4L ) ) |
- goto Fail1; |
- |
- for ( n = 0; n < count; n++ ) |
- { |
- slr[n].SequenceIndex = GET_UShort(); |
- slr[n].LookupListIndex = GET_UShort(); |
- } |
- |
- FORGET_Frame(); |
- |
- return HB_Err_Ok; |
- |
-Fail1: |
- FREE( slr ); |
- |
-Fail2: |
- FREE( l ); |
- |
-Fail3: |
- FREE( i ); |
- |
-Fail4: |
- FREE( b ); |
- return error; |
-} |
- |
- |
-static void Free_ChainSubClassRule( HB_ChainSubClassRule* cscr ) |
-{ |
- FREE( cscr->SubstLookupRecord ); |
- FREE( cscr->Lookahead ); |
- FREE( cscr->Input ); |
- FREE( cscr->Backtrack ); |
-} |
- |
- |
-/* SubClassSet */ |
- |
-static HB_Error Load_ChainSubClassSet( |
- HB_ChainContextSubstFormat2* ccsf2, |
- HB_ChainSubClassSet* cscs, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n = 0, m, count; |
- HB_UInt cur_offset, new_offset, base_offset; |
- |
- HB_ChainSubClassRule* cscr; |
- |
- |
- base_offset = FILE_Pos(); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- count = cscs->ChainSubClassRuleCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- cscs->ChainSubClassRule = NULL; |
- |
- if ( ALLOC_ARRAY( cscs->ChainSubClassRule, count, |
- HB_ChainSubClassRule ) ) |
- return error; |
- |
- cscr = cscs->ChainSubClassRule; |
- |
- 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 ( FILE_Seek( new_offset ) || |
- ( error = Load_ChainSubClassRule( ccsf2, &cscr[n], |
- stream ) ) != HB_Err_Ok ) |
- goto Fail; |
- (void)FILE_Seek( cur_offset ); |
- } |
- |
- return HB_Err_Ok; |
- |
-Fail: |
- for ( m = 0; m < n; m++ ) |
- Free_ChainSubClassRule( &cscr[m] ); |
- |
- FREE( cscr ); |
- return error; |
-} |
- |
- |
-static void Free_ChainSubClassSet( HB_ChainSubClassSet* cscs ) |
-{ |
- HB_UShort n, count; |
- |
- HB_ChainSubClassRule* cscr; |
- |
- |
- if ( cscs->ChainSubClassRule ) |
- { |
- count = cscs->ChainSubClassRuleCount; |
- cscr = cscs->ChainSubClassRule; |
- |
- for ( n = 0; n < count; n++ ) |
- Free_ChainSubClassRule( &cscr[n] ); |
- |
- FREE( cscr ); |
- } |
-} |
- |
- |
-/* ChainContextSubstFormat2 */ |
- |
-static HB_Error Load_ChainContextSubst2( |
- HB_ChainContextSubstFormat2* ccsf2, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n = 0, m, count; |
- HB_UInt cur_offset, new_offset, base_offset; |
- HB_UInt backtrack_offset, input_offset, lookahead_offset; |
- |
- HB_ChainSubClassSet* cscs; |
- |
- |
- base_offset = FILE_Pos() - 2; |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = _HB_OPEN_Load_Coverage( &ccsf2->Coverage, stream ) ) != HB_Err_Ok ) |
- return error; |
- (void)FILE_Seek( cur_offset ); |
- |
- if ( ACCESS_Frame( 8L ) ) |
- goto Fail5; |
- |
- backtrack_offset = GET_UShort(); |
- input_offset = GET_UShort(); |
- lookahead_offset = GET_UShort(); |
- |
- /* `ChainSubClassSetCount' is the upper limit for input class values, |
- thus we read it now to make an additional safety check. No limit |
- is known or needed for the other two class definitions */ |
- |
- count = ccsf2->ChainSubClassSetCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->BacktrackClassDef, 65535, |
- backtrack_offset, base_offset, |
- stream ) ) != HB_Err_Ok ) |
- goto Fail5; |
- |
- if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->InputClassDef, count, |
- input_offset, base_offset, |
- stream ) ) != HB_Err_Ok ) |
- goto Fail4; |
- if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->LookaheadClassDef, 65535, |
- lookahead_offset, base_offset, |
- stream ) ) != HB_Err_Ok ) |
- goto Fail3; |
- |
- ccsf2->ChainSubClassSet = NULL; |
- ccsf2->MaxBacktrackLength = 0; |
- ccsf2->MaxInputLength = 0; |
- ccsf2->MaxLookaheadLength = 0; |
- |
- if ( ALLOC_ARRAY( ccsf2->ChainSubClassSet, count, HB_ChainSubClassSet ) ) |
- goto Fail2; |
- |
- cscs = ccsf2->ChainSubClassSet; |
- |
- for ( n = 0; n < count; n++ ) |
- { |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail1; |
- |
- 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_ChainSubClassSet( ccsf2, &cscs[n], |
- stream ) ) != HB_Err_Ok ) |
- goto Fail1; |
- (void)FILE_Seek( cur_offset ); |
- } |
- else |
- { |
- /* we create a ChainSubClassSet table with no entries */ |
- |
- ccsf2->ChainSubClassSet[n].ChainSubClassRuleCount = 0; |
- ccsf2->ChainSubClassSet[n].ChainSubClassRule = NULL; |
- } |
- } |
- |
- return HB_Err_Ok; |
- |
-Fail1: |
- for ( m = 0; m < n; m++ ) |
- Free_ChainSubClassSet( &cscs[m] ); |
- |
- FREE( cscs ); |
- |
-Fail2: |
- _HB_OPEN_Free_ClassDefinition( &ccsf2->LookaheadClassDef ); |
- |
-Fail3: |
- _HB_OPEN_Free_ClassDefinition( &ccsf2->InputClassDef ); |
- |
-Fail4: |
- _HB_OPEN_Free_ClassDefinition( &ccsf2->BacktrackClassDef ); |
- |
-Fail5: |
- _HB_OPEN_Free_Coverage( &ccsf2->Coverage ); |
- return error; |
-} |
- |
- |
-static void Free_ChainContextSubst2( HB_ChainContextSubstFormat2* ccsf2 ) |
-{ |
- HB_UShort n, count; |
- |
- HB_ChainSubClassSet* cscs; |
- |
- |
- if ( ccsf2->ChainSubClassSet ) |
- { |
- count = ccsf2->ChainSubClassSetCount; |
- cscs = ccsf2->ChainSubClassSet; |
- |
- for ( n = 0; n < count; n++ ) |
- Free_ChainSubClassSet( &cscs[n] ); |
- |
- FREE( cscs ); |
- } |
- |
- _HB_OPEN_Free_ClassDefinition( &ccsf2->LookaheadClassDef ); |
- _HB_OPEN_Free_ClassDefinition( &ccsf2->InputClassDef ); |
- _HB_OPEN_Free_ClassDefinition( &ccsf2->BacktrackClassDef ); |
- |
- _HB_OPEN_Free_Coverage( &ccsf2->Coverage ); |
-} |
- |
- |
-/* ChainContextSubstFormat3 */ |
- |
-static HB_Error Load_ChainContextSubst3( |
- HB_ChainContextSubstFormat3* ccsf3, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- |
- HB_UShort n, nb = 0, ni =0, nl = 0, m, count; |
- HB_UShort backtrack_count, input_count, lookahead_count; |
- HB_UInt cur_offset, new_offset, base_offset; |
- |
- HB_Coverage* b; |
- HB_Coverage* i; |
- HB_Coverage* l; |
- HB_SubstLookupRecord* slr; |
- |
- |
- base_offset = FILE_Pos() - 2L; |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- ccsf3->BacktrackGlyphCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- ccsf3->BacktrackCoverage = NULL; |
- |
- backtrack_count = ccsf3->BacktrackGlyphCount; |
- |
- if ( ALLOC_ARRAY( ccsf3->BacktrackCoverage, backtrack_count, |
- HB_Coverage ) ) |
- return error; |
- |
- b = ccsf3->BacktrackCoverage; |
- |
- for ( nb = 0; nb < backtrack_count; nb++ ) |
- { |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail4; |
- |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != HB_Err_Ok ) |
- goto Fail4; |
- (void)FILE_Seek( cur_offset ); |
- } |
- |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail4; |
- |
- ccsf3->InputGlyphCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- ccsf3->InputCoverage = NULL; |
- |
- input_count = ccsf3->InputGlyphCount; |
- |
- if ( ALLOC_ARRAY( ccsf3->InputCoverage, input_count, HB_Coverage ) ) |
- goto Fail4; |
- |
- i = ccsf3->InputCoverage; |
- |
- for ( ni = 0; ni < input_count; ni++ ) |
- { |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail3; |
- |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = _HB_OPEN_Load_Coverage( &i[ni], stream ) ) != HB_Err_Ok ) |
- goto Fail3; |
- (void)FILE_Seek( cur_offset ); |
- } |
- |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail3; |
- |
- ccsf3->LookaheadGlyphCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- ccsf3->LookaheadCoverage = NULL; |
- |
- lookahead_count = ccsf3->LookaheadGlyphCount; |
- |
- if ( ALLOC_ARRAY( ccsf3->LookaheadCoverage, lookahead_count, |
- HB_Coverage ) ) |
- goto Fail3; |
- |
- l = ccsf3->LookaheadCoverage; |
- |
- for ( nl = 0; nl < lookahead_count; nl++ ) |
- { |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail2; |
- |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != HB_Err_Ok ) |
- goto Fail2; |
- (void)FILE_Seek( cur_offset ); |
- } |
- |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail2; |
- |
- ccsf3->SubstCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- ccsf3->SubstLookupRecord = NULL; |
- |
- count = ccsf3->SubstCount; |
- |
- if ( ALLOC_ARRAY( ccsf3->SubstLookupRecord, count, |
- HB_SubstLookupRecord ) ) |
- goto Fail2; |
- |
- slr = ccsf3->SubstLookupRecord; |
- |
- if ( ACCESS_Frame( count * 4L ) ) |
- goto Fail1; |
- |
- for ( n = 0; n < count; n++ ) |
- { |
- slr[n].SequenceIndex = GET_UShort(); |
- slr[n].LookupListIndex = GET_UShort(); |
- } |
- |
- FORGET_Frame(); |
- |
- return HB_Err_Ok; |
- |
-Fail1: |
- FREE( slr ); |
- |
-Fail2: |
- for ( m = 0; m < nl; m++ ) |
- _HB_OPEN_Free_Coverage( &l[m] ); |
- |
- FREE( l ); |
- |
-Fail3: |
- for ( m = 0; m < ni; m++ ) |
- _HB_OPEN_Free_Coverage( &i[m] ); |
- |
- FREE( i ); |
- |
-Fail4: |
- for ( m = 0; m < nb; m++ ) |
- _HB_OPEN_Free_Coverage( &b[m] ); |
- |
- FREE( b ); |
- return error; |
-} |
- |
- |
-static void Free_ChainContextSubst3( HB_ChainContextSubstFormat3* ccsf3 ) |
-{ |
- HB_UShort n, count; |
- |
- HB_Coverage* c; |
- |
- |
- FREE( ccsf3->SubstLookupRecord ); |
- |
- if ( ccsf3->LookaheadCoverage ) |
- { |
- count = ccsf3->LookaheadGlyphCount; |
- c = ccsf3->LookaheadCoverage; |
- |
- for ( n = 0; n < count; n++ ) |
- _HB_OPEN_Free_Coverage( &c[n] ); |
- |
- FREE( c ); |
- } |
- |
- if ( ccsf3->InputCoverage ) |
- { |
- count = ccsf3->InputGlyphCount; |
- c = ccsf3->InputCoverage; |
- |
- for ( n = 0; n < count; n++ ) |
- _HB_OPEN_Free_Coverage( &c[n] ); |
- |
- FREE( c ); |
- } |
- |
- if ( ccsf3->BacktrackCoverage ) |
- { |
- count = ccsf3->BacktrackGlyphCount; |
- c = ccsf3->BacktrackCoverage; |
- |
- for ( n = 0; n < count; n++ ) |
- _HB_OPEN_Free_Coverage( &c[n] ); |
- |
- FREE( c ); |
- } |
-} |
- |
- |
-/* ChainContextSubst */ |
- |
-static HB_Error Load_ChainContextSubst( HB_GSUB_SubTable* st, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- HB_ChainContextSubst* ccs = &st->chain; |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- ccs->SubstFormat = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- switch ( ccs->SubstFormat ) { |
- case 1: return Load_ChainContextSubst1( &ccs->ccsf.ccsf1, stream ); |
- case 2: return Load_ChainContextSubst2( &ccs->ccsf.ccsf2, stream ); |
- case 3: return Load_ChainContextSubst3( &ccs->ccsf.ccsf3, stream ); |
- default: return ERR(HB_Err_Invalid_SubTable_Format); |
- } |
- |
- return HB_Err_Ok; /* never reached */ |
-} |
- |
- |
-static void Free_ChainContextSubst( HB_GSUB_SubTable* st ) |
-{ |
- HB_ChainContextSubst* ccs = &st->chain; |
- |
- switch ( ccs->SubstFormat ) { |
- case 1: Free_ChainContextSubst1( &ccs->ccsf.ccsf1 ); break; |
- case 2: Free_ChainContextSubst2( &ccs->ccsf.ccsf2 ); break; |
- case 3: Free_ChainContextSubst3( &ccs->ccsf.ccsf3 ); break; |
- default: break; |
- } |
-} |
- |
- |
-static HB_Error Lookup_ChainContextSubst1( HB_GSUBHeader* gsub, |
- HB_ChainContextSubstFormat1* ccsf1, |
- HB_Buffer buffer, |
- HB_UShort flags, |
- HB_UShort context_length, |
- int nesting_level ) |
-{ |
- HB_UShort index, property; |
- HB_UShort i, j, k, num_csr; |
- HB_UShort bgc, igc, lgc; |
- HB_Error error; |
- |
- HB_ChainSubRule* csr; |
- HB_ChainSubRule curr_csr; |
- HB_GDEFHeader* gdef; |
- |
- |
- gdef = gsub->gdef; |
- |
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) |
- return error; |
- |
- error = _HB_OPEN_Coverage_Index( &ccsf1->Coverage, IN_CURGLYPH(), &index ); |
- if ( error ) |
- return error; |
- |
- csr = ccsf1->ChainSubRuleSet[index].ChainSubRule; |
- num_csr = ccsf1->ChainSubRuleSet[index].ChainSubRuleCount; |
- |
- for ( k = 0; k < num_csr; k++ ) |
- { |
- curr_csr = csr[k]; |
- bgc = curr_csr.BacktrackGlyphCount; |
- igc = curr_csr.InputGlyphCount; |
- lgc = curr_csr.LookaheadGlyphCount; |
- |
- if ( context_length != 0xFFFF && context_length < igc ) |
- goto next_chainsubrule; |
- |
- /* check whether context is too long; it is a first guess only */ |
- |
- if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length ) |
- goto next_chainsubrule; |
- |
- if ( bgc ) |
- { |
- /* since we don't know in advance the number of glyphs to inspect, |
- we search backwards for matches in the backtrack glyph array */ |
- |
- for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- ) |
- { |
- while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) ) |
- { |
- if ( error && error != HB_Err_Not_Covered ) |
- return error; |
- |
- if ( j + 1 == bgc - i ) |
- goto next_chainsubrule; |
- j--; |
- } |
- |
- /* In OpenType 1.3, it is undefined whether the offsets of |
- backtrack glyphs is in logical order or not. Version 1.4 |
- will clarify this: |
- |
- Logical order - a b c d e f g h i j |
- i |
- Input offsets - 0 1 |
- Backtrack offsets - 3 2 1 0 |
- Lookahead offsets - 0 1 2 3 */ |
- |
- if ( OUT_GLYPH( j ) != curr_csr.Backtrack[i] ) |
- goto next_chainsubrule; |
- } |
- } |
- |
- /* Start at 1 because [0] is implied */ |
- |
- for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ ) |
- { |
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) ) |
- { |
- if ( error && error != HB_Err_Not_Covered ) |
- return error; |
- |
- if ( j + igc - i + lgc == (HB_Int)buffer->in_length ) |
- goto next_chainsubrule; |
- j++; |
- } |
- |
- if ( IN_GLYPH( j ) != curr_csr.Input[i - 1] ) |
- goto next_chainsubrule; |
- } |
- |
- /* we are starting to check for lookahead glyphs right after the |
- last context glyph */ |
- |
- for ( i = 0; i < lgc; i++, j++ ) |
- { |
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) ) |
- { |
- if ( error && error != HB_Err_Not_Covered ) |
- return error; |
- |
- if ( j + lgc - i == (HB_Int)buffer->in_length ) |
- goto next_chainsubrule; |
- j++; |
- } |
- |
- if ( IN_GLYPH( j ) != curr_csr.Lookahead[i] ) |
- goto next_chainsubrule; |
- } |
- |
- return Do_ContextSubst( gsub, igc, |
- curr_csr.SubstCount, |
- curr_csr.SubstLookupRecord, |
- buffer, |
- nesting_level ); |
- |
- next_chainsubrule: |
- ; |
- } |
- |
- return HB_Err_Not_Covered; |
-} |
- |
- |
-static HB_Error Lookup_ChainContextSubst2( HB_GSUBHeader* gsub, |
- HB_ChainContextSubstFormat2* ccsf2, |
- HB_Buffer buffer, |
- HB_UShort flags, |
- HB_UShort context_length, |
- int nesting_level ) |
-{ |
- HB_UShort index, property; |
- HB_Error error; |
- HB_UShort i, j, k; |
- HB_UShort bgc, igc, lgc; |
- HB_UShort known_backtrack_classes, |
- known_input_classes, |
- known_lookahead_classes; |
- |
- HB_UShort* backtrack_classes; |
- HB_UShort* input_classes; |
- HB_UShort* lookahead_classes; |
- |
- HB_UShort* bc; |
- HB_UShort* ic; |
- HB_UShort* lc; |
- |
- HB_ChainSubClassSet* cscs; |
- HB_ChainSubClassRule ccsr; |
- HB_GDEFHeader* gdef; |
- |
- |
- gdef = gsub->gdef; |
- |
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) |
- return error; |
- |
- /* Note: The coverage table in format 2 doesn't give an index into |
- anything. It just lets us know whether or not we need to |
- do any lookup at all. */ |
- |
- error = _HB_OPEN_Coverage_Index( &ccsf2->Coverage, IN_CURGLYPH(), &index ); |
- if ( error ) |
- return error; |
- |
- if ( ALLOC_ARRAY( backtrack_classes, ccsf2->MaxBacktrackLength, HB_UShort ) ) |
- return error; |
- known_backtrack_classes = 0; |
- |
- if (ccsf2->MaxInputLength < 1) |
- return HB_Err_Not_Covered; |
- |
- if ( ALLOC_ARRAY( input_classes, ccsf2->MaxInputLength, HB_UShort ) ) |
- goto End3; |
- known_input_classes = 1; |
- |
- if ( ALLOC_ARRAY( lookahead_classes, ccsf2->MaxLookaheadLength, HB_UShort ) ) |
- goto End2; |
- known_lookahead_classes = 0; |
- |
- error = _HB_OPEN_Get_Class( &ccsf2->InputClassDef, IN_CURGLYPH(), |
- &input_classes[0], NULL ); |
- if ( error && error != HB_Err_Not_Covered ) |
- goto End1; |
- |
- cscs = &ccsf2->ChainSubClassSet[input_classes[0]]; |
- if ( !cscs ) |
- { |
- error = ERR(HB_Err_Invalid_SubTable); |
- goto End1; |
- } |
- |
- for ( k = 0; k < cscs->ChainSubClassRuleCount; k++ ) |
- { |
- ccsr = cscs->ChainSubClassRule[k]; |
- bgc = ccsr.BacktrackGlyphCount; |
- igc = ccsr.InputGlyphCount; |
- lgc = ccsr.LookaheadGlyphCount; |
- |
- if ( context_length != 0xFFFF && context_length < igc ) |
- goto next_chainsubclassrule; |
- |
- /* check whether context is too long; it is a first guess only */ |
- |
- if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length ) |
- goto next_chainsubclassrule; |
- |
- if ( bgc ) |
- { |
- /* Since we don't know in advance the number of glyphs to inspect, |
- we search backwards for matches in the backtrack glyph array. |
- Note that `known_backtrack_classes' starts at index 0. */ |
- |
- bc = ccsr.Backtrack; |
- |
- for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- ) |
- { |
- while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) ) |
- { |
- if ( error && error != HB_Err_Not_Covered ) |
- goto End1; |
- |
- if ( j + 1 == bgc - i ) |
- goto next_chainsubclassrule; |
- j--; |
- } |
- |
- if ( i >= known_backtrack_classes ) |
- { |
- /* Keeps us from having to do this for each rule */ |
- |
- error = _HB_OPEN_Get_Class( &ccsf2->BacktrackClassDef, OUT_GLYPH( j ), |
- &backtrack_classes[i], NULL ); |
- if ( error && error != HB_Err_Not_Covered ) |
- goto End1; |
- known_backtrack_classes = i; |
- } |
- |
- if ( bc[i] != backtrack_classes[i] ) |
- goto next_chainsubclassrule; |
- } |
- } |
- |
- ic = ccsr.Input; |
- |
- /* Start at 1 because [0] is implied */ |
- |
- for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ ) |
- { |
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) ) |
- { |
- if ( error && error != HB_Err_Not_Covered ) |
- goto End1; |
- |
- if ( j + igc - i + lgc == (HB_Int)buffer->in_length ) |
- goto next_chainsubclassrule; |
- j++; |
- } |
- |
- if ( i >= known_input_classes ) |
- { |
- error = _HB_OPEN_Get_Class( &ccsf2->InputClassDef, IN_GLYPH( j ), |
- &input_classes[i], NULL ); |
- if ( error && error != HB_Err_Not_Covered ) |
- goto End1; |
- known_input_classes = i; |
- } |
- |
- if ( ic[i - 1] != input_classes[i] ) |
- goto next_chainsubclassrule; |
- } |
- |
- /* we are starting to check for lookahead glyphs right after the |
- last context glyph */ |
- |
- lc = ccsr.Lookahead; |
- |
- for ( i = 0; i < lgc; i++, j++ ) |
- { |
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) ) |
- { |
- if ( error && error != HB_Err_Not_Covered ) |
- goto End1; |
- |
- if ( j + lgc - i == (HB_Int)buffer->in_length ) |
- goto next_chainsubclassrule; |
- j++; |
- } |
- |
- if ( i >= known_lookahead_classes ) |
- { |
- error = _HB_OPEN_Get_Class( &ccsf2->LookaheadClassDef, IN_GLYPH( j ), |
- &lookahead_classes[i], NULL ); |
- if ( error && error != HB_Err_Not_Covered ) |
- goto End1; |
- known_lookahead_classes = i; |
- } |
- |
- if ( lc[i] != lookahead_classes[i] ) |
- goto next_chainsubclassrule; |
- } |
- |
- error = Do_ContextSubst( gsub, igc, |
- ccsr.SubstCount, |
- ccsr.SubstLookupRecord, |
- buffer, |
- nesting_level ); |
- goto End1; |
- |
- next_chainsubclassrule: |
- ; |
- } |
- |
- error = HB_Err_Not_Covered; |
- |
-End1: |
- FREE( lookahead_classes ); |
- |
-End2: |
- FREE( input_classes ); |
- |
-End3: |
- FREE( backtrack_classes ); |
- return error; |
-} |
- |
- |
-static HB_Error Lookup_ChainContextSubst3( HB_GSUBHeader* gsub, |
- HB_ChainContextSubstFormat3* ccsf3, |
- HB_Buffer buffer, |
- HB_UShort flags, |
- HB_UShort context_length, |
- int nesting_level ) |
-{ |
- HB_UShort index, i, j, property; |
- HB_UShort bgc, igc, lgc; |
- HB_Error error; |
- |
- HB_Coverage* bc; |
- HB_Coverage* ic; |
- HB_Coverage* lc; |
- HB_GDEFHeader* gdef; |
- |
- |
- gdef = gsub->gdef; |
- |
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) |
- return error; |
- |
- bgc = ccsf3->BacktrackGlyphCount; |
- igc = ccsf3->InputGlyphCount; |
- lgc = ccsf3->LookaheadGlyphCount; |
- |
- if ( context_length != 0xFFFF && context_length < igc ) |
- return HB_Err_Not_Covered; |
- |
- /* check whether context is too long; it is a first guess only */ |
- |
- if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length ) |
- return HB_Err_Not_Covered; |
- |
- if ( bgc ) |
- { |
- /* Since we don't know in advance the number of glyphs to inspect, |
- we search backwards for matches in the backtrack glyph array */ |
- |
- bc = ccsf3->BacktrackCoverage; |
- |
- for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- ) |
- { |
- while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) ) |
- { |
- if ( error && error != HB_Err_Not_Covered ) |
- return error; |
- |
- if ( j + 1 == bgc - i ) |
- return HB_Err_Not_Covered; |
- j--; |
- } |
- |
- error = _HB_OPEN_Coverage_Index( &bc[i], OUT_GLYPH( j ), &index ); |
- if ( error ) |
- return error; |
- } |
- } |
- |
- ic = ccsf3->InputCoverage; |
- |
- for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ ) |
- { |
- /* We already called CHECK_Property for IN_GLYPH( buffer->in_pos ) */ |
- while ( j > buffer->in_pos && CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) ) |
- { |
- if ( error && error != HB_Err_Not_Covered ) |
- return error; |
- |
- if ( j + igc - i + lgc == (HB_Int)buffer->in_length ) |
- return HB_Err_Not_Covered; |
- j++; |
- } |
- |
- error = _HB_OPEN_Coverage_Index( &ic[i], IN_GLYPH( j ), &index ); |
- if ( error ) |
- return error; |
- } |
- |
- /* we are starting for lookahead glyphs right after the last context |
- glyph */ |
- |
- lc = ccsf3->LookaheadCoverage; |
- |
- for ( i = 0; i < lgc; i++, j++ ) |
- { |
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) ) |
- { |
- if ( error && error != HB_Err_Not_Covered ) |
- return error; |
- |
- if ( j + lgc - i == (HB_Int)buffer->in_length ) |
- return HB_Err_Not_Covered; |
- j++; |
- } |
- |
- error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index ); |
- if ( error ) |
- return error; |
- } |
- |
- return Do_ContextSubst( gsub, igc, |
- ccsf3->SubstCount, |
- ccsf3->SubstLookupRecord, |
- buffer, |
- nesting_level ); |
-} |
- |
- |
-static HB_Error Lookup_ChainContextSubst( HB_GSUBHeader* gsub, |
- HB_GSUB_SubTable* st, |
- HB_Buffer buffer, |
- HB_UShort flags, |
- HB_UShort context_length, |
- int nesting_level ) |
-{ |
- HB_ChainContextSubst* ccs = &st->chain; |
- |
- switch ( ccs->SubstFormat ) { |
- case 1: return Lookup_ChainContextSubst1( gsub, &ccs->ccsf.ccsf1, buffer, flags, context_length, nesting_level ); |
- case 2: return Lookup_ChainContextSubst2( gsub, &ccs->ccsf.ccsf2, buffer, flags, context_length, nesting_level ); |
- case 3: return Lookup_ChainContextSubst3( gsub, &ccs->ccsf.ccsf3, buffer, flags, context_length, nesting_level ); |
- default: return ERR(HB_Err_Invalid_SubTable_Format); |
- } |
-} |
- |
- |
-static HB_Error Load_ReverseChainContextSubst( HB_GSUB_SubTable* st, |
- HB_Stream stream ) |
-{ |
- HB_Error error; |
- HB_ReverseChainContextSubst* rccs = &st->reverse; |
- |
- HB_UShort m, count; |
- |
- HB_UShort nb = 0, nl = 0, n; |
- HB_UShort backtrack_count, lookahead_count; |
- HB_UInt cur_offset, new_offset, base_offset; |
- |
- HB_Coverage* b; |
- HB_Coverage* l; |
- HB_UShort* sub; |
- |
- base_offset = FILE_Pos(); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- rccs->SubstFormat = GET_UShort(); |
- |
- if ( rccs->SubstFormat != 1 ) |
- return ERR(HB_Err_Invalid_SubTable_Format); |
- |
- FORGET_Frame(); |
- |
- if ( ACCESS_Frame( 2L ) ) |
- return error; |
- |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = _HB_OPEN_Load_Coverage( &rccs->Coverage, stream ) ) != HB_Err_Ok ) |
- return error; |
- (void)FILE_Seek( cur_offset ); |
- |
- |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail4; |
- |
- rccs->BacktrackGlyphCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- rccs->BacktrackCoverage = NULL; |
- |
- backtrack_count = rccs->BacktrackGlyphCount; |
- |
- if ( ALLOC_ARRAY( rccs->BacktrackCoverage, backtrack_count, |
- HB_Coverage ) ) |
- goto Fail4; |
- |
- b = rccs->BacktrackCoverage; |
- |
- for ( nb = 0; nb < backtrack_count; nb++ ) |
- { |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail3; |
- |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != HB_Err_Ok ) |
- goto Fail3; |
- (void)FILE_Seek( cur_offset ); |
- } |
- |
- |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail3; |
- |
- rccs->LookaheadGlyphCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- rccs->LookaheadCoverage = NULL; |
- |
- lookahead_count = rccs->LookaheadGlyphCount; |
- |
- if ( ALLOC_ARRAY( rccs->LookaheadCoverage, lookahead_count, |
- HB_Coverage ) ) |
- goto Fail3; |
- |
- l = rccs->LookaheadCoverage; |
- |
- for ( nl = 0; nl < lookahead_count; nl++ ) |
- { |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail2; |
- |
- new_offset = GET_UShort() + base_offset; |
- |
- FORGET_Frame(); |
- |
- cur_offset = FILE_Pos(); |
- if ( FILE_Seek( new_offset ) || |
- ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != HB_Err_Ok ) |
- goto Fail2; |
- (void)FILE_Seek( cur_offset ); |
- } |
- |
- if ( ACCESS_Frame( 2L ) ) |
- goto Fail2; |
- |
- rccs->GlyphCount = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- rccs->Substitute = NULL; |
- |
- count = rccs->GlyphCount; |
- |
- if ( ALLOC_ARRAY( rccs->Substitute, count, |
- HB_UShort ) ) |
- goto Fail2; |
- |
- sub = rccs->Substitute; |
- |
- if ( ACCESS_Frame( count * 2L ) ) |
- goto Fail1; |
- |
- for ( n = 0; n < count; n++ ) |
- sub[n] = GET_UShort(); |
- |
- FORGET_Frame(); |
- |
- return HB_Err_Ok; |
- |
-Fail1: |
- FREE( sub ); |
- |
-Fail2: |
- for ( m = 0; m < nl; m++ ) |
- _HB_OPEN_Free_Coverage( &l[m] ); |
- |
- FREE( l ); |
- |
-Fail3: |
- for ( m = 0; m < nb; m++ ) |
- _HB_OPEN_Free_Coverage( &b[m] ); |
- |
- FREE( b ); |
- |
-Fail4: |
- _HB_OPEN_Free_Coverage( &rccs->Coverage ); |
- return error; |
-} |
- |
- |
-static void Free_ReverseChainContextSubst( HB_GSUB_SubTable* st ) |
-{ |
- HB_UShort n, count; |
- HB_ReverseChainContextSubst* rccs = &st->reverse; |
- |
- HB_Coverage* c; |
- |
- _HB_OPEN_Free_Coverage( &rccs->Coverage ); |
- |
- if ( rccs->LookaheadCoverage ) |
- { |
- count = rccs->LookaheadGlyphCount; |
- c = rccs->LookaheadCoverage; |
- |
- for ( n = 0; n < count; n++ ) |
- _HB_OPEN_Free_Coverage( &c[n] ); |
- |
- FREE( c ); |
- } |
- |
- if ( rccs->BacktrackCoverage ) |
- { |
- count = rccs->BacktrackGlyphCount; |
- c = rccs->BacktrackCoverage; |
- |
- for ( n = 0; n < count; n++ ) |
- _HB_OPEN_Free_Coverage( &c[n] ); |
- |
- FREE( c ); |
- } |
- |
- FREE ( rccs->Substitute ); |
-} |
- |
- |
-static HB_Error Lookup_ReverseChainContextSubst( HB_GSUBHeader* gsub, |
- HB_GSUB_SubTable* st, |
- HB_Buffer buffer, |
- HB_UShort flags, |
- HB_UShort context_length, |
- int nesting_level ) |
-{ |
- HB_UShort index, input_index, i, j, property; |
- HB_UShort bgc, lgc; |
- HB_Error error; |
- |
- HB_ReverseChainContextSubst* rccs = &st->reverse; |
- HB_Coverage* bc; |
- HB_Coverage* lc; |
- HB_GDEFHeader* gdef; |
- |
- if ( nesting_level != 1 || context_length != 0xFFFF ) |
- return HB_Err_Not_Covered; |
- |
- gdef = gsub->gdef; |
- |
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) |
- return error; |
- |
- bgc = rccs->BacktrackGlyphCount; |
- lgc = rccs->LookaheadGlyphCount; |
- |
- /* check whether context is too long; it is a first guess only */ |
- |
- if ( bgc > buffer->in_pos || buffer->in_pos + 1 + lgc > buffer->in_length ) |
- return HB_Err_Not_Covered; |
- |
- if ( bgc ) |
- { |
- /* Since we don't know in advance the number of glyphs to inspect, |
- we search backwards for matches in the backtrack glyph array */ |
- |
- bc = rccs->BacktrackCoverage; |
- |
- for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- ) |
- { |
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) ) |
- { |
- if ( error && error != HB_Err_Not_Covered ) |
- return error; |
- |
- if ( j + 1 == bgc - i ) |
- return HB_Err_Not_Covered; |
- j--; |
- } |
- |
- error = _HB_OPEN_Coverage_Index( &bc[i], IN_GLYPH( j ), &index ); |
- if ( error ) |
- return error; |
- } |
- } |
- |
- j = buffer->in_pos; |
- |
- error = _HB_OPEN_Coverage_Index( &rccs->Coverage, IN_GLYPH( j ), &input_index ); |
- if ( error ) |
- return error; |
- |
- lc = rccs->LookaheadCoverage; |
- |
- for ( i = 0, j = buffer->in_pos + 1; i < lgc; i++, j++ ) |
- { |
- while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) ) |
- { |
- if ( error && error != HB_Err_Not_Covered ) |
- return error; |
- |
- if ( j + lgc - i == (HB_Int)buffer->in_length ) |
- return HB_Err_Not_Covered; |
- j++; |
- } |
- |
- error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index ); |
- if ( error ) |
- return error; |
- } |
- |
- IN_CURGLYPH() = rccs->Substitute[input_index]; |
- buffer->in_pos--; /* Reverse! */ |
- |
- return error; |
-} |
- |
- |
- |
-/*********** |
- * GSUB API |
- ***********/ |
- |
- |
- |
-HB_Error HB_GSUB_Select_Script( HB_GSUBHeader* gsub, |
- HB_UInt script_tag, |
- HB_UShort* script_index ) |
-{ |
- HB_UShort n; |
- |
- HB_ScriptList* sl; |
- HB_ScriptRecord* sr; |
- |
- |
- if ( !gsub || !script_index ) |
- return ERR(HB_Err_Invalid_Argument); |
- |
- sl = &gsub->ScriptList; |
- sr = sl->ScriptRecord; |
- |
- for ( n = 0; n < sl->ScriptCount; n++ ) |
- if ( script_tag == sr[n].ScriptTag ) |
- { |
- *script_index = n; |
- |
- return HB_Err_Ok; |
- } |
- |
- return HB_Err_Not_Covered; |
-} |
- |
- |
- |
-HB_Error HB_GSUB_Select_Language( HB_GSUBHeader* gsub, |
- HB_UInt language_tag, |
- HB_UShort script_index, |
- HB_UShort* language_index, |
- HB_UShort* req_feature_index ) |
-{ |
- HB_UShort n; |
- |
- HB_ScriptList* sl; |
- HB_ScriptRecord* sr; |
- HB_ScriptTable* s; |
- HB_LangSysRecord* lsr; |
- |
- |
- if ( !gsub || !language_index || !req_feature_index ) |
- return ERR(HB_Err_Invalid_Argument); |
- |
- sl = &gsub->ScriptList; |
- sr = sl->ScriptRecord; |
- |
- if ( script_index >= sl->ScriptCount ) |
- return ERR(HB_Err_Invalid_Argument); |
- |
- s = &sr[script_index].Script; |
- lsr = s->LangSysRecord; |
- |
- for ( n = 0; n < s->LangSysCount; n++ ) |
- if ( language_tag == lsr[n].LangSysTag ) |
- { |
- *language_index = n; |
- *req_feature_index = lsr[n].LangSys.ReqFeatureIndex; |
- |
- return HB_Err_Ok; |
- } |
- |
- return HB_Err_Not_Covered; |
-} |
- |
- |
-/* selecting 0xFFFF for language_index asks for the values of the |
- default language (DefaultLangSys) */ |
- |
- |
-HB_Error HB_GSUB_Select_Feature( HB_GSUBHeader* gsub, |
- HB_UInt feature_tag, |
- HB_UShort script_index, |
- HB_UShort language_index, |
- HB_UShort* feature_index ) |
-{ |
- HB_UShort n; |
- |
- HB_ScriptList* sl; |
- HB_ScriptRecord* sr; |
- HB_ScriptTable* s; |
- HB_LangSysRecord* lsr; |
- HB_LangSys* ls; |
- HB_UShort* fi; |
- |
- HB_FeatureList* fl; |
- HB_FeatureRecord* fr; |
- |
- |
- if ( !gsub || !feature_index ) |
- return ERR(HB_Err_Invalid_Argument); |
- |
- sl = &gsub->ScriptList; |
- sr = sl->ScriptRecord; |
- |
- fl = &gsub->FeatureList; |
- fr = fl->FeatureRecord; |
- |
- if ( script_index >= sl->ScriptCount ) |
- return ERR(HB_Err_Invalid_Argument); |
- |
- s = &sr[script_index].Script; |
- lsr = s->LangSysRecord; |
- |
- if ( language_index == 0xFFFF ) |
- ls = &s->DefaultLangSys; |
- else |
- { |
- if ( language_index >= s->LangSysCount ) |
- return ERR(HB_Err_Invalid_Argument); |
- |
- ls = &lsr[language_index].LangSys; |
- } |
- |
- fi = ls->FeatureIndex; |
- |
- for ( n = 0; n < ls->FeatureCount; n++ ) |
- { |
- if ( fi[n] >= fl->FeatureCount ) |
- return ERR(HB_Err_Invalid_SubTable_Format); |
- |
- if ( feature_tag == fr[fi[n]].FeatureTag ) |
- { |
- *feature_index = fi[n]; |
- |
- return HB_Err_Ok; |
- } |
- } |
- |
- return HB_Err_Not_Covered; |
-} |
- |
- |
-/* The next three functions return a null-terminated list */ |
- |
- |
-HB_Error HB_GSUB_Query_Scripts( HB_GSUBHeader* gsub, |
- HB_UInt** script_tag_list ) |
-{ |
- HB_UShort n; |
- HB_Error error; |
- HB_UInt* stl; |
- |
- HB_ScriptList* sl; |
- HB_ScriptRecord* sr; |
- |
- |
- if ( !gsub || !script_tag_list ) |
- return ERR(HB_Err_Invalid_Argument); |
- |
- sl = &gsub->ScriptList; |
- sr = sl->ScriptRecord; |
- |
- if ( ALLOC_ARRAY( stl, sl->ScriptCount + 1, HB_UInt ) ) |
- return error; |
- |
- for ( n = 0; n < sl->ScriptCount; n++ ) |
- stl[n] = sr[n].ScriptTag; |
- stl[n] = 0; |
- |
- *script_tag_list = stl; |
- |
- return HB_Err_Ok; |
-} |
- |
- |
- |
-HB_Error HB_GSUB_Query_Languages( HB_GSUBHeader* gsub, |
- HB_UShort script_index, |
- HB_UInt** language_tag_list ) |
-{ |
- HB_UShort n; |
- HB_Error error; |
- HB_UInt* ltl; |
- |
- HB_ScriptList* sl; |
- HB_ScriptRecord* sr; |
- HB_ScriptTable* s; |
- HB_LangSysRecord* lsr; |
- |
- |
- if ( !gsub || !language_tag_list ) |
- return ERR(HB_Err_Invalid_Argument); |
- |
- sl = &gsub->ScriptList; |
- sr = sl->ScriptRecord; |
- |
- if ( script_index >= sl->ScriptCount ) |
- return ERR(HB_Err_Invalid_Argument); |
- |
- s = &sr[script_index].Script; |
- lsr = s->LangSysRecord; |
- |
- if ( ALLOC_ARRAY( ltl, s->LangSysCount + 1, HB_UInt ) ) |
- return error; |
- |
- for ( n = 0; n < s->LangSysCount; n++ ) |
- ltl[n] = lsr[n].LangSysTag; |
- ltl[n] = 0; |
- |
- *language_tag_list = ltl; |
- |
- return HB_Err_Ok; |
-} |
- |
- |
-/* selecting 0xFFFF for language_index asks for the values of the |
- default language (DefaultLangSys) */ |
- |
- |
-HB_Error HB_GSUB_Query_Features( HB_GSUBHeader* gsub, |
- HB_UShort script_index, |
- HB_UShort language_index, |
- HB_UInt** feature_tag_list ) |
-{ |
- HB_UShort n; |
- HB_Error error; |
- HB_UInt* ftl; |
- |
- HB_ScriptList* sl; |
- HB_ScriptRecord* sr; |
- HB_ScriptTable* s; |
- HB_LangSysRecord* lsr; |
- HB_LangSys* ls; |
- HB_UShort* fi; |
- |
- HB_FeatureList* fl; |
- HB_FeatureRecord* fr; |
- |
- |
- if ( !gsub || !feature_tag_list ) |
- return ERR(HB_Err_Invalid_Argument); |
- |
- sl = &gsub->ScriptList; |
- sr = sl->ScriptRecord; |
- |
- fl = &gsub->FeatureList; |
- fr = fl->FeatureRecord; |
- |
- if ( script_index >= sl->ScriptCount ) |
- return ERR(HB_Err_Invalid_Argument); |
- |
- s = &sr[script_index].Script; |
- lsr = s->LangSysRecord; |
- |
- if ( language_index == 0xFFFF ) |
- ls = &s->DefaultLangSys; |
- else |
- { |
- if ( language_index >= s->LangSysCount ) |
- return ERR(HB_Err_Invalid_Argument); |
- |
- ls = &lsr[language_index].LangSys; |
- } |
- |
- fi = ls->FeatureIndex; |
- |
- if ( ALLOC_ARRAY( ftl, ls->FeatureCount + 1, HB_UInt ) ) |
- return error; |
- |
- for ( n = 0; n < ls->FeatureCount; n++ ) |
- { |
- if ( fi[n] >= fl->FeatureCount ) |
- { |
- FREE( ftl ); |
- return ERR(HB_Err_Invalid_SubTable_Format); |
- } |
- ftl[n] = fr[fi[n]].FeatureTag; |
- } |
- ftl[n] = 0; |
- |
- *feature_tag_list = ftl; |
- |
- return HB_Err_Ok; |
-} |
- |
- |
-/* Do an individual subtable lookup. Returns HB_Err_Ok if substitution |
- has been done, or HB_Err_Not_Covered if not. */ |
-static HB_Error GSUB_Do_Glyph_Lookup( HB_GSUBHeader* gsub, |
- HB_UShort lookup_index, |
- HB_Buffer buffer, |
- HB_UShort context_length, |
- int nesting_level ) |
-{ |
- HB_Error error = HB_Err_Not_Covered; |
- HB_UShort i, flags, lookup_count; |
- HB_Lookup* lo; |
- int lookup_type; |
- |
- nesting_level++; |
- |
- if ( nesting_level > HB_MAX_NESTING_LEVEL ) |
- return ERR(HB_Err_Not_Covered); /* ERR() call intended */ |
- |
- lookup_count = gsub->LookupList.LookupCount; |
- if (lookup_index >= lookup_count) |
- return error; |
- |
- lo = &gsub->LookupList.Lookup[lookup_index]; |
- flags = lo->LookupFlag; |
- lookup_type = lo->LookupType; |
- |
- for ( i = 0; i < lo->SubTableCount; i++ ) |
- { |
- HB_GSUB_SubTable *st = &lo->SubTable[i].st.gsub; |
- |
- switch (lookup_type) { |
- case HB_GSUB_LOOKUP_SINGLE: |
- error = Lookup_SingleSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break; |
- case HB_GSUB_LOOKUP_MULTIPLE: |
- error = Lookup_MultipleSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break; |
- case HB_GSUB_LOOKUP_ALTERNATE: |
- error = Lookup_AlternateSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break; |
- case HB_GSUB_LOOKUP_LIGATURE: |
- error = Lookup_LigatureSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break; |
- case HB_GSUB_LOOKUP_CONTEXT: |
- error = Lookup_ContextSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break; |
- case HB_GSUB_LOOKUP_CHAIN: |
- error = Lookup_ChainContextSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break; |
- /*case HB_GSUB_LOOKUP_EXTENSION: |
- error = Lookup_ExtensionSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break;*/ |
- case HB_GSUB_LOOKUP_REVERSE_CHAIN: |
- error = Lookup_ReverseChainContextSubst ( gsub, st, buffer, flags, context_length, nesting_level ); break; |
- default: |
- error = HB_Err_Not_Covered; |
- }; |
- |
- /* Check whether we have a successful substitution or an error other |
- than HB_Err_Not_Covered */ |
- if ( error != HB_Err_Not_Covered ) |
- return error; |
- } |
- |
- return HB_Err_Not_Covered; |
-} |
- |
- |
-HB_INTERNAL HB_Error |
-_HB_GSUB_Load_SubTable( HB_GSUB_SubTable* st, |
- HB_Stream stream, |
- HB_UShort lookup_type ) |
-{ |
- switch (lookup_type) { |
- case HB_GSUB_LOOKUP_SINGLE: return Load_SingleSubst ( st, stream ); |
- case HB_GSUB_LOOKUP_MULTIPLE: return Load_MultipleSubst ( st, stream ); |
- case HB_GSUB_LOOKUP_ALTERNATE: return Load_AlternateSubst ( st, stream ); |
- case HB_GSUB_LOOKUP_LIGATURE: return Load_LigatureSubst ( st, stream ); |
- case HB_GSUB_LOOKUP_CONTEXT: return Load_ContextSubst ( st, stream ); |
- case HB_GSUB_LOOKUP_CHAIN: return Load_ChainContextSubst ( st, stream ); |
- /*case HB_GSUB_LOOKUP_EXTENSION: return Load_ExtensionSubst ( st, stream );*/ |
- case HB_GSUB_LOOKUP_REVERSE_CHAIN: return Load_ReverseChainContextSubst ( st, stream ); |
- default: return ERR(HB_Err_Invalid_SubTable_Format); |
- }; |
-} |
- |
- |
-HB_INTERNAL void |
-_HB_GSUB_Free_SubTable( HB_GSUB_SubTable* st, |
- HB_UShort lookup_type ) |
-{ |
- switch ( lookup_type ) { |
- case HB_GSUB_LOOKUP_SINGLE: Free_SingleSubst ( st ); return; |
- case HB_GSUB_LOOKUP_MULTIPLE: Free_MultipleSubst ( st ); return; |
- case HB_GSUB_LOOKUP_ALTERNATE: Free_AlternateSubst ( st ); return; |
- case HB_GSUB_LOOKUP_LIGATURE: Free_LigatureSubst ( st ); return; |
- case HB_GSUB_LOOKUP_CONTEXT: Free_ContextSubst ( st ); return; |
- case HB_GSUB_LOOKUP_CHAIN: Free_ChainContextSubst ( st ); return; |
- /*case HB_GSUB_LOOKUP_EXTENSION: Free_ExtensionSubst ( st ); return;*/ |
- case HB_GSUB_LOOKUP_REVERSE_CHAIN: Free_ReverseChainContextSubst ( st ); return; |
- default: return; |
- }; |
-} |
- |
- |
- |
-/* apply one lookup to the input string object */ |
- |
-static HB_Error GSUB_Do_String_Lookup( HB_GSUBHeader* gsub, |
- HB_UShort lookup_index, |
- HB_Buffer buffer ) |
-{ |
- HB_Error error, retError = HB_Err_Not_Covered; |
- |
- HB_UInt* properties = gsub->LookupList.Properties; |
- int lookup_type = gsub->LookupList.Lookup[lookup_index].LookupType; |
- |
- const int nesting_level = 0; |
- /* 0xFFFF indicates that we don't have a context length yet */ |
- const HB_UShort context_length = 0xFFFF; |
- |
- switch (lookup_type) { |
- |
- case HB_GSUB_LOOKUP_SINGLE: |
- case HB_GSUB_LOOKUP_MULTIPLE: |
- case HB_GSUB_LOOKUP_ALTERNATE: |
- case HB_GSUB_LOOKUP_LIGATURE: |
- case HB_GSUB_LOOKUP_CONTEXT: |
- case HB_GSUB_LOOKUP_CHAIN: |
- /* in/out forward substitution (implemented lazy) */ |
- |
- _hb_buffer_clear_output ( buffer ); |
- buffer->in_pos = 0; |
- while ( buffer->in_pos < buffer->in_length ) |
- { |
- if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] ) |
- { |
- error = GSUB_Do_Glyph_Lookup( gsub, lookup_index, buffer, context_length, nesting_level ); |
- if ( error ) |
- { |
- if ( error != HB_Err_Not_Covered ) |
- return error; |
- } |
- else |
- retError = error; |
- } |
- else |
- error = HB_Err_Not_Covered; |
- |
- if ( error == HB_Err_Not_Covered ) |
- if ( COPY_Glyph ( buffer ) ) |
- return error; |
- } |
- /* we shouldn't swap if error occurred. |
- * |
- * also don't swap if nothing changed (ie HB_Err_Not_Covered). |
- * shouldn't matter in that case though. |
- */ |
- if ( retError == HB_Err_Ok ) |
- _hb_buffer_swap( buffer ); |
- |
- return retError; |
- |
- case HB_GSUB_LOOKUP_REVERSE_CHAIN: |
- /* in-place backward substitution */ |
- |
- buffer->in_pos = buffer->in_length - 1; |
- do |
- { |
- if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] ) |
- { |
- error = GSUB_Do_Glyph_Lookup( gsub, lookup_index, buffer, context_length, nesting_level ); |
- if ( error ) |
- { |
- if ( error != HB_Err_Not_Covered ) |
- return error; |
- } |
- else |
- retError = error; |
- } |
- else |
- error = HB_Err_Not_Covered; |
- |
- if ( error == HB_Err_Not_Covered ) |
- buffer->in_pos--; |
- } |
- while ((HB_Int) buffer->in_pos >= 0); |
- |
- return retError; |
- |
- /*case HB_GSUB_LOOKUP_EXTENSION:*/ |
- default: |
- return retError; |
- }; |
-} |
- |
- |
-HB_Error HB_GSUB_Add_Feature( HB_GSUBHeader* gsub, |
- HB_UShort feature_index, |
- HB_UInt property ) |
-{ |
- HB_UShort i; |
- |
- HB_Feature feature; |
- HB_UInt* properties; |
- HB_UShort* index; |
- HB_UShort lookup_count; |
- |
- /* Each feature can only be added once */ |
- |
- if ( !gsub || |
- feature_index >= gsub->FeatureList.FeatureCount || |
- gsub->FeatureList.ApplyCount == gsub->FeatureList.FeatureCount ) |
- return ERR(HB_Err_Invalid_Argument); |
- |
- gsub->FeatureList.ApplyOrder[gsub->FeatureList.ApplyCount++] = feature_index; |
- |
- properties = gsub->LookupList.Properties; |
- |
- feature = gsub->FeatureList.FeatureRecord[feature_index].Feature; |
- index = feature.LookupListIndex; |
- lookup_count = gsub->LookupList.LookupCount; |
- |
- for ( i = 0; i < feature.LookupListCount; i++ ) |
- { |
- HB_UShort lookup_index = index[i]; |
- if (lookup_index < lookup_count) |
- properties[lookup_index] |= property; |
- } |
- |
- return HB_Err_Ok; |
-} |
- |
- |
- |
-HB_Error HB_GSUB_Clear_Features( HB_GSUBHeader* gsub ) |
-{ |
- HB_UShort i; |
- |
- HB_UInt* properties; |
- |
- |
- if ( !gsub ) |
- return ERR(HB_Err_Invalid_Argument); |
- |
- gsub->FeatureList.ApplyCount = 0; |
- |
- properties = gsub->LookupList.Properties; |
- |
- for ( i = 0; i < gsub->LookupList.LookupCount; i++ ) |
- properties[i] = 0; |
- |
- return HB_Err_Ok; |
-} |
- |
- |
- |
-HB_Error HB_GSUB_Register_Alternate_Function( HB_GSUBHeader* gsub, |
- HB_AltFunction altfunc, |
- void* data ) |
-{ |
- if ( !gsub ) |
- return ERR(HB_Err_Invalid_Argument); |
- |
- gsub->altfunc = altfunc; |
- gsub->data = data; |
- |
- return HB_Err_Ok; |
-} |
- |
-/* returns error if one happened, otherwise returns HB_Err_Not_Covered if no |
- * feature were applied, or HB_Err_Ok otherwise. |
- */ |
-HB_Error HB_GSUB_Apply_String( HB_GSUBHeader* gsub, |
- HB_Buffer buffer ) |
-{ |
- HB_Error error, retError = HB_Err_Not_Covered; |
- int i, j, lookup_count, num_features; |
- |
- if ( !gsub || |
- !buffer) |
- return ERR(HB_Err_Invalid_Argument); |
- |
- if ( buffer->in_length == 0 ) |
- return retError; |
- |
- lookup_count = gsub->LookupList.LookupCount; |
- num_features = gsub->FeatureList.ApplyCount; |
- |
- for ( i = 0; i < num_features; i++) |
- { |
- HB_UShort feature_index = gsub->FeatureList.ApplyOrder[i]; |
- HB_Feature feature = gsub->FeatureList.FeatureRecord[feature_index].Feature; |
- |
- for ( j = 0; j < feature.LookupListCount; j++ ) |
- { |
- HB_UShort lookup_index = feature.LookupListIndex[j]; |
- |
- /* Skip nonexistant lookups */ |
- if (lookup_index >= lookup_count) |
- continue; |
- |
- error = GSUB_Do_String_Lookup( gsub, lookup_index, buffer ); |
- if ( error ) |
- { |
- if ( error != HB_Err_Not_Covered ) |
- return error; |
- } |
- else |
- retError = error; |
- } |
- } |
- |
- error = retError; |
- |
- return error; |
-} |
- |
- |
-/* END */ |