diff options
Diffstat (limited to 'tqtinterface/qt4/include/private/qt4_harfbuzz/src/harfbuzz-gsub.c')
-rw-r--r-- | tqtinterface/qt4/include/private/qt4_harfbuzz/src/harfbuzz-gsub.c | 4329 |
1 files changed, 0 insertions, 4329 deletions
diff --git a/tqtinterface/qt4/include/private/qt4_harfbuzz/src/harfbuzz-gsub.c b/tqtinterface/qt4/include/private/qt4_harfbuzz/src/harfbuzz-gsub.c deleted file mode 100644 index 21fec51..0000000 --- a/tqtinterface/qt4/include/private/qt4_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 */ |