diff options
Diffstat (limited to 'tqtinterface/qt4/src/3rdparty/opentype/ftxgsub.c')
-rw-r--r-- | tqtinterface/qt4/src/3rdparty/opentype/ftxgsub.c | 4156 |
1 files changed, 0 insertions, 4156 deletions
diff --git a/tqtinterface/qt4/src/3rdparty/opentype/ftxgsub.c b/tqtinterface/qt4/src/3rdparty/opentype/ftxgsub.c deleted file mode 100644 index fd2cda0..0000000 --- a/tqtinterface/qt4/src/3rdparty/opentype/ftxgsub.c +++ /dev/null @@ -1,4156 +0,0 @@ -/******************************************************************* - * - * ftxgsub.c - * - * TrueType Open GSUB table support. - * - * Copyright 1996-2000 by - * David Turner, Robert Wilhelm, and Werner Lemberg. - * - * This file is part of the FreeType project, and may only be used - * modified and distributed under the terms of the FreeType project - * license, LICENSE.TXT. By continuing to use, modify, or distribute - * this file you indicate that you have read the license and - * understand and accept it fully. - * - ******************************************************************/ - -/* XXX There is *a lot* of duplicated code (cf. formats 5 and 6), but - I don't care currently. I believe that it would be possible to - save about 50% of TTO code by carefully designing the structures, - sharing as much as possible with extensive use of macros. This - is something for a volunteer :-) */ - -#define EXPORT_FUNC - -#include "ftxopen.h" -#include "ftxopenf.h" - -#include "ftglue.h" - -#include FT_TRUETYPE_TAGS_H - -#define GSUB_ID Build_Extension_ID( 'G', 'S', 'U', 'B' ) - - - static FT_Error GSub_Do_Glyph_Lookup( TTO_GSUBHeader* gsub, - FT_UShort lookup_index, - OTL_Buffer buffer, - FT_UShort context_length, - int nesting_level ); - - - - /********************** - * Auxiliary functions - **********************/ - - - EXPORT_FUNC - FT_Error TT_Load_GSUB_Table( FT_Face face, - TTO_GSUBHeader** retptr, - TTO_GDEFHeader* gdef ) - { - FT_Stream stream = face->stream; - FT_Memory memory = face->memory; - FT_Error error; - FT_ULong cur_offset, new_offset, base_offset; - - FT_UShort i, num_lookups; - TTO_GSUBHeader* gsub; - TTO_Lookup* lo; - - if ( !retptr ) - return TT_Err_Invalid_Argument; - - if (( error = ftglue_face_goto_table( face, TTAG_GSUB, stream ) )) - return error; - - base_offset = FILE_Pos(); - - if ( ALLOC ( gsub, sizeof( *gsub ) ) ) - return error; - - gsub->memory = memory; - - /* 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 = Load_ScriptList( &gsub->ScriptList, - stream ) ) != TT_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 = Load_FeatureList( &gsub->FeatureList, - stream ) ) != TT_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 = Load_LookupList( &gsub->LookupList, - stream, GSUB ) ) != TT_Err_Ok ) - goto Fail2; - - gsub->gdef = gdef; /* can be NULL */ - - /* We now check the LookupFlags for values larger than 0xFF to find - out whether we need to load the `MarkAttachClassDef' field of the - GDEF table -- this hack is necessary for OpenType 1.2 tables since - the version field of the GDEF table hasn't been incremented. - - For constructed GDEF tables, we only load it if - `MarkAttachClassDef_offset' is not zero (nevertheless, a build of - a constructed mark attach table is not supported currently). */ - - if ( gdef && - gdef->MarkAttachClassDef_offset && !gdef->MarkAttachClassDef.loaded ) - { - lo = gsub->LookupList.Lookup; - num_lookups = gsub->LookupList.LookupCount; - - for ( i = 0; i < num_lookups; i++ ) - { - - if ( lo[i].LookupFlag & IGNORE_SPECIAL_MARKS ) - { - if ( FILE_Seek( gdef->MarkAttachClassDef_offset ) || - ( error = Load_ClassDefinition( &gdef->MarkAttachClassDef, - 256, stream ) ) != TT_Err_Ok ) - goto Fail1; - - break; - } - } - } - - *retptr = gsub; - - return TT_Err_Ok; - - Fail1: - Free_LookupList( &gsub->LookupList, GSUB, memory ); - - Fail2: - Free_FeatureList( &gsub->FeatureList, memory ); - - Fail3: - Free_ScriptList( &gsub->ScriptList, memory ); - - Fail4: - FREE ( gsub ); - - - return error; - } - - EXPORT_FUNC - FT_Error TT_Done_GSUB_Table( TTO_GSUBHeader* gsub ) - { - FT_Memory memory = gsub->memory; - - Free_LookupList( &gsub->LookupList, GSUB, memory ); - Free_FeatureList( &gsub->FeatureList, memory ); - Free_ScriptList( &gsub->ScriptList, memory ); - - FREE( gsub ); - - return TT_Err_Ok; - } - - /***************************** - * SubTable related functions - *****************************/ - - - /* LookupType 1 */ - - /* SingleSubstFormat1 */ - /* SingleSubstFormat2 */ - - FT_Error Load_SingleSubst( TTO_SingleSubst* ss, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UShort n, count; - FT_ULong cur_offset, new_offset, base_offset; - - FT_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 = Load_Coverage( &ss->Coverage, stream ) ) != TT_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, FT_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 TTO_Err_Invalid_GSUB_SubTable_Format; - } - - return TT_Err_Ok; - - Fail1: - FREE( s ); - - Fail2: - Free_Coverage( &ss->Coverage, memory ); - return error; - } - - - void Free_SingleSubst( TTO_SingleSubst* ss, - FT_Memory memory ) - { - switch ( ss->SubstFormat ) - { - case 1: - break; - - case 2: - FREE( ss->ssf.ssf2.Substitute ); - break; - } - - Free_Coverage( &ss->Coverage, memory ); - } - - - static FT_Error Lookup_SingleSubst( TTO_SingleSubst* ss, - OTL_Buffer buffer, - FT_UShort flags, - FT_UShort context_length, - TTO_GDEFHeader* gdef ) - { - FT_UShort index, value, property; - FT_Error error; - - - if ( context_length != 0xFFFF && context_length < 1 ) - return TTO_Err_Not_Covered; - - if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) - return error; - - error = 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 ( ADD_Glyph( buffer, value, 0xFFFF, 0xFFFF ) ) - return error; - break; - - case 2: - if ( index >= ss->ssf.ssf2.GlyphCount ) - return TTO_Err_Invalid_GSUB_SubTable; - value = ss->ssf.ssf2.Substitute[index]; - if ( ADD_Glyph( buffer, value, 0xFFFF, 0xFFFF ) ) - return error; - break; - - default: - return TTO_Err_Invalid_GSUB_SubTable; - } - - if ( gdef && gdef->NewGlyphClasses ) - { - /* we inherit the old glyph class to the substituted glyph */ - - error = Add_Glyph_Property( gdef, value, property ); - if ( error && error != TTO_Err_Not_Covered ) - return error; - } - - return TT_Err_Ok; - } - - - /* LookupType 2 */ - - /* Sequence */ - - static FT_Error Load_Sequence( TTO_Sequence* s, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UShort n, count; - FT_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, FT_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 TT_Err_Ok; - } - - - static void Free_Sequence( TTO_Sequence* s, - FT_Memory memory ) - { - FREE( s->Substitute ); - } - - - /* MultipleSubstFormat1 */ - - FT_Error Load_MultipleSubst( TTO_MultipleSubst* ms, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UShort n = 0, m, count; - FT_ULong cur_offset, new_offset, base_offset; - - TTO_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 = Load_Coverage( &ms->Coverage, stream ) ) != TT_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, TTO_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 ) ) != TT_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - - return TT_Err_Ok; - - Fail1: - for ( m = 0; m < n; m++ ) - Free_Sequence( &s[m], memory ); - - FREE( s ); - - Fail2: - Free_Coverage( &ms->Coverage, memory ); - return error; - } - - - void Free_MultipleSubst( TTO_MultipleSubst* ms, - FT_Memory memory ) - { - FT_UShort n, count; - - TTO_Sequence* s; - - - if ( ms->Sequence ) - { - count = ms->SequenceCount; - s = ms->Sequence; - - for ( n = 0; n < count; n++ ) - Free_Sequence( &s[n], memory ); - - FREE( s ); - } - - Free_Coverage( &ms->Coverage, memory ); - } - - - static FT_Error Lookup_MultipleSubst( TTO_MultipleSubst* ms, - OTL_Buffer buffer, - FT_UShort flags, - FT_UShort context_length, - TTO_GDEFHeader* gdef ) - { - FT_Error error; - FT_UShort index, property, n, count; - FT_UShort*s; - - - if ( context_length != 0xFFFF && context_length < 1 ) - return TTO_Err_Not_Covered; - - if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) - return error; - - error = Coverage_Index( &ms->Coverage, IN_CURGLYPH(), &index ); - if ( error ) - return error; - - if ( index >= ms->SequenceCount ) - return TTO_Err_Invalid_GSUB_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 == TTO_LIGATURE ) - property = TTO_BASE_GLYPH; - - for ( n = 0; n < count; n++ ) - { - error = Add_Glyph_Property( gdef, s[n], property ); - if ( error && error != TTO_Err_Not_Covered ) - return error; - } - } - - return TT_Err_Ok; - } - - - /* LookupType 3 */ - - /* AlternateSet */ - - static FT_Error Load_AlternateSet( TTO_AlternateSet* as, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UShort n, count; - FT_UShort* a; - - - if ( ACCESS_Frame( 2L ) ) - return error; - - count = as->GlyphCount = GET_UShort(); - - FORGET_Frame(); - - as->Alternate = NULL; - - if ( ALLOC_ARRAY( as->Alternate, count, FT_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 TT_Err_Ok; - } - - - static void Free_AlternateSet( TTO_AlternateSet* as, - FT_Memory memory ) - { - FREE( as->Alternate ); - } - - - /* AlternateSubstFormat1 */ - - FT_Error Load_AlternateSubst( TTO_AlternateSubst* as, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UShort n = 0, m, count; - FT_ULong cur_offset, new_offset, base_offset; - - TTO_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 = Load_Coverage( &as->Coverage, stream ) ) != TT_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, TTO_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 ) ) != TT_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - - return TT_Err_Ok; - - Fail1: - for ( m = 0; m < n; m++ ) - Free_AlternateSet( &aset[m], memory ); - - FREE( aset ); - - Fail2: - Free_Coverage( &as->Coverage, memory ); - return error; - } - - - void Free_AlternateSubst( TTO_AlternateSubst* as, - FT_Memory memory ) - { - FT_UShort n, count; - - TTO_AlternateSet* aset; - - - if ( as->AlternateSet ) - { - count = as->AlternateSetCount; - aset = as->AlternateSet; - - for ( n = 0; n < count; n++ ) - Free_AlternateSet( &aset[n], memory ); - - FREE( aset ); - } - - Free_Coverage( &as->Coverage, memory ); - } - - - static FT_Error Lookup_AlternateSubst( TTO_GSUBHeader* gsub, - TTO_AlternateSubst* as, - OTL_Buffer buffer, - FT_UShort flags, - FT_UShort context_length, - TTO_GDEFHeader* gdef ) - { - FT_Error error; - FT_UShort index, alt_index, property; - - TTO_AlternateSet aset; - - - if ( context_length != 0xFFFF && context_length < 1 ) - return TTO_Err_Not_Covered; - - if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) - return error; - - error = 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; - - if ( ADD_Glyph( buffer, aset.Alternate[alt_index], - 0xFFFF, 0xFFFF ) ) - return error; - - if ( gdef && gdef->NewGlyphClasses ) - { - /* we inherit the old glyph class to the substituted glyph */ - - error = Add_Glyph_Property( gdef, aset.Alternate[alt_index], - property ); - if ( error && error != TTO_Err_Not_Covered ) - return error; - } - - return TT_Err_Ok; - } - - - /* LookupType 4 */ - - /* Ligature */ - - static FT_Error Load_Ligature( TTO_Ligature* l, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UShort n, count; - FT_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, FT_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 TT_Err_Ok; - } - - - static void Free_Ligature( TTO_Ligature* l, - FT_Memory memory ) - { - FREE( l->Component ); - } - - - /* LigatureSet */ - - static FT_Error Load_LigatureSet( TTO_LigatureSet* ls, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UShort n = 0, m, count; - FT_ULong cur_offset, new_offset, base_offset; - - TTO_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, TTO_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 ) ) != TT_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return TT_Err_Ok; - - Fail: - for ( m = 0; m < n; m++ ) - Free_Ligature( &l[m], memory ); - - FREE( l ); - return error; - } - - - static void Free_LigatureSet( TTO_LigatureSet* ls, - FT_Memory memory ) - { - FT_UShort n, count; - - TTO_Ligature* l; - - - if ( ls->Ligature ) - { - count = ls->LigatureCount; - l = ls->Ligature; - - for ( n = 0; n < count; n++ ) - Free_Ligature( &l[n], memory ); - - FREE( l ); - } - } - - - /* LigatureSubstFormat1 */ - - FT_Error Load_LigatureSubst( TTO_LigatureSubst* ls, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UShort n = 0, m, count; - FT_ULong cur_offset, new_offset, base_offset; - - TTO_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 = Load_Coverage( &ls->Coverage, stream ) ) != TT_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, TTO_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 ) ) != TT_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - - return TT_Err_Ok; - - Fail1: - for ( m = 0; m < n; m++ ) - Free_LigatureSet( &lset[m], memory ); - - FREE( lset ); - - Fail2: - Free_Coverage( &ls->Coverage, memory ); - return error; - } - - - void Free_LigatureSubst( TTO_LigatureSubst* ls, - FT_Memory memory ) - { - FT_UShort n, count; - - TTO_LigatureSet* lset; - - - if ( ls->LigatureSet ) - { - count = ls->LigatureSetCount; - lset = ls->LigatureSet; - - for ( n = 0; n < count; n++ ) - Free_LigatureSet( &lset[n], memory ); - - FREE( lset ); - } - - Free_Coverage( &ls->Coverage, memory ); - } - - - static FT_Error Lookup_LigatureSubst( TTO_LigatureSubst* ls, - OTL_Buffer buffer, - FT_UShort flags, - FT_UShort context_length, - TTO_GDEFHeader* gdef ) - { - FT_UShort index, property; - FT_Error error; - FT_UShort numlig, i, j, is_mark, first_is_mark = FALSE; - FT_UShort* c; - - TTO_Ligature* lig; - - - if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) - return error; - - if ( property == TTO_MARK || property & IGNORE_SPECIAL_MARKS ) - first_is_mark = TRUE; - - error = Coverage_Index( &ls->Coverage, IN_CURGLYPH(), &index ); - if ( error ) - return error; - - if ( index >= ls->LigatureSetCount ) - return TTO_Err_Invalid_GSUB_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 != TTO_Err_Not_Covered ) - return error; - - if ( j + lig->ComponentCount - i == (FT_Int)buffer->in_length ) - goto next_ligature; - j++; - } - - if ( !( property == TTO_MARK || property & 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 = Add_Glyph_Property( gdef, lig->LigGlyph, - is_mark ? TTO_MARK : TTO_LIGATURE ); - if ( error && error != TTO_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 - { - FT_UShort ligID = otl_buffer_allocate_ligid( buffer ); - if ( ADD_String( buffer, i, 1, &lig->LigGlyph, - 0xFFFF, ligID ) ) - return error; - } - } - else - { - FT_UShort ligID = otl_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 TT_Err_Ok; - - next_ligature: - ; - } - - return TTO_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 FT_Error Do_ContextSubst( TTO_GSUBHeader* gsub, - FT_UShort GlyphCount, - FT_UShort SubstCount, - TTO_SubstLookupRecord* subst, - OTL_Buffer buffer, - int nesting_level ) - { - FT_Error error; - FT_UShort 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 == TTO_Err_Not_Covered ) - { - /* XXX "can't happen" -- but don't count on it */ - - if ( ADD_Glyph( buffer, IN_CURGLYPH(), - 0xFFFF, 0xFFFF ) ) - return error; - i++; - } - else if ( error ) - return error; - } - else - { - /* No substitution for this index */ - - if ( ADD_Glyph( buffer, IN_CURGLYPH(), - 0xFFFF, 0xFFFF ) ) - return error; - i++; - } - } - - return TT_Err_Ok; - } - - - /* LookupType 5 */ - - /* SubRule */ - - static FT_Error Load_SubRule( TTO_SubRule* sr, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UShort n, count; - FT_UShort* i; - - TTO_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, FT_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, TTO_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 TT_Err_Ok; - - Fail1: - FREE( slr ); - - Fail2: - FREE( i ); - return error; - } - - - static void Free_SubRule( TTO_SubRule* sr, - FT_Memory memory ) - { - FREE( sr->SubstLookupRecord ); - FREE( sr->Input ); - } - - - /* SubRuleSet */ - - static FT_Error Load_SubRuleSet( TTO_SubRuleSet* srs, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UShort n = 0, m, count; - FT_ULong cur_offset, new_offset, base_offset; - - TTO_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, TTO_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 ) ) != TT_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return TT_Err_Ok; - - Fail: - for ( m = 0; m < n; m++ ) - Free_SubRule( &sr[m], memory ); - - FREE( sr ); - return error; - } - - - static void Free_SubRuleSet( TTO_SubRuleSet* srs, - FT_Memory memory ) - { - FT_UShort n, count; - - TTO_SubRule* sr; - - - if ( srs->SubRule ) - { - count = srs->SubRuleCount; - sr = srs->SubRule; - - for ( n = 0; n < count; n++ ) - Free_SubRule( &sr[n], memory ); - - FREE( sr ); - } - } - - - /* ContextSubstFormat1 */ - - static FT_Error Load_ContextSubst1( TTO_ContextSubstFormat1* csf1, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UShort n = 0, m, count; - FT_ULong cur_offset, new_offset, base_offset; - - TTO_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 = Load_Coverage( &csf1->Coverage, stream ) ) != TT_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, TTO_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 ) ) != TT_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - - return TT_Err_Ok; - - Fail1: - for ( m = 0; m < n; m++ ) - Free_SubRuleSet( &srs[m], memory ); - - FREE( srs ); - - Fail2: - Free_Coverage( &csf1->Coverage, memory ); - return error; - } - - - static void Gsub_Free_Context1( TTO_ContextSubstFormat1* csf1, - FT_Memory memory ) - { - FT_UShort n, count; - - TTO_SubRuleSet* srs; - - - if ( csf1->SubRuleSet ) - { - count = csf1->SubRuleSetCount; - srs = csf1->SubRuleSet; - - for ( n = 0; n < count; n++ ) - Free_SubRuleSet( &srs[n], memory ); - - FREE( srs ); - } - - Free_Coverage( &csf1->Coverage, memory ); - } - - - /* SubClassRule */ - - static FT_Error Load_SubClassRule( TTO_ContextSubstFormat2* csf2, - TTO_SubClassRule* scr, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UShort n, count; - - FT_UShort* c; - TTO_SubstLookupRecord* slr; - FT_Bool* d; - - - 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, FT_UShort ) ) - return error; - - c = scr->Class; - d = csf2->ClassDef.Defined; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail2; - - for ( n = 0; n < count; n++ ) - { - c[n] = GET_UShort(); - - /* We check whether the specific class is used at all. If not, - class 0 is used instead. */ - if ( !d[c[n]] ) - c[n] = 0; - } - - FORGET_Frame(); - - scr->SubstLookupRecord = NULL; - - count = scr->SubstCount; - - if ( ALLOC_ARRAY( scr->SubstLookupRecord, count, TTO_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 TT_Err_Ok; - - Fail1: - FREE( slr ); - - Fail2: - FREE( c ); - return error; - } - - - static void Free_SubClassRule( TTO_SubClassRule* scr, - FT_Memory memory ) - { - FREE( scr->SubstLookupRecord ); - FREE( scr->Class ); - } - - - /* SubClassSet */ - - static FT_Error Load_SubClassSet( TTO_ContextSubstFormat2* csf2, - TTO_SubClassSet* scs, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UShort n = 0, m, count; - FT_ULong cur_offset, new_offset, base_offset; - - TTO_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, TTO_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 ) ) != TT_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return TT_Err_Ok; - - Fail: - for ( m = 0; m < n; m++ ) - Free_SubClassRule( &scr[m], memory ); - - FREE( scr ); - return error; - } - - - static void Free_SubClassSet( TTO_SubClassSet* scs, - FT_Memory memory ) - { - FT_UShort n, count; - - TTO_SubClassRule* scr; - - - if ( scs->SubClassRule ) - { - count = scs->SubClassRuleCount; - scr = scs->SubClassRule; - - for ( n = 0; n < count; n++ ) - Free_SubClassRule( &scr[n], memory ); - - FREE( scr ); - } - } - - - /* ContextSubstFormat2 */ - - static FT_Error Load_ContextSubst2( TTO_ContextSubstFormat2* csf2, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UShort n = 0, m, count; - FT_ULong cur_offset, new_offset, base_offset; - - TTO_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 = Load_Coverage( &csf2->Coverage, stream ) ) != TT_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 = Load_ClassDefinition( &csf2->ClassDef, count, - stream ) ) != TT_Err_Ok ) - goto Fail3; - (void)FILE_Seek( cur_offset ); - - csf2->SubClassSet = NULL; - csf2->MaxContextLength = 0; - - if ( ALLOC_ARRAY( csf2->SubClassSet, count, TTO_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 ) ) != TT_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 TT_Err_Ok; - - Fail1: - for ( m = 0; m < n; m++ ) - Free_SubClassSet( &scs[m], memory ); - - FREE( scs ); - - Fail2: - Free_ClassDefinition( &csf2->ClassDef, memory ); - - Fail3: - Free_Coverage( &csf2->Coverage, memory ); - return error; - } - - - static void Gsub_Free_Context2( TTO_ContextSubstFormat2* csf2, - FT_Memory memory ) - { - FT_UShort n, count; - - TTO_SubClassSet* scs; - - - if ( csf2->SubClassSet ) - { - count = csf2->SubClassSetCount; - scs = csf2->SubClassSet; - - for ( n = 0; n < count; n++ ) - Free_SubClassSet( &scs[n], memory ); - - FREE( scs ); - } - - Free_ClassDefinition( &csf2->ClassDef, memory ); - Free_Coverage( &csf2->Coverage, memory ); - } - - - /* ContextSubstFormat3 */ - - static FT_Error Load_ContextSubst3( TTO_ContextSubstFormat3* csf3, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UShort n = 0, m, count; - FT_ULong cur_offset, new_offset, base_offset; - - TTO_Coverage* c; - TTO_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, TTO_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 = Load_Coverage( &c[n], stream ) ) != TT_Err_Ok ) - goto Fail2; - (void)FILE_Seek( cur_offset ); - } - - csf3->SubstLookupRecord = NULL; - - count = csf3->SubstCount; - - if ( ALLOC_ARRAY( csf3->SubstLookupRecord, count, - TTO_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 TT_Err_Ok; - - Fail1: - FREE( slr ); - - Fail2: - for ( m = 0; m < n; m++ ) - Free_Coverage( &c[m], memory ); - - FREE( c ); - return error; - } - - - static void Gsub_Free_Context3( TTO_ContextSubstFormat3* csf3, - FT_Memory memory ) - { - FT_UShort n, count; - - TTO_Coverage* c; - - - FREE( csf3->SubstLookupRecord ); - - if ( csf3->Coverage ) - { - count = csf3->GlyphCount; - c = csf3->Coverage; - - for ( n = 0; n < count; n++ ) - Free_Coverage( &c[n], memory ); - - FREE( c ); - } - } - - - /* ContextSubst */ - - FT_Error Load_ContextSubst( TTO_ContextSubst* cs, - FT_Stream stream ) - { - FT_Error error; - - - 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 TTO_Err_Invalid_GSUB_SubTable_Format; - } - - return TT_Err_Ok; /* never reached */ - } - - - void Free_ContextSubst( TTO_ContextSubst* cs, - FT_Memory memory ) - { - switch ( cs->SubstFormat ) - { - case 1: - Gsub_Free_Context1( &cs->csf.csf1, memory ); - break; - - case 2: - Gsub_Free_Context2( &cs->csf.csf2, memory ); - break; - - case 3: - Gsub_Free_Context3( &cs->csf.csf3, memory ); - break; - } - } - - - static FT_Error Lookup_ContextSubst1( - TTO_GSUBHeader* gsub, - TTO_ContextSubstFormat1* csf1, - OTL_Buffer buffer, - FT_UShort flags, - FT_UShort context_length, - int nesting_level ) - { - FT_UShort index, property; - FT_UShort i, j, k, numsr; - FT_Error error; - - TTO_SubRule* sr; - TTO_GDEFHeader* gdef; - - - gdef = gsub->gdef; - - if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) - return error; - - error = 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 != TTO_Err_Not_Covered ) - return error; - - if ( j + sr[k].GlyphCount - i == (FT_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 TTO_Err_Not_Covered; - } - - - static FT_Error Lookup_ContextSubst2( - TTO_GSUBHeader* gsub, - TTO_ContextSubstFormat2* csf2, - OTL_Buffer buffer, - FT_UShort flags, - FT_UShort context_length, - int nesting_level ) - { - FT_UShort index, property; - FT_Error error; - FT_Memory memory = gsub->memory; - FT_UShort i, j, k, known_classes; - - FT_UShort* classes; - FT_UShort* cl; - - TTO_SubClassSet* scs; - TTO_SubClassRule* sr; - TTO_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 = Coverage_Index( &csf2->Coverage, IN_CURGLYPH(), &index ); - if ( error ) - return error; - - if ( ALLOC_ARRAY( classes, csf2->MaxContextLength, FT_UShort ) ) - return error; - - error = Get_Class( &csf2->ClassDef, IN_CURGLYPH(), - &classes[0], NULL ); - if ( error && error != TTO_Err_Not_Covered ) - goto End; - known_classes = 0; - - scs = &csf2->SubClassSet[classes[0]]; - if ( !scs ) - { - error = TTO_Err_Invalid_GSUB_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 != TTO_Err_Not_Covered ) - goto End; - - if ( j + sr->GlyphCount - i < (FT_Int)buffer->in_length ) - goto next_subclassrule; - j++; - } - - if ( i > known_classes ) - { - /* Keeps us from having to do this for each rule */ - - error = Get_Class( &csf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL ); - if ( error && error != TTO_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 = TTO_Err_Not_Covered; - - End: - FREE( classes ); - return error; - } - - - static FT_Error Lookup_ContextSubst3( - TTO_GSUBHeader* gsub, - TTO_ContextSubstFormat3* csf3, - OTL_Buffer buffer, - FT_UShort flags, - FT_UShort context_length, - int nesting_level ) - { - FT_Error error; - FT_UShort index, i, j, property; - - TTO_Coverage* c; - TTO_GDEFHeader* gdef; - - - gdef = gsub->gdef; - - if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) - return error; - - if ( context_length != 0xFFFF && context_length < csf3->GlyphCount ) - return TTO_Err_Not_Covered; - - if ( buffer->in_pos + csf3->GlyphCount > buffer->in_length ) - return TTO_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 != TTO_Err_Not_Covered ) - return error; - - if ( j + csf3->GlyphCount - i == (FT_Int)buffer->in_length ) - return TTO_Err_Not_Covered; - j++; - } - - error = 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 FT_Error Lookup_ContextSubst( TTO_GSUBHeader* gsub, - TTO_ContextSubst* cs, - OTL_Buffer buffer, - FT_UShort flags, - FT_UShort context_length, - int nesting_level ) - { - 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 TTO_Err_Invalid_GSUB_SubTable_Format; - } - - return TT_Err_Ok; /* never reached */ - } - - - /* LookupType 6 */ - - /* ChainSubRule */ - - static FT_Error Load_ChainSubRule( TTO_ChainSubRule* csr, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UShort n, count; - FT_UShort* b; - FT_UShort* i; - FT_UShort* l; - - TTO_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, FT_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, FT_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, FT_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, TTO_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 TT_Err_Ok; - - Fail1: - FREE( slr ); - - Fail2: - FREE( l ); - - Fail3: - FREE( i ); - - Fail4: - FREE( b ); - return error; - } - - - static void Gsub_Free_ChainSubRule( TTO_ChainSubRule* csr, - FT_Memory memory ) - { - FREE( csr->SubstLookupRecord ); - FREE( csr->Lookahead ); - FREE( csr->Input ); - FREE( csr->Backtrack ); - } - - - /* ChainSubRuleSet */ - - static FT_Error Load_ChainSubRuleSet( TTO_ChainSubRuleSet* csrs, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UShort n = 0, m, count; - FT_ULong cur_offset, new_offset, base_offset; - - TTO_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, TTO_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 ) ) != TT_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return TT_Err_Ok; - - Fail: - for ( m = 0; m < n; m++ ) - Gsub_Free_ChainSubRule( &csr[m], memory ); - - FREE( csr ); - return error; - } - - - static void Gsub_Free_ChainSubRuleSet( TTO_ChainSubRuleSet* csrs, - FT_Memory memory ) - { - FT_UShort n, count; - - TTO_ChainSubRule* csr; - - - if ( csrs->ChainSubRule ) - { - count = csrs->ChainSubRuleCount; - csr = csrs->ChainSubRule; - - for ( n = 0; n < count; n++ ) - Gsub_Free_ChainSubRule( &csr[n], memory ); - - FREE( csr ); - } - } - - - /* ChainContextSubstFormat1 */ - - static FT_Error Load_ChainContextSubst1( - TTO_ChainContextSubstFormat1* ccsf1, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UShort n = 0, m, count; - FT_ULong cur_offset, new_offset, base_offset; - - TTO_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 = Load_Coverage( &ccsf1->Coverage, stream ) ) != TT_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, TTO_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 ) ) != TT_Err_Ok ) - goto Fail1; - (void)FILE_Seek( cur_offset ); - } - - return TT_Err_Ok; - - Fail1: - for ( m = 0; m < n; m++ ) - Gsub_Free_ChainSubRuleSet( &csrs[m], memory ); - - FREE( csrs ); - - Fail2: - Free_Coverage( &ccsf1->Coverage, memory ); - return error; - } - - - static void Gsub_Free_ChainContext1( TTO_ChainContextSubstFormat1* ccsf1, - FT_Memory memory ) - { - FT_UShort n, count; - - TTO_ChainSubRuleSet* csrs; - - - if ( ccsf1->ChainSubRuleSet ) - { - count = ccsf1->ChainSubRuleSetCount; - csrs = ccsf1->ChainSubRuleSet; - - for ( n = 0; n < count; n++ ) - Gsub_Free_ChainSubRuleSet( &csrs[n], memory ); - - FREE( csrs ); - } - - Free_Coverage( &ccsf1->Coverage, memory ); - } - - - /* ChainSubClassRule */ - - static FT_Error Load_ChainSubClassRule( - TTO_ChainContextSubstFormat2* ccsf2, - TTO_ChainSubClassRule* cscr, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UShort n, count; - - FT_UShort* b; - FT_UShort* i; - FT_UShort* l; - TTO_SubstLookupRecord* slr; - FT_Bool* d; - - - 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, FT_UShort ) ) - return error; - - b = cscr->Backtrack; - d = ccsf2->BacktrackClassDef.Defined; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail4; - - for ( n = 0; n < count; n++ ) - { - b[n] = GET_UShort(); - - /* We check whether the specific class is used at all. If not, - class 0 is used instead. */ - - if ( !d[b[n]] ) - b[n] = 0; - } - - 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, FT_UShort ) ) - goto Fail4; - - i = cscr->Input; - d = ccsf2->InputClassDef.Defined; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail3; - - for ( n = 0; n < count; n++ ) - { - i[n] = GET_UShort(); - - if ( !d[i[n]] ) - i[n] = 0; - } - - 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, FT_UShort ) ) - goto Fail3; - - l = cscr->Lookahead; - d = ccsf2->LookaheadClassDef.Defined; - - if ( ACCESS_Frame( count * 2L ) ) - goto Fail2; - - for ( n = 0; n < count; n++ ) - { - l[n] = GET_UShort(); - - if ( !d[l[n]] ) - l[n] = 0; - } - - 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, - TTO_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 TT_Err_Ok; - - Fail1: - FREE( slr ); - - Fail2: - FREE( l ); - - Fail3: - FREE( i ); - - Fail4: - FREE( b ); - return error; - } - - - static void Gsub_Free_ChainSubClassRule( TTO_ChainSubClassRule* cscr, - FT_Memory memory ) - { - FREE( cscr->SubstLookupRecord ); - FREE( cscr->Lookahead ); - FREE( cscr->Input ); - FREE( cscr->Backtrack ); - } - - - /* SubClassSet */ - - static FT_Error Load_ChainSubClassSet( - TTO_ChainContextSubstFormat2* ccsf2, - TTO_ChainSubClassSet* cscs, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UShort n = 0, m, count; - FT_ULong cur_offset, new_offset, base_offset; - - TTO_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, - TTO_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 ) ) != TT_Err_Ok ) - goto Fail; - (void)FILE_Seek( cur_offset ); - } - - return TT_Err_Ok; - - Fail: - for ( m = 0; m < n; m++ ) - Gsub_Free_ChainSubClassRule( &cscr[m], memory ); - - FREE( cscr ); - return error; - } - - - static void Gsub_Free_ChainSubClassSet( TTO_ChainSubClassSet* cscs, - FT_Memory memory ) - { - FT_UShort n, count; - - TTO_ChainSubClassRule* cscr; - - - if ( cscs->ChainSubClassRule ) - { - count = cscs->ChainSubClassRuleCount; - cscr = cscs->ChainSubClassRule; - - for ( n = 0; n < count; n++ ) - Gsub_Free_ChainSubClassRule( &cscr[n], memory ); - - FREE( cscr ); - } - } - - static FT_Error Gsub_Load_EmptyOrClassDefinition( TTO_ClassDefinition* cd, - FT_UShort limit, - FT_ULong class_offset, - FT_ULong base_offset, - FT_Stream stream ) - { - FT_Error error; - FT_ULong cur_offset; - - cur_offset = FILE_Pos(); - - if ( class_offset ) - { - if ( !FILE_Seek( class_offset + base_offset ) ) - error = Load_ClassDefinition( cd, limit, stream ); - } - else - error = Load_EmptyClassDefinition ( cd, stream ); - - if (error == TT_Err_Ok) - (void)FILE_Seek( cur_offset ); /* Changes error as a side-effect */ - - return error; - } - - - /* ChainContextSubstFormat2 */ - - static FT_Error Load_ChainContextSubst2( - TTO_ChainContextSubstFormat2* ccsf2, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UShort n = 0, m, count; - FT_ULong cur_offset, new_offset, base_offset; - FT_ULong backtrack_offset, input_offset, lookahead_offset; - - TTO_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 = Load_Coverage( &ccsf2->Coverage, stream ) ) != TT_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 = Gsub_Load_EmptyOrClassDefinition( &ccsf2->BacktrackClassDef, 65535, - backtrack_offset, base_offset, - stream ) ) != TT_Err_Ok ) - goto Fail5; - - if ( ( error = Gsub_Load_EmptyOrClassDefinition( &ccsf2->InputClassDef, count, - input_offset, base_offset, - stream ) ) != TT_Err_Ok ) - goto Fail4; - if ( ( error = Gsub_Load_EmptyOrClassDefinition( &ccsf2->LookaheadClassDef, 65535, - lookahead_offset, base_offset, - stream ) ) != TT_Err_Ok ) - goto Fail3; - - ccsf2->ChainSubClassSet = NULL; - ccsf2->MaxBacktrackLength = 0; - ccsf2->MaxInputLength = 0; - ccsf2->MaxLookaheadLength = 0; - - if ( ALLOC_ARRAY( ccsf2->ChainSubClassSet, count, TTO_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 ) ) != TT_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 TT_Err_Ok; - - Fail1: - for ( m = 0; m < n; m++ ) - Gsub_Free_ChainSubClassSet( &cscs[m], memory ); - - FREE( cscs ); - - Fail2: - Free_ClassDefinition( &ccsf2->LookaheadClassDef, memory ); - - Fail3: - Free_ClassDefinition( &ccsf2->InputClassDef, memory ); - - Fail4: - Free_ClassDefinition( &ccsf2->BacktrackClassDef, memory ); - - Fail5: - Free_Coverage( &ccsf2->Coverage, memory ); - return error; - } - - - static void Gsub_Free_ChainContext2( TTO_ChainContextSubstFormat2* ccsf2, - FT_Memory memory ) - { - FT_UShort n, count; - - TTO_ChainSubClassSet* cscs; - - - if ( ccsf2->ChainSubClassSet ) - { - count = ccsf2->ChainSubClassSetCount; - cscs = ccsf2->ChainSubClassSet; - - for ( n = 0; n < count; n++ ) - Gsub_Free_ChainSubClassSet( &cscs[n], memory ); - - FREE( cscs ); - } - - Free_ClassDefinition( &ccsf2->LookaheadClassDef, memory ); - Free_ClassDefinition( &ccsf2->InputClassDef, memory ); - Free_ClassDefinition( &ccsf2->BacktrackClassDef, memory ); - - Free_Coverage( &ccsf2->Coverage, memory ); - } - - - /* ChainContextSubstFormat3 */ - - static FT_Error Load_ChainContextSubst3( - TTO_ChainContextSubstFormat3* ccsf3, - FT_Stream stream ) - { - FT_Error error; - FT_Memory memory = stream->memory; - - FT_UShort n, nb = 0, ni =0, nl = 0, m, count; - FT_UShort backtrack_count, input_count, lookahead_count; - FT_ULong cur_offset, new_offset, base_offset; - - TTO_Coverage* b; - TTO_Coverage* i; - TTO_Coverage* l; - TTO_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, - TTO_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 = Load_Coverage( &b[nb], stream ) ) != TT_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, TTO_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 = Load_Coverage( &i[ni], stream ) ) != TT_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, - TTO_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 = Load_Coverage( &l[nl], stream ) ) != TT_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, - TTO_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 TT_Err_Ok; - - Fail1: - FREE( slr ); - - Fail2: - for ( m = 0; m < nl; m++ ) - Free_Coverage( &l[m], memory ); - - FREE( l ); - - Fail3: - for ( m = 0; m < ni; m++ ) - Free_Coverage( &i[m], memory ); - - FREE( i ); - - Fail4: - for ( m = 0; m < nb; m++ ) - Free_Coverage( &b[m], memory ); - - FREE( b ); - return error; - } - - - static void Gsub_Free_ChainContext3( TTO_ChainContextSubstFormat3* ccsf3, - FT_Memory memory ) - { - FT_UShort n, count; - - TTO_Coverage* c; - - - FREE( ccsf3->SubstLookupRecord ); - - if ( ccsf3->LookaheadCoverage ) - { - count = ccsf3->LookaheadGlyphCount; - c = ccsf3->LookaheadCoverage; - - for ( n = 0; n < count; n++ ) - Free_Coverage( &c[n], memory ); - - FREE( c ); - } - - if ( ccsf3->InputCoverage ) - { - count = ccsf3->InputGlyphCount; - c = ccsf3->InputCoverage; - - for ( n = 0; n < count; n++ ) - Free_Coverage( &c[n], memory ); - - FREE( c ); - } - - if ( ccsf3->BacktrackCoverage ) - { - count = ccsf3->BacktrackGlyphCount; - c = ccsf3->BacktrackCoverage; - - for ( n = 0; n < count; n++ ) - Free_Coverage( &c[n], memory ); - - FREE( c ); - } - } - - - /* ChainContextSubst */ - - FT_Error Load_ChainContextSubst( TTO_ChainContextSubst* ccs, - FT_Stream stream ) - { - FT_Error error; - - - 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 TTO_Err_Invalid_GSUB_SubTable_Format; - } - - return TT_Err_Ok; /* never reached */ - } - - - void Free_ChainContextSubst( TTO_ChainContextSubst* ccs, - FT_Memory memory ) - { - switch ( ccs->SubstFormat ) - { - case 1: - Gsub_Free_ChainContext1( &ccs->ccsf.ccsf1, memory ); - break; - - case 2: - Gsub_Free_ChainContext2( &ccs->ccsf.ccsf2, memory ); - break; - - case 3: - Gsub_Free_ChainContext3( &ccs->ccsf.ccsf3, memory ); - break; - } - } - - - static FT_Error Lookup_ChainContextSubst1( - TTO_GSUBHeader* gsub, - TTO_ChainContextSubstFormat1* ccsf1, - OTL_Buffer buffer, - FT_UShort flags, - FT_UShort context_length, - int nesting_level ) - { - FT_UShort index, property; - FT_UShort i, j, k, num_csr; - FT_UShort bgc, igc, lgc; - FT_Error error; - - TTO_ChainSubRule* csr; - TTO_ChainSubRule curr_csr; - TTO_GDEFHeader* gdef; - - - gdef = gsub->gdef; - - if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) ) - return error; - - error = 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 != TTO_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 != TTO_Err_Not_Covered ) - return error; - - if ( j + igc - i + lgc == (FT_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 != TTO_Err_Not_Covered ) - return error; - - if ( j + lgc - i == (FT_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 TTO_Err_Not_Covered; - } - - - static FT_Error Lookup_ChainContextSubst2( - TTO_GSUBHeader* gsub, - TTO_ChainContextSubstFormat2* ccsf2, - OTL_Buffer buffer, - FT_UShort flags, - FT_UShort context_length, - int nesting_level ) - { - FT_UShort index, property; - FT_Memory memory; - FT_Error error; - FT_UShort i, j, k; - FT_UShort bgc, igc, lgc; - FT_UShort known_backtrack_classes, - known_input_classes, - known_lookahead_classes; - - FT_UShort* backtrack_classes; - FT_UShort* input_classes; - FT_UShort* lookahead_classes; - - FT_UShort* bc; - FT_UShort* ic; - FT_UShort* lc; - - TTO_ChainSubClassSet* cscs; - TTO_ChainSubClassRule ccsr; - TTO_GDEFHeader* gdef; - - - gdef = gsub->gdef; - memory = gsub->memory; - - 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 = Coverage_Index( &ccsf2->Coverage, IN_CURGLYPH(), &index ); - if ( error ) - return error; - - if ( ALLOC_ARRAY( backtrack_classes, ccsf2->MaxBacktrackLength, FT_UShort ) ) - return error; - known_backtrack_classes = 0; - - if ( ALLOC_ARRAY( input_classes, ccsf2->MaxInputLength, FT_UShort ) ) - goto End3; - known_input_classes = 1; - - if ( ALLOC_ARRAY( lookahead_classes, ccsf2->MaxLookaheadLength, FT_UShort ) ) - goto End2; - known_lookahead_classes = 0; - - error = Get_Class( &ccsf2->InputClassDef, IN_CURGLYPH(), - &input_classes[0], NULL ); - if ( error && error != TTO_Err_Not_Covered ) - goto End1; - - cscs = &ccsf2->ChainSubClassSet[input_classes[0]]; - if ( !cscs ) - { - error = TTO_Err_Invalid_GSUB_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 != TTO_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 = Get_Class( &ccsf2->BacktrackClassDef, OUT_GLYPH( j ), - &backtrack_classes[i], NULL ); - if ( error && error != TTO_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 != TTO_Err_Not_Covered ) - goto End1; - - if ( j + igc - i + lgc == (FT_Int)buffer->in_length ) - goto next_chainsubclassrule; - j++; - } - - if ( i >= known_input_classes ) - { - error = Get_Class( &ccsf2->InputClassDef, IN_GLYPH( j ), - &input_classes[i], NULL ); - if ( error && error != TTO_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 != TTO_Err_Not_Covered ) - goto End1; - - if ( j + lgc - i == (FT_Int)buffer->in_length ) - goto next_chainsubclassrule; - j++; - } - - if ( i >= known_lookahead_classes ) - { - error = Get_Class( &ccsf2->LookaheadClassDef, IN_GLYPH( j ), - &lookahead_classes[i], NULL ); - if ( error && error != TTO_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 = TTO_Err_Not_Covered; - - End1: - FREE( lookahead_classes ); - - End2: - FREE( input_classes ); - - End3: - FREE( backtrack_classes ); - return error; - } - - - static FT_Error Lookup_ChainContextSubst3( - TTO_GSUBHeader* gsub, - TTO_ChainContextSubstFormat3* ccsf3, - OTL_Buffer buffer, - FT_UShort flags, - FT_UShort context_length, - int nesting_level ) - { - FT_UShort index, i, j, property; - FT_UShort bgc, igc, lgc; - FT_Error error; - - TTO_Coverage* bc; - TTO_Coverage* ic; - TTO_Coverage* lc; - TTO_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 TTO_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 TTO_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 != TTO_Err_Not_Covered ) - return error; - - if ( j + 1 == bgc - i ) - return TTO_Err_Not_Covered; - j--; - } - - error = 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 != TTO_Err_Not_Covered ) - return error; - - if ( j + igc - i + lgc == (FT_Int)buffer->in_length ) - return TTO_Err_Not_Covered; - j++; - } - - error = 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 != TTO_Err_Not_Covered ) - return error; - - if ( j + lgc - i == (FT_Int)buffer->in_length ) - return TTO_Err_Not_Covered; - j++; - } - - error = 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 FT_Error Lookup_ChainContextSubst( - TTO_GSUBHeader* gsub, - TTO_ChainContextSubst* ccs, - OTL_Buffer buffer, - FT_UShort flags, - FT_UShort context_length, - int nesting_level ) - { - 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 TTO_Err_Invalid_GSUB_SubTable_Format; - } - - return TT_Err_Ok; /* never reached */ - } - - - - /*********** - * GSUB API - ***********/ - - - EXPORT_FUNC - FT_Error TT_GSUB_Select_Script( TTO_GSUBHeader* gsub, - FT_ULong script_tag, - FT_UShort* script_index ) - { - FT_UShort n; - - TTO_ScriptList* sl; - TTO_ScriptRecord* sr; - - - if ( !gsub || !script_index ) - return TT_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 TT_Err_Ok; - } - - return TTO_Err_Not_Covered; - } - - - EXPORT_FUNC - FT_Error TT_GSUB_Select_Language( TTO_GSUBHeader* gsub, - FT_ULong language_tag, - FT_UShort script_index, - FT_UShort* language_index, - FT_UShort* req_feature_index ) - { - FT_UShort n; - - TTO_ScriptList* sl; - TTO_ScriptRecord* sr; - TTO_Script* s; - TTO_LangSysRecord* lsr; - - - if ( !gsub || !language_index || !req_feature_index ) - return TT_Err_Invalid_Argument; - - sl = &gsub->ScriptList; - sr = sl->ScriptRecord; - - if ( script_index >= sl->ScriptCount ) - return TT_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 TT_Err_Ok; - } - - return TTO_Err_Not_Covered; - } - - - /* selecting 0xFFFF for language_index asks for the values of the - default language (DefaultLangSys) */ - - EXPORT_FUNC - FT_Error TT_GSUB_Select_Feature( TTO_GSUBHeader* gsub, - FT_ULong feature_tag, - FT_UShort script_index, - FT_UShort language_index, - FT_UShort* feature_index ) - { - FT_UShort n; - - TTO_ScriptList* sl; - TTO_ScriptRecord* sr; - TTO_Script* s; - TTO_LangSysRecord* lsr; - TTO_LangSys* ls; - FT_UShort* fi; - - TTO_FeatureList* fl; - TTO_FeatureRecord* fr; - - - if ( !gsub || !feature_index ) - return TT_Err_Invalid_Argument; - - sl = &gsub->ScriptList; - sr = sl->ScriptRecord; - - fl = &gsub->FeatureList; - fr = fl->FeatureRecord; - - if ( script_index >= sl->ScriptCount ) - return TT_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 TT_Err_Invalid_Argument; - - ls = &lsr[language_index].LangSys; - } - - fi = ls->FeatureIndex; - - for ( n = 0; n < ls->FeatureCount; n++ ) - { - if ( fi[n] >= fl->FeatureCount ) - return TTO_Err_Invalid_GSUB_SubTable_Format; - - if ( feature_tag == fr[fi[n]].FeatureTag ) - { - *feature_index = fi[n]; - - return TT_Err_Ok; - } - } - - return TTO_Err_Not_Covered; - } - - - /* The next three functions return a null-terminated list */ - - EXPORT_FUNC - FT_Error TT_GSUB_Query_Scripts( TTO_GSUBHeader* gsub, - FT_ULong** script_tag_list ) - { - FT_UShort n; - FT_Error error; - FT_Memory memory; - FT_ULong* stl; - - TTO_ScriptList* sl; - TTO_ScriptRecord* sr; - - - if ( !gsub || !script_tag_list ) - return TT_Err_Invalid_Argument; - - memory = gsub->memory; - - sl = &gsub->ScriptList; - sr = sl->ScriptRecord; - - if ( ALLOC_ARRAY( stl, sl->ScriptCount + 1, FT_ULong ) ) - return error; - - for ( n = 0; n < sl->ScriptCount; n++ ) - stl[n] = sr[n].ScriptTag; - stl[n] = 0; - - *script_tag_list = stl; - - return TT_Err_Ok; - } - - - EXPORT_FUNC - FT_Error TT_GSUB_Query_Languages( TTO_GSUBHeader* gsub, - FT_UShort script_index, - FT_ULong** language_tag_list ) - { - FT_UShort n; - FT_Error error; - FT_Memory memory; - FT_ULong* ltl; - - TTO_ScriptList* sl; - TTO_ScriptRecord* sr; - TTO_Script* s; - TTO_LangSysRecord* lsr; - - - if ( !gsub || !language_tag_list ) - return TT_Err_Invalid_Argument; - - memory = gsub->memory; - - sl = &gsub->ScriptList; - sr = sl->ScriptRecord; - - if ( script_index >= sl->ScriptCount ) - return TT_Err_Invalid_Argument; - - s = &sr[script_index].Script; - lsr = s->LangSysRecord; - - if ( ALLOC_ARRAY( ltl, s->LangSysCount + 1, FT_ULong ) ) - return error; - - for ( n = 0; n < s->LangSysCount; n++ ) - ltl[n] = lsr[n].LangSysTag; - ltl[n] = 0; - - *language_tag_list = ltl; - - return TT_Err_Ok; - } - - - /* selecting 0xFFFF for language_index asks for the values of the - default language (DefaultLangSys) */ - - EXPORT_FUNC - FT_Error TT_GSUB_Query_Features( TTO_GSUBHeader* gsub, - FT_UShort script_index, - FT_UShort language_index, - FT_ULong** feature_tag_list ) - { - FT_UShort n; - FT_Error error; - FT_Memory memory; - FT_ULong* ftl; - - TTO_ScriptList* sl; - TTO_ScriptRecord* sr; - TTO_Script* s; - TTO_LangSysRecord* lsr; - TTO_LangSys* ls; - FT_UShort* fi; - - TTO_FeatureList* fl; - TTO_FeatureRecord* fr; - - - if ( !gsub || !feature_tag_list ) - return TT_Err_Invalid_Argument; - - memory = gsub->memory; - - sl = &gsub->ScriptList; - sr = sl->ScriptRecord; - - fl = &gsub->FeatureList; - fr = fl->FeatureRecord; - - if ( script_index >= sl->ScriptCount ) - return TT_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 TT_Err_Invalid_Argument; - - ls = &lsr[language_index].LangSys; - } - - fi = ls->FeatureIndex; - - if ( ALLOC_ARRAY( ftl, ls->FeatureCount + 1, FT_ULong ) ) - return error; - - for ( n = 0; n < ls->FeatureCount; n++ ) - { - if ( fi[n] >= fl->FeatureCount ) - { - FREE( ftl ); - return TTO_Err_Invalid_GSUB_SubTable_Format; - } - ftl[n] = fr[fi[n]].FeatureTag; - } - ftl[n] = 0; - - *feature_tag_list = ftl; - - return TT_Err_Ok; - } - - - /* Do an individual subtable lookup. Returns TT_Err_Ok if substitution - has been done, or TTO_Err_Not_Covered if not. */ - - static FT_Error GSub_Do_Glyph_Lookup( TTO_GSUBHeader* gsub, - FT_UShort lookup_index, - OTL_Buffer buffer, - FT_UShort context_length, - int nesting_level ) - { - FT_Error error = TTO_Err_Not_Covered; - FT_UShort i, flags, lookup_count; - TTO_Lookup* lo; - - - nesting_level++; - - if ( nesting_level > TTO_MAX_NESTING_LEVEL ) - return TTO_Err_Too_Many_Nested_Contexts; - - lookup_count = gsub->LookupList.LookupCount; - if (lookup_index >= lookup_count) - return error; - - lo = &gsub->LookupList.Lookup[lookup_index]; - flags = lo->LookupFlag; - - for ( i = 0; i < lo->SubTableCount; i++ ) - { - switch ( lo->LookupType ) - { - case GSUB_LOOKUP_SINGLE: - error = Lookup_SingleSubst( &lo->SubTable[i].st.gsub.single, - buffer, - flags, context_length, gsub->gdef ); - break; - - case GSUB_LOOKUP_MULTIPLE: - error = Lookup_MultipleSubst( &lo->SubTable[i].st.gsub.multiple, - buffer, - flags, context_length, gsub->gdef ); - break; - - case GSUB_LOOKUP_ALTERNATE: - error = Lookup_AlternateSubst( gsub, - &lo->SubTable[i].st.gsub.alternate, - buffer, - flags, context_length, gsub->gdef ); - break; - - case GSUB_LOOKUP_LIGATURE: - error = Lookup_LigatureSubst( &lo->SubTable[i].st.gsub.ligature, - buffer, - flags, context_length, gsub->gdef ); - break; - - case GSUB_LOOKUP_CONTEXT: - error = Lookup_ContextSubst( gsub, &lo->SubTable[i].st.gsub.context, - buffer, - flags, context_length, nesting_level ); - break; - - case GSUB_LOOKUP_CHAIN: - error = Lookup_ChainContextSubst( gsub, - &lo->SubTable[i].st.gsub.chain, - buffer, - flags, context_length, - nesting_level ); - break; - } - - /* Check whether we have a successful substitution or an error other - than TTO_Err_Not_Covered */ - - if ( error != TTO_Err_Not_Covered ) - return error; - } - - return TTO_Err_Not_Covered; - } - - /* apply one lookup to the input string object */ - - static FT_Error GSub_Do_String_Lookup( TTO_GSUBHeader* gsub, - FT_UShort lookup_index, - OTL_Buffer buffer ) - { - FT_Error error, retError = TTO_Err_Not_Covered; - - FT_UInt* properties = gsub->LookupList.Properties; - - int nesting_level = 0; - - - while ( buffer->in_pos < buffer->in_length ) - { - if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] ) - { - /* 0xFFFF indicates that we don't have a context length yet */ - error = GSub_Do_Glyph_Lookup( gsub, lookup_index, buffer, - 0xFFFF, nesting_level ); - if ( error ) - { - if ( error != TTO_Err_Not_Covered ) - return error; - } - else - retError = error; - } - else - error = TTO_Err_Not_Covered; - - if ( error == TTO_Err_Not_Covered ) - if ( otl_buffer_copy_output_glyph ( buffer ) ) - return error; - } - - return retError; - } - - - EXPORT_FUNC - FT_Error TT_GSUB_Add_Feature( TTO_GSUBHeader* gsub, - FT_UShort feature_index, - FT_UInt property ) - { - FT_UShort i; - - TTO_Feature feature; - FT_UInt* properties; - FT_UShort* index; - FT_UShort lookup_count; - - /* Each feature can only be added once */ - - if ( !gsub || - feature_index >= gsub->FeatureList.FeatureCount || - gsub->FeatureList.ApplyCount == gsub->FeatureList.FeatureCount ) - return TT_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++ ) - { - FT_UShort lookup_index = index[i]; - if (lookup_index < lookup_count) - properties[lookup_index] |= property; - } - - return TT_Err_Ok; - } - - - EXPORT_FUNC - FT_Error TT_GSUB_Clear_Features( TTO_GSUBHeader* gsub ) - { - FT_UShort i; - - FT_UInt* properties; - - - if ( !gsub ) - return TT_Err_Invalid_Argument; - - gsub->FeatureList.ApplyCount = 0; - - properties = gsub->LookupList.Properties; - - for ( i = 0; i < gsub->LookupList.LookupCount; i++ ) - properties[i] = 0; - - return TT_Err_Ok; - } - - - EXPORT_FUNC - FT_Error TT_GSUB_Register_Alternate_Function( TTO_GSUBHeader* gsub, - TTO_AltFunction altfunc, - void* data ) - { - if ( !gsub ) - return TT_Err_Invalid_Argument; - - gsub->altfunc = altfunc; - gsub->data = data; - - return TT_Err_Ok; - } - - - EXPORT_FUNC - FT_Error TT_GSUB_Apply_String( TTO_GSUBHeader* gsub, - OTL_Buffer buffer ) - { - FT_Error error, retError = TTO_Err_Not_Covered; - FT_UShort i, j, feature_index, lookup_count; - TTO_Feature feature; - - if ( !gsub || - !buffer || buffer->in_length == 0 || buffer->in_pos >= buffer->in_length ) - return TT_Err_Invalid_Argument; - - lookup_count = gsub->LookupList.LookupCount; - - for ( i = 0; i < gsub->FeatureList.ApplyCount; i++) - { - feature_index = gsub->FeatureList.ApplyOrder[i]; - feature = gsub->FeatureList.FeatureRecord[feature_index].Feature; - - for ( j = 0; j < feature.LookupListCount; j++ ) - { - FT_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 != TTO_Err_Not_Covered ) - goto End; - } - else - retError = error; - - error = otl_buffer_swap( buffer ); - if ( error ) - goto End; - } - } - - error = retError; - - End: - return error; - } - - -/* END */ |