/libs/pango/src/pango/opentype/harfbuzz-gsub.c
C | 3158 lines | 2060 code | 984 blank | 114 comment | 458 complexity | 4eb75e5f6b901456600e769bde467f36 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-3.0, GPL-3.0, GPL-2.0, AGPL-3.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, LGPL-2.0
Large files files are truncated, but you can click here to view the full file
- /*
- * 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_Font font,
- HB_GSUBHeader** retptr,
- HB_GDEFHeader* gdef )
- {
- HB_Stream stream = font->stream;
- 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, stream,
- 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;
- HB_Bool* d;
- if ( ACCESS_Frame( 4L ) )
- return error;
- scr->GlyphCount = GET_UShort();
- scr->SubstCount = GET_UShort();
- if ( scr->GlyphCount > csf2->MaxContextLength )
- csf2->MaxContextLength = scr->GlyphCount;
- FORGET_Frame();
- scr->Class = NULL;
- count = scr->GlyphCount - 1; /* only GlyphCount - 1 elements */
- if ( ALLOC_ARRAY( scr->Class, count, HB_UShort ) )
- return error;
- c = scr->Class;
- d = csf2->ClassDef.Defined;
- if ( ACCESS_Frame( count * 2L ) )
- goto Fail2;
- for ( n = 0; n < count; n++ )
- {
- c[n] = GET_UShort();
- /* We check whether the specific class is used at all. If not,
- class 0 is used instead. */
- if ( !d[c[n]] )
- c[n] = 0;
- }
- FORGET_Frame();
- scr->SubstLookupRecord = NULL;
- count = scr->SubstCount;
- if ( ALLOC_ARRAY( scr->SubstLookupRecord, count, 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 ( 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;
- HB_Bool* d;
- if ( ACCESS_Frame( 2L ) )
- return error;
- cscr->BacktrackGlyphCount = GET_UShort();
- FORGET_Frame();
- if ( cscr->BacktrackGlyphCount > ccsf2->MaxBacktrackLength )
- ccsf2->MaxBacktrackLength = cscr->BacktrackGlyphCount;
- cscr->Backtrack = NULL;
- count = cscr->BacktrackGlyphCount;
- if ( ALLOC_ARRAY( cscr->Backtrack, count, HB_UShort ) )
- return error;
- b = cscr->Backtrack;
- d = ccsf2->BacktrackClassDef.Defined;
- if ( ACCESS_Frame( count * 2L ) )
- goto Fail4;
- for ( n = 0; n < count; n++ )
- {
- b[n] = GET_UShort();
- /* We check whether the specific class is used at all. If not,
- class 0 is used instead. */
- if ( !d[b[n]] )
- b[n] = 0;
- }
- FORGET_Frame();
- if ( ACCESS_Frame( 2L ) )
- goto Fail4;
- cscr->InputGlyphCount = GET_UShort();
- FORGET_Frame();
- if ( cscr->InputGlyphCount > ccsf2->MaxInputLength )
- ccsf2->MaxInputLength = cscr->InputGlyphCount;
- cscr->Input = NULL;
- count = cscr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
- if ( ALLOC_ARRAY( cscr->Input, count, HB_UShort ) )
- goto Fail4;
- i = cscr->Input;
- d = ccsf2->InputClassDef.Defined;
- if ( ACCESS_Frame( count * 2L ) )
- goto Fail3;
- for ( n = 0; n < count; n++ )
- {
- i[n] = GET_UShort();
- if ( !d[i[n]] )
- i[n] = 0;
- }
- FORGET_Frame();
- if ( ACCESS_Frame( 2L ) )
- goto Fail3;
- cscr->LookaheadGlyphCount = GET_UShort…
Large files files are truncated, but you can click here to view the full file