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