harfbuzz-gsub.c revision d124f9692dc8dad8f5f77c293fe6d4ec1a0c02ea
15569331642446be05292e3e1f8a51218827168cdclaireho/*
25569331642446be05292e3e1f8a51218827168cdclaireho * Copyright (C) 1998-2004  David Turner and Werner Lemberg
35569331642446be05292e3e1f8a51218827168cdclaireho * Copyright (C) 2006  Behdad Esfahbod
45569331642446be05292e3e1f8a51218827168cdclaireho * Copyright (C) 2007  Red Hat, Inc.
55569331642446be05292e3e1f8a51218827168cdclaireho *
65569331642446be05292e3e1f8a51218827168cdclaireho * This is part of HarfBuzz, an OpenType Layout engine library.
75569331642446be05292e3e1f8a51218827168cdclaireho *
85569331642446be05292e3e1f8a51218827168cdclaireho * Permission is hereby granted, without written agreement and without
95569331642446be05292e3e1f8a51218827168cdclaireho * license or royalty fees, to use, copy, modify, and distribute this
105569331642446be05292e3e1f8a51218827168cdclaireho * software and its documentation for any purpose, provided that the
115569331642446be05292e3e1f8a51218827168cdclaireho * above copyright notice and the following two paragraphs appear in
125569331642446be05292e3e1f8a51218827168cdclaireho * all copies of this software.
135569331642446be05292e3e1f8a51218827168cdclaireho *
145569331642446be05292e3e1f8a51218827168cdclaireho * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
155569331642446be05292e3e1f8a51218827168cdclaireho * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
165569331642446be05292e3e1f8a51218827168cdclaireho * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
175569331642446be05292e3e1f8a51218827168cdclaireho * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
185569331642446be05292e3e1f8a51218827168cdclaireho * DAMAGE.
195569331642446be05292e3e1f8a51218827168cdclaireho *
205569331642446be05292e3e1f8a51218827168cdclaireho * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
215569331642446be05292e3e1f8a51218827168cdclaireho * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
225569331642446be05292e3e1f8a51218827168cdclaireho * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
235569331642446be05292e3e1f8a51218827168cdclaireho * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
245569331642446be05292e3e1f8a51218827168cdclaireho * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
255569331642446be05292e3e1f8a51218827168cdclaireho *
265569331642446be05292e3e1f8a51218827168cdclaireho * Red Hat Author(s): Behdad Esfahbod
275569331642446be05292e3e1f8a51218827168cdclaireho */
285569331642446be05292e3e1f8a51218827168cdclaireho
295569331642446be05292e3e1f8a51218827168cdclaireho#include "harfbuzz-impl.h"
305569331642446be05292e3e1f8a51218827168cdclaireho#include "harfbuzz-gsub-private.h"
315569331642446be05292e3e1f8a51218827168cdclaireho#include "harfbuzz-open-private.h"
325569331642446be05292e3e1f8a51218827168cdclaireho#include "harfbuzz-gdef-private.h"
335569331642446be05292e3e1f8a51218827168cdclaireho
345569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  GSUB_Do_Glyph_Lookup( HB_GSUBHeader*   gsub,
355569331642446be05292e3e1f8a51218827168cdclaireho				       HB_UShort         lookup_index,
365569331642446be05292e3e1f8a51218827168cdclaireho				       HB_Buffer        buffer,
375569331642446be05292e3e1f8a51218827168cdclaireho				       HB_UShort         context_length,
385569331642446be05292e3e1f8a51218827168cdclaireho				       int               nesting_level );
395569331642446be05292e3e1f8a51218827168cdclaireho
405569331642446be05292e3e1f8a51218827168cdclaireho
415569331642446be05292e3e1f8a51218827168cdclaireho
425569331642446be05292e3e1f8a51218827168cdclaireho/**********************
435569331642446be05292e3e1f8a51218827168cdclaireho * Auxiliary functions
445569331642446be05292e3e1f8a51218827168cdclaireho **********************/
455569331642446be05292e3e1f8a51218827168cdclaireho
465569331642446be05292e3e1f8a51218827168cdclaireho
475569331642446be05292e3e1f8a51218827168cdclaireho
485569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_Load_GSUB_Table( HB_Stream stream,
495569331642446be05292e3e1f8a51218827168cdclaireho			      HB_GSUBHeader** retptr,
505569331642446be05292e3e1f8a51218827168cdclaireho			      HB_GDEFHeader*  gdef,
515569331642446be05292e3e1f8a51218827168cdclaireho                              HB_Stream       gdefStream )
525569331642446be05292e3e1f8a51218827168cdclaireho{
535569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error         error;
545569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt         cur_offset, new_offset, base_offset;
555569331642446be05292e3e1f8a51218827168cdclaireho
565569331642446be05292e3e1f8a51218827168cdclaireho  HB_GSUBHeader*  gsub;
575569331642446be05292e3e1f8a51218827168cdclaireho
585569331642446be05292e3e1f8a51218827168cdclaireho  if ( !retptr )
595569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
605569331642446be05292e3e1f8a51218827168cdclaireho
615569331642446be05292e3e1f8a51218827168cdclaireho  if ( GOTO_Table( TTAG_GSUB ) )
625569331642446be05292e3e1f8a51218827168cdclaireho    return error;
635569331642446be05292e3e1f8a51218827168cdclaireho
645569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
655569331642446be05292e3e1f8a51218827168cdclaireho
665569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC ( gsub, sizeof( *gsub ) ) )
675569331642446be05292e3e1f8a51218827168cdclaireho      return error;
685569331642446be05292e3e1f8a51218827168cdclaireho
695569331642446be05292e3e1f8a51218827168cdclaireho
705569331642446be05292e3e1f8a51218827168cdclaireho  /* skip version */
715569331642446be05292e3e1f8a51218827168cdclaireho
725569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( base_offset + 4L ) ||
735569331642446be05292e3e1f8a51218827168cdclaireho       ACCESS_Frame( 2L ) )
745569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
755569331642446be05292e3e1f8a51218827168cdclaireho
765569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
775569331642446be05292e3e1f8a51218827168cdclaireho
785569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
795569331642446be05292e3e1f8a51218827168cdclaireho
805569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
815569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
825569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_ScriptList( &gsub->ScriptList,
835569331642446be05292e3e1f8a51218827168cdclaireho				  stream ) ) != HB_Err_Ok )
845569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
855569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
865569331642446be05292e3e1f8a51218827168cdclaireho
875569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
885569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
895569331642446be05292e3e1f8a51218827168cdclaireho
905569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
915569331642446be05292e3e1f8a51218827168cdclaireho
925569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
935569331642446be05292e3e1f8a51218827168cdclaireho
945569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
955569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
965569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_FeatureList( &gsub->FeatureList,
975569331642446be05292e3e1f8a51218827168cdclaireho				   stream ) ) != HB_Err_Ok )
985569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
995569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
1005569331642446be05292e3e1f8a51218827168cdclaireho
1015569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
1025569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
1035569331642446be05292e3e1f8a51218827168cdclaireho
1045569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
1055569331642446be05292e3e1f8a51218827168cdclaireho
1065569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
1075569331642446be05292e3e1f8a51218827168cdclaireho
1085569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
1095569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
1105569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_LookupList( &gsub->LookupList,
1115569331642446be05292e3e1f8a51218827168cdclaireho				  stream, HB_Type_GSUB ) ) != HB_Err_Ok )
1125569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
1135569331642446be05292e3e1f8a51218827168cdclaireho
1145569331642446be05292e3e1f8a51218827168cdclaireho  gsub->gdef = gdef;      /* can be NULL */
1155569331642446be05292e3e1f8a51218827168cdclaireho
1165569331642446be05292e3e1f8a51218827168cdclaireho  if ( ( error =  _HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( gdef, gdefStream,
1175569331642446be05292e3e1f8a51218827168cdclaireho								     gsub->LookupList.Lookup,
1185569331642446be05292e3e1f8a51218827168cdclaireho								     gsub->LookupList.LookupCount ) ) )
1195569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail1;
1205569331642446be05292e3e1f8a51218827168cdclaireho
1215569331642446be05292e3e1f8a51218827168cdclaireho  *retptr = gsub;
1225569331642446be05292e3e1f8a51218827168cdclaireho
1235569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
1245569331642446be05292e3e1f8a51218827168cdclaireho
1255569331642446be05292e3e1f8a51218827168cdclairehoFail1:
1265569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_LookupList( &gsub->LookupList, HB_Type_GSUB );
1275569331642446be05292e3e1f8a51218827168cdclaireho
1285569331642446be05292e3e1f8a51218827168cdclairehoFail2:
1295569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_FeatureList( &gsub->FeatureList );
1305569331642446be05292e3e1f8a51218827168cdclaireho
1315569331642446be05292e3e1f8a51218827168cdclairehoFail3:
1325569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_ScriptList( &gsub->ScriptList );
1335569331642446be05292e3e1f8a51218827168cdclaireho
1345569331642446be05292e3e1f8a51218827168cdclairehoFail4:
1355569331642446be05292e3e1f8a51218827168cdclaireho  FREE ( gsub );
1365569331642446be05292e3e1f8a51218827168cdclaireho
1375569331642446be05292e3e1f8a51218827168cdclaireho
1385569331642446be05292e3e1f8a51218827168cdclaireho  return error;
1395569331642446be05292e3e1f8a51218827168cdclaireho}
1405569331642446be05292e3e1f8a51218827168cdclaireho
1415569331642446be05292e3e1f8a51218827168cdclaireho
1425569331642446be05292e3e1f8a51218827168cdclairehoHB_Error   HB_Done_GSUB_Table( HB_GSUBHeader* gsub )
1435569331642446be05292e3e1f8a51218827168cdclaireho{
1445569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_LookupList( &gsub->LookupList, HB_Type_GSUB );
1455569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_FeatureList( &gsub->FeatureList );
1465569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_ScriptList( &gsub->ScriptList );
1475569331642446be05292e3e1f8a51218827168cdclaireho
1485569331642446be05292e3e1f8a51218827168cdclaireho  FREE( gsub );
1495569331642446be05292e3e1f8a51218827168cdclaireho
1505569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
1515569331642446be05292e3e1f8a51218827168cdclaireho}
1525569331642446be05292e3e1f8a51218827168cdclaireho
1535569331642446be05292e3e1f8a51218827168cdclaireho/*****************************
1545569331642446be05292e3e1f8a51218827168cdclaireho * SubTable related functions
1555569331642446be05292e3e1f8a51218827168cdclaireho *****************************/
1565569331642446be05292e3e1f8a51218827168cdclaireho
1575569331642446be05292e3e1f8a51218827168cdclaireho
1585569331642446be05292e3e1f8a51218827168cdclaireho/* LookupType 1 */
1595569331642446be05292e3e1f8a51218827168cdclaireho
1605569331642446be05292e3e1f8a51218827168cdclaireho/* SingleSubstFormat1 */
1615569331642446be05292e3e1f8a51218827168cdclaireho/* SingleSubstFormat2 */
1625569331642446be05292e3e1f8a51218827168cdclaireho
1635569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_SingleSubst( HB_GSUB_SubTable* st,
1645569331642446be05292e3e1f8a51218827168cdclaireho				   HB_Stream         stream )
1655569331642446be05292e3e1f8a51218827168cdclaireho{
1665569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
1675569331642446be05292e3e1f8a51218827168cdclaireho  HB_SingleSubst*  ss = &st->single;
1685569331642446be05292e3e1f8a51218827168cdclaireho
1695569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort n, count;
1705569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt cur_offset, new_offset, base_offset;
1715569331642446be05292e3e1f8a51218827168cdclaireho
1725569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*  s;
1735569331642446be05292e3e1f8a51218827168cdclaireho
1745569331642446be05292e3e1f8a51218827168cdclaireho
1755569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
1765569331642446be05292e3e1f8a51218827168cdclaireho
1775569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 4L ) )
1785569331642446be05292e3e1f8a51218827168cdclaireho    return error;
1795569331642446be05292e3e1f8a51218827168cdclaireho
1805569331642446be05292e3e1f8a51218827168cdclaireho  ss->SubstFormat = GET_UShort();
1815569331642446be05292e3e1f8a51218827168cdclaireho  new_offset      = GET_UShort() + base_offset;
1825569331642446be05292e3e1f8a51218827168cdclaireho
1835569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
1845569331642446be05292e3e1f8a51218827168cdclaireho
1855569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
1865569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
1875569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_Coverage( &ss->Coverage, stream ) ) != HB_Err_Ok )
1885569331642446be05292e3e1f8a51218827168cdclaireho    return error;
1895569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
1905569331642446be05292e3e1f8a51218827168cdclaireho
1915569331642446be05292e3e1f8a51218827168cdclaireho  switch ( ss->SubstFormat )
1925569331642446be05292e3e1f8a51218827168cdclaireho  {
1935569331642446be05292e3e1f8a51218827168cdclaireho  case 1:
1945569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
1955569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail2;
1965569331642446be05292e3e1f8a51218827168cdclaireho
1975569331642446be05292e3e1f8a51218827168cdclaireho    ss->ssf.ssf1.DeltaGlyphID = GET_UShort();
1985569331642446be05292e3e1f8a51218827168cdclaireho
1995569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
2005569331642446be05292e3e1f8a51218827168cdclaireho
2015569331642446be05292e3e1f8a51218827168cdclaireho    break;
2025569331642446be05292e3e1f8a51218827168cdclaireho
2035569331642446be05292e3e1f8a51218827168cdclaireho  case 2:
2045569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
2055569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail2;
2065569331642446be05292e3e1f8a51218827168cdclaireho
2075569331642446be05292e3e1f8a51218827168cdclaireho    count = ss->ssf.ssf2.GlyphCount = GET_UShort();
2085569331642446be05292e3e1f8a51218827168cdclaireho
2095569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
2105569331642446be05292e3e1f8a51218827168cdclaireho
2115569331642446be05292e3e1f8a51218827168cdclaireho    ss->ssf.ssf2.Substitute = NULL;
2125569331642446be05292e3e1f8a51218827168cdclaireho
2135569331642446be05292e3e1f8a51218827168cdclaireho    if ( ALLOC_ARRAY( ss->ssf.ssf2.Substitute, count, HB_UShort ) )
2145569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail2;
2155569331642446be05292e3e1f8a51218827168cdclaireho
2165569331642446be05292e3e1f8a51218827168cdclaireho    s = ss->ssf.ssf2.Substitute;
2175569331642446be05292e3e1f8a51218827168cdclaireho
2185569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( count * 2L ) )
2195569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
2205569331642446be05292e3e1f8a51218827168cdclaireho
2215569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
2225569331642446be05292e3e1f8a51218827168cdclaireho      s[n] = GET_UShort();
2235569331642446be05292e3e1f8a51218827168cdclaireho
2245569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
2255569331642446be05292e3e1f8a51218827168cdclaireho
2265569331642446be05292e3e1f8a51218827168cdclaireho    break;
2275569331642446be05292e3e1f8a51218827168cdclaireho
2285569331642446be05292e3e1f8a51218827168cdclaireho  default:
2295569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable_Format);
2305569331642446be05292e3e1f8a51218827168cdclaireho  }
2315569331642446be05292e3e1f8a51218827168cdclaireho
2325569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
2335569331642446be05292e3e1f8a51218827168cdclaireho
2345569331642446be05292e3e1f8a51218827168cdclairehoFail1:
2355569331642446be05292e3e1f8a51218827168cdclaireho  FREE( s );
2365569331642446be05292e3e1f8a51218827168cdclaireho
2375569331642446be05292e3e1f8a51218827168cdclairehoFail2:
2385569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &ss->Coverage );
2395569331642446be05292e3e1f8a51218827168cdclaireho  return error;
2405569331642446be05292e3e1f8a51218827168cdclaireho}
2415569331642446be05292e3e1f8a51218827168cdclaireho
2425569331642446be05292e3e1f8a51218827168cdclaireho
2435569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_SingleSubst( HB_GSUB_SubTable* st )
2445569331642446be05292e3e1f8a51218827168cdclaireho{
2455569331642446be05292e3e1f8a51218827168cdclaireho  HB_SingleSubst*  ss = &st->single;
2465569331642446be05292e3e1f8a51218827168cdclaireho
2475569331642446be05292e3e1f8a51218827168cdclaireho  switch ( ss->SubstFormat )
2485569331642446be05292e3e1f8a51218827168cdclaireho  {
2495569331642446be05292e3e1f8a51218827168cdclaireho  case 1:
2505569331642446be05292e3e1f8a51218827168cdclaireho    break;
2515569331642446be05292e3e1f8a51218827168cdclaireho
2525569331642446be05292e3e1f8a51218827168cdclaireho  case 2:
2535569331642446be05292e3e1f8a51218827168cdclaireho    FREE( ss->ssf.ssf2.Substitute );
2545569331642446be05292e3e1f8a51218827168cdclaireho    break;
2555569331642446be05292e3e1f8a51218827168cdclaireho
2565569331642446be05292e3e1f8a51218827168cdclaireho  default:
2575569331642446be05292e3e1f8a51218827168cdclaireho    break;
2585569331642446be05292e3e1f8a51218827168cdclaireho  }
2595569331642446be05292e3e1f8a51218827168cdclaireho
2605569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &ss->Coverage );
2615569331642446be05292e3e1f8a51218827168cdclaireho}
2625569331642446be05292e3e1f8a51218827168cdclaireho
2635569331642446be05292e3e1f8a51218827168cdclaireho
2645569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_SingleSubst( HB_GSUBHeader*   gsub,
2655569331642446be05292e3e1f8a51218827168cdclaireho				     HB_GSUB_SubTable* st,
2665569331642446be05292e3e1f8a51218827168cdclaireho				     HB_Buffer        buffer,
2675569331642446be05292e3e1f8a51218827168cdclaireho				     HB_UShort         flags,
2685569331642446be05292e3e1f8a51218827168cdclaireho				     HB_UShort         context_length,
2695569331642446be05292e3e1f8a51218827168cdclaireho				     int               nesting_level )
2705569331642446be05292e3e1f8a51218827168cdclaireho{
2715569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort index, value, property;
2725569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
2735569331642446be05292e3e1f8a51218827168cdclaireho  HB_SingleSubst*  ss = &st->single;
2745569331642446be05292e3e1f8a51218827168cdclaireho  HB_GDEFHeader*   gdef = gsub->gdef;
2755569331642446be05292e3e1f8a51218827168cdclaireho
2765569331642446be05292e3e1f8a51218827168cdclaireho  HB_UNUSED(nesting_level);
2775569331642446be05292e3e1f8a51218827168cdclaireho
2785569331642446be05292e3e1f8a51218827168cdclaireho  if ( context_length != 0xFFFF && context_length < 1 )
2795569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
2805569331642446be05292e3e1f8a51218827168cdclaireho
2815569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
2825569331642446be05292e3e1f8a51218827168cdclaireho    return error;
2835569331642446be05292e3e1f8a51218827168cdclaireho
2845569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Coverage_Index( &ss->Coverage, IN_CURGLYPH(), &index );
2855569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
2865569331642446be05292e3e1f8a51218827168cdclaireho    return error;
2875569331642446be05292e3e1f8a51218827168cdclaireho
2885569331642446be05292e3e1f8a51218827168cdclaireho  switch ( ss->SubstFormat )
2895569331642446be05292e3e1f8a51218827168cdclaireho  {
2905569331642446be05292e3e1f8a51218827168cdclaireho  case 1:
2915569331642446be05292e3e1f8a51218827168cdclaireho    value = ( IN_CURGLYPH() + ss->ssf.ssf1.DeltaGlyphID ) & 0xFFFF;
2925569331642446be05292e3e1f8a51218827168cdclaireho    if ( REPLACE_Glyph( buffer, value, nesting_level ) )
2935569331642446be05292e3e1f8a51218827168cdclaireho      return error;
2945569331642446be05292e3e1f8a51218827168cdclaireho    break;
2955569331642446be05292e3e1f8a51218827168cdclaireho
2965569331642446be05292e3e1f8a51218827168cdclaireho  case 2:
2975569331642446be05292e3e1f8a51218827168cdclaireho    if ( index >= ss->ssf.ssf2.GlyphCount )
2985569331642446be05292e3e1f8a51218827168cdclaireho      return ERR(HB_Err_Invalid_SubTable);
2995569331642446be05292e3e1f8a51218827168cdclaireho    value = ss->ssf.ssf2.Substitute[index];
3005569331642446be05292e3e1f8a51218827168cdclaireho    if ( REPLACE_Glyph( buffer, value, nesting_level ) )
3015569331642446be05292e3e1f8a51218827168cdclaireho      return error;
3025569331642446be05292e3e1f8a51218827168cdclaireho    break;
3035569331642446be05292e3e1f8a51218827168cdclaireho
3045569331642446be05292e3e1f8a51218827168cdclaireho  default:
3055569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable);
3065569331642446be05292e3e1f8a51218827168cdclaireho  }
3075569331642446be05292e3e1f8a51218827168cdclaireho
3085569331642446be05292e3e1f8a51218827168cdclaireho  if ( gdef && gdef->NewGlyphClasses )
3095569331642446be05292e3e1f8a51218827168cdclaireho  {
3105569331642446be05292e3e1f8a51218827168cdclaireho    /* we inherit the old glyph class to the substituted glyph */
3115569331642446be05292e3e1f8a51218827168cdclaireho
3125569331642446be05292e3e1f8a51218827168cdclaireho    error = _HB_GDEF_Add_Glyph_Property( gdef, value, property );
3135569331642446be05292e3e1f8a51218827168cdclaireho    if ( error && error != HB_Err_Not_Covered )
3145569331642446be05292e3e1f8a51218827168cdclaireho      return error;
3155569331642446be05292e3e1f8a51218827168cdclaireho  }
3165569331642446be05292e3e1f8a51218827168cdclaireho
3175569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
3185569331642446be05292e3e1f8a51218827168cdclaireho}
3195569331642446be05292e3e1f8a51218827168cdclaireho
3205569331642446be05292e3e1f8a51218827168cdclaireho
3215569331642446be05292e3e1f8a51218827168cdclaireho/* LookupType 2 */
3225569331642446be05292e3e1f8a51218827168cdclaireho
3235569331642446be05292e3e1f8a51218827168cdclaireho/* Sequence */
3245569331642446be05292e3e1f8a51218827168cdclaireho
3255569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_Sequence( HB_Sequence*  s,
3265569331642446be05292e3e1f8a51218827168cdclaireho				HB_Stream      stream )
3275569331642446be05292e3e1f8a51218827168cdclaireho{
3285569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
3295569331642446be05292e3e1f8a51218827168cdclaireho
3305569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort n, count;
3315569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*  sub;
3325569331642446be05292e3e1f8a51218827168cdclaireho
3335569331642446be05292e3e1f8a51218827168cdclaireho
3345569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
3355569331642446be05292e3e1f8a51218827168cdclaireho    return error;
3365569331642446be05292e3e1f8a51218827168cdclaireho
3375569331642446be05292e3e1f8a51218827168cdclaireho  count = s->GlyphCount = GET_UShort();
3385569331642446be05292e3e1f8a51218827168cdclaireho
3395569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
3405569331642446be05292e3e1f8a51218827168cdclaireho
3415569331642446be05292e3e1f8a51218827168cdclaireho  s->Substitute = NULL;
3425569331642446be05292e3e1f8a51218827168cdclaireho
3435569331642446be05292e3e1f8a51218827168cdclaireho  if ( count )
3445569331642446be05292e3e1f8a51218827168cdclaireho  {
3455569331642446be05292e3e1f8a51218827168cdclaireho    if ( ALLOC_ARRAY( s->Substitute, count, HB_UShort ) )
3465569331642446be05292e3e1f8a51218827168cdclaireho      return error;
3475569331642446be05292e3e1f8a51218827168cdclaireho
3485569331642446be05292e3e1f8a51218827168cdclaireho    sub = s->Substitute;
3495569331642446be05292e3e1f8a51218827168cdclaireho
3505569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( count * 2L ) )
3515569331642446be05292e3e1f8a51218827168cdclaireho    {
3525569331642446be05292e3e1f8a51218827168cdclaireho      FREE( sub );
3535569331642446be05292e3e1f8a51218827168cdclaireho      return error;
3545569331642446be05292e3e1f8a51218827168cdclaireho    }
3555569331642446be05292e3e1f8a51218827168cdclaireho
3565569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
3575569331642446be05292e3e1f8a51218827168cdclaireho      sub[n] = GET_UShort();
3585569331642446be05292e3e1f8a51218827168cdclaireho
3595569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
3605569331642446be05292e3e1f8a51218827168cdclaireho  }
3615569331642446be05292e3e1f8a51218827168cdclaireho
3625569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
3635569331642446be05292e3e1f8a51218827168cdclaireho}
3645569331642446be05292e3e1f8a51218827168cdclaireho
3655569331642446be05292e3e1f8a51218827168cdclaireho
3665569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_Sequence( HB_Sequence*  s )
3675569331642446be05292e3e1f8a51218827168cdclaireho{
3685569331642446be05292e3e1f8a51218827168cdclaireho  FREE( s->Substitute );
3695569331642446be05292e3e1f8a51218827168cdclaireho}
3705569331642446be05292e3e1f8a51218827168cdclaireho
3715569331642446be05292e3e1f8a51218827168cdclaireho
3725569331642446be05292e3e1f8a51218827168cdclaireho/* MultipleSubstFormat1 */
3735569331642446be05292e3e1f8a51218827168cdclaireho
3745569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_MultipleSubst( HB_GSUB_SubTable* st,
3755569331642446be05292e3e1f8a51218827168cdclaireho				     HB_Stream         stream )
3765569331642446be05292e3e1f8a51218827168cdclaireho{
3775569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
3785569331642446be05292e3e1f8a51218827168cdclaireho  HB_MultipleSubst*  ms = &st->multiple;
3795569331642446be05292e3e1f8a51218827168cdclaireho
3805569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort      n = 0, m, count;
3815569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt       cur_offset, new_offset, base_offset;
3825569331642446be05292e3e1f8a51218827168cdclaireho
3835569331642446be05292e3e1f8a51218827168cdclaireho  HB_Sequence*  s;
3845569331642446be05292e3e1f8a51218827168cdclaireho
3855569331642446be05292e3e1f8a51218827168cdclaireho
3865569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
3875569331642446be05292e3e1f8a51218827168cdclaireho
3885569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 4L ) )
3895569331642446be05292e3e1f8a51218827168cdclaireho    return error;
3905569331642446be05292e3e1f8a51218827168cdclaireho
3915569331642446be05292e3e1f8a51218827168cdclaireho  ms->SubstFormat = GET_UShort();             /* should be 1 */
3925569331642446be05292e3e1f8a51218827168cdclaireho  new_offset      = GET_UShort() + base_offset;
3935569331642446be05292e3e1f8a51218827168cdclaireho
3945569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
3955569331642446be05292e3e1f8a51218827168cdclaireho
3965569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
3975569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
3985569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_Coverage( &ms->Coverage, stream ) ) != HB_Err_Ok )
3995569331642446be05292e3e1f8a51218827168cdclaireho    return error;
4005569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
4015569331642446be05292e3e1f8a51218827168cdclaireho
4025569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
4035569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
4045569331642446be05292e3e1f8a51218827168cdclaireho
4055569331642446be05292e3e1f8a51218827168cdclaireho  count = ms->SequenceCount = GET_UShort();
4065569331642446be05292e3e1f8a51218827168cdclaireho
4075569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
4085569331642446be05292e3e1f8a51218827168cdclaireho
4095569331642446be05292e3e1f8a51218827168cdclaireho  ms->Sequence = NULL;
4105569331642446be05292e3e1f8a51218827168cdclaireho
4115569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ms->Sequence, count, HB_Sequence ) )
4125569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
4135569331642446be05292e3e1f8a51218827168cdclaireho
4145569331642446be05292e3e1f8a51218827168cdclaireho  s = ms->Sequence;
4155569331642446be05292e3e1f8a51218827168cdclaireho
4165569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
4175569331642446be05292e3e1f8a51218827168cdclaireho  {
4185569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
4195569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
4205569331642446be05292e3e1f8a51218827168cdclaireho
4215569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
4225569331642446be05292e3e1f8a51218827168cdclaireho
4235569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
4245569331642446be05292e3e1f8a51218827168cdclaireho
4255569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
4265569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
4275569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_Sequence( &s[n], stream ) ) != HB_Err_Ok )
4285569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
4295569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
4305569331642446be05292e3e1f8a51218827168cdclaireho  }
4315569331642446be05292e3e1f8a51218827168cdclaireho
4325569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
4335569331642446be05292e3e1f8a51218827168cdclaireho
4345569331642446be05292e3e1f8a51218827168cdclairehoFail1:
4355569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
4365569331642446be05292e3e1f8a51218827168cdclaireho    Free_Sequence( &s[m] );
4375569331642446be05292e3e1f8a51218827168cdclaireho
4385569331642446be05292e3e1f8a51218827168cdclaireho  FREE( s );
4395569331642446be05292e3e1f8a51218827168cdclaireho
4405569331642446be05292e3e1f8a51218827168cdclairehoFail2:
4415569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &ms->Coverage );
4425569331642446be05292e3e1f8a51218827168cdclaireho  return error;
4435569331642446be05292e3e1f8a51218827168cdclaireho}
4445569331642446be05292e3e1f8a51218827168cdclaireho
4455569331642446be05292e3e1f8a51218827168cdclaireho
4465569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_MultipleSubst( HB_GSUB_SubTable* st )
4475569331642446be05292e3e1f8a51218827168cdclaireho{
4485569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort      n, count;
4495569331642446be05292e3e1f8a51218827168cdclaireho  HB_MultipleSubst*  ms = &st->multiple;
4505569331642446be05292e3e1f8a51218827168cdclaireho
4515569331642446be05292e3e1f8a51218827168cdclaireho  HB_Sequence*  s;
4525569331642446be05292e3e1f8a51218827168cdclaireho
4535569331642446be05292e3e1f8a51218827168cdclaireho
4545569331642446be05292e3e1f8a51218827168cdclaireho  if ( ms->Sequence )
4555569331642446be05292e3e1f8a51218827168cdclaireho  {
4565569331642446be05292e3e1f8a51218827168cdclaireho    count = ms->SequenceCount;
4575569331642446be05292e3e1f8a51218827168cdclaireho    s     = ms->Sequence;
4585569331642446be05292e3e1f8a51218827168cdclaireho
4595569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
4605569331642446be05292e3e1f8a51218827168cdclaireho      Free_Sequence( &s[n] );
4615569331642446be05292e3e1f8a51218827168cdclaireho
4625569331642446be05292e3e1f8a51218827168cdclaireho    FREE( s );
4635569331642446be05292e3e1f8a51218827168cdclaireho  }
4645569331642446be05292e3e1f8a51218827168cdclaireho
4655569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &ms->Coverage );
4665569331642446be05292e3e1f8a51218827168cdclaireho}
4675569331642446be05292e3e1f8a51218827168cdclaireho
4685569331642446be05292e3e1f8a51218827168cdclaireho
4695569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_MultipleSubst( HB_GSUBHeader*    gsub,
4705569331642446be05292e3e1f8a51218827168cdclaireho				       HB_GSUB_SubTable* st,
4715569331642446be05292e3e1f8a51218827168cdclaireho				       HB_Buffer         buffer,
4725569331642446be05292e3e1f8a51218827168cdclaireho				       HB_UShort          flags,
4735569331642446be05292e3e1f8a51218827168cdclaireho				       HB_UShort          context_length,
4745569331642446be05292e3e1f8a51218827168cdclaireho				       int                nesting_level )
4755569331642446be05292e3e1f8a51218827168cdclaireho{
4765569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
4775569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort index, property, n, count;
4785569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*s;
4795569331642446be05292e3e1f8a51218827168cdclaireho  HB_MultipleSubst*  ms = &st->multiple;
4805569331642446be05292e3e1f8a51218827168cdclaireho  HB_GDEFHeader*     gdef = gsub->gdef;
4815569331642446be05292e3e1f8a51218827168cdclaireho
4825569331642446be05292e3e1f8a51218827168cdclaireho  HB_UNUSED(nesting_level);
4835569331642446be05292e3e1f8a51218827168cdclaireho
4845569331642446be05292e3e1f8a51218827168cdclaireho  if ( context_length != 0xFFFF && context_length < 1 )
4855569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
4865569331642446be05292e3e1f8a51218827168cdclaireho
4875569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
4885569331642446be05292e3e1f8a51218827168cdclaireho    return error;
4895569331642446be05292e3e1f8a51218827168cdclaireho
4905569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Coverage_Index( &ms->Coverage, IN_CURGLYPH(), &index );
4915569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
4925569331642446be05292e3e1f8a51218827168cdclaireho    return error;
4935569331642446be05292e3e1f8a51218827168cdclaireho
4945569331642446be05292e3e1f8a51218827168cdclaireho  if ( index >= ms->SequenceCount )
4955569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable);
4965569331642446be05292e3e1f8a51218827168cdclaireho
4975569331642446be05292e3e1f8a51218827168cdclaireho  count = ms->Sequence[index].GlyphCount;
4985569331642446be05292e3e1f8a51218827168cdclaireho  s     = ms->Sequence[index].Substitute;
4995569331642446be05292e3e1f8a51218827168cdclaireho
5005569331642446be05292e3e1f8a51218827168cdclaireho  if ( ADD_String( buffer, 1, count, s, 0xFFFF, 0xFFFF ) )
5015569331642446be05292e3e1f8a51218827168cdclaireho    return error;
5025569331642446be05292e3e1f8a51218827168cdclaireho
5035569331642446be05292e3e1f8a51218827168cdclaireho  if ( gdef && gdef->NewGlyphClasses )
5045569331642446be05292e3e1f8a51218827168cdclaireho  {
5055569331642446be05292e3e1f8a51218827168cdclaireho    /* this is a guess only ... */
5065569331642446be05292e3e1f8a51218827168cdclaireho
5075569331642446be05292e3e1f8a51218827168cdclaireho    if ( property == HB_GDEF_LIGATURE )
5085569331642446be05292e3e1f8a51218827168cdclaireho      property = HB_GDEF_BASE_GLYPH;
5095569331642446be05292e3e1f8a51218827168cdclaireho
5105569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
5115569331642446be05292e3e1f8a51218827168cdclaireho    {
5125569331642446be05292e3e1f8a51218827168cdclaireho      error = _HB_GDEF_Add_Glyph_Property( gdef, s[n], property );
5135569331642446be05292e3e1f8a51218827168cdclaireho      if ( error && error != HB_Err_Not_Covered )
5145569331642446be05292e3e1f8a51218827168cdclaireho	return error;
5155569331642446be05292e3e1f8a51218827168cdclaireho    }
5165569331642446be05292e3e1f8a51218827168cdclaireho  }
5175569331642446be05292e3e1f8a51218827168cdclaireho
5185569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
5195569331642446be05292e3e1f8a51218827168cdclaireho}
5205569331642446be05292e3e1f8a51218827168cdclaireho
5215569331642446be05292e3e1f8a51218827168cdclaireho
5225569331642446be05292e3e1f8a51218827168cdclaireho/* LookupType 3 */
5235569331642446be05292e3e1f8a51218827168cdclaireho
5245569331642446be05292e3e1f8a51218827168cdclaireho/* AlternateSet */
5255569331642446be05292e3e1f8a51218827168cdclaireho
5265569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_AlternateSet( HB_AlternateSet*  as,
5275569331642446be05292e3e1f8a51218827168cdclaireho				    HB_Stream          stream )
5285569331642446be05292e3e1f8a51218827168cdclaireho{
5295569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
5305569331642446be05292e3e1f8a51218827168cdclaireho
5315569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort n, count;
5325569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*  a;
5335569331642446be05292e3e1f8a51218827168cdclaireho
5345569331642446be05292e3e1f8a51218827168cdclaireho
5355569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
5365569331642446be05292e3e1f8a51218827168cdclaireho    return error;
5375569331642446be05292e3e1f8a51218827168cdclaireho
5385569331642446be05292e3e1f8a51218827168cdclaireho  count = as->GlyphCount = GET_UShort();
5395569331642446be05292e3e1f8a51218827168cdclaireho
5405569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
5415569331642446be05292e3e1f8a51218827168cdclaireho
5425569331642446be05292e3e1f8a51218827168cdclaireho  as->Alternate = NULL;
5435569331642446be05292e3e1f8a51218827168cdclaireho
5445569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( as->Alternate, count, HB_UShort ) )
5455569331642446be05292e3e1f8a51218827168cdclaireho    return error;
5465569331642446be05292e3e1f8a51218827168cdclaireho
5475569331642446be05292e3e1f8a51218827168cdclaireho  a = as->Alternate;
5485569331642446be05292e3e1f8a51218827168cdclaireho
5495569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
5505569331642446be05292e3e1f8a51218827168cdclaireho  {
5515569331642446be05292e3e1f8a51218827168cdclaireho    FREE( a );
5525569331642446be05292e3e1f8a51218827168cdclaireho    return error;
5535569331642446be05292e3e1f8a51218827168cdclaireho  }
5545569331642446be05292e3e1f8a51218827168cdclaireho
5555569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
5565569331642446be05292e3e1f8a51218827168cdclaireho    a[n] = GET_UShort();
5575569331642446be05292e3e1f8a51218827168cdclaireho
5585569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
5595569331642446be05292e3e1f8a51218827168cdclaireho
5605569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
5615569331642446be05292e3e1f8a51218827168cdclaireho}
5625569331642446be05292e3e1f8a51218827168cdclaireho
5635569331642446be05292e3e1f8a51218827168cdclaireho
5645569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_AlternateSet( HB_AlternateSet*  as )
5655569331642446be05292e3e1f8a51218827168cdclaireho{
5665569331642446be05292e3e1f8a51218827168cdclaireho  FREE( as->Alternate );
5675569331642446be05292e3e1f8a51218827168cdclaireho}
5685569331642446be05292e3e1f8a51218827168cdclaireho
5695569331642446be05292e3e1f8a51218827168cdclaireho
5705569331642446be05292e3e1f8a51218827168cdclaireho/* AlternateSubstFormat1 */
5715569331642446be05292e3e1f8a51218827168cdclaireho
5725569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_AlternateSubst( HB_GSUB_SubTable* st,
5735569331642446be05292e3e1f8a51218827168cdclaireho				      HB_Stream         stream )
5745569331642446be05292e3e1f8a51218827168cdclaireho{
5755569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
5765569331642446be05292e3e1f8a51218827168cdclaireho  HB_AlternateSubst* as = &st->alternate;
5775569331642446be05292e3e1f8a51218827168cdclaireho
5785569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          n = 0, m, count;
5795569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt           cur_offset, new_offset, base_offset;
5805569331642446be05292e3e1f8a51218827168cdclaireho
5815569331642446be05292e3e1f8a51218827168cdclaireho  HB_AlternateSet*  aset;
5825569331642446be05292e3e1f8a51218827168cdclaireho
5835569331642446be05292e3e1f8a51218827168cdclaireho
5845569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
5855569331642446be05292e3e1f8a51218827168cdclaireho
5865569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 4L ) )
5875569331642446be05292e3e1f8a51218827168cdclaireho    return error;
5885569331642446be05292e3e1f8a51218827168cdclaireho
5895569331642446be05292e3e1f8a51218827168cdclaireho  as->SubstFormat = GET_UShort();             /* should be 1 */
5905569331642446be05292e3e1f8a51218827168cdclaireho  new_offset      = GET_UShort() + base_offset;
5915569331642446be05292e3e1f8a51218827168cdclaireho
5925569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
5935569331642446be05292e3e1f8a51218827168cdclaireho
5945569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
5955569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
5965569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_Coverage( &as->Coverage, stream ) ) != HB_Err_Ok )
5975569331642446be05292e3e1f8a51218827168cdclaireho    return error;
5985569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
5995569331642446be05292e3e1f8a51218827168cdclaireho
6005569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
6015569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
6025569331642446be05292e3e1f8a51218827168cdclaireho
6035569331642446be05292e3e1f8a51218827168cdclaireho  count = as->AlternateSetCount = GET_UShort();
6045569331642446be05292e3e1f8a51218827168cdclaireho
6055569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
6065569331642446be05292e3e1f8a51218827168cdclaireho
6075569331642446be05292e3e1f8a51218827168cdclaireho  as->AlternateSet = NULL;
6085569331642446be05292e3e1f8a51218827168cdclaireho
6095569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( as->AlternateSet, count, HB_AlternateSet ) )
6105569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
6115569331642446be05292e3e1f8a51218827168cdclaireho
6125569331642446be05292e3e1f8a51218827168cdclaireho  aset = as->AlternateSet;
6135569331642446be05292e3e1f8a51218827168cdclaireho
6145569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
6155569331642446be05292e3e1f8a51218827168cdclaireho  {
6165569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
6175569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
6185569331642446be05292e3e1f8a51218827168cdclaireho
6195569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
6205569331642446be05292e3e1f8a51218827168cdclaireho
6215569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
6225569331642446be05292e3e1f8a51218827168cdclaireho
6235569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
6245569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
6255569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_AlternateSet( &aset[n], stream ) ) != HB_Err_Ok )
6265569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
6275569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
6285569331642446be05292e3e1f8a51218827168cdclaireho  }
6295569331642446be05292e3e1f8a51218827168cdclaireho
6305569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
6315569331642446be05292e3e1f8a51218827168cdclaireho
6325569331642446be05292e3e1f8a51218827168cdclairehoFail1:
6335569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
6345569331642446be05292e3e1f8a51218827168cdclaireho    Free_AlternateSet( &aset[m] );
6355569331642446be05292e3e1f8a51218827168cdclaireho
6365569331642446be05292e3e1f8a51218827168cdclaireho  FREE( aset );
6375569331642446be05292e3e1f8a51218827168cdclaireho
6385569331642446be05292e3e1f8a51218827168cdclairehoFail2:
6395569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &as->Coverage );
6405569331642446be05292e3e1f8a51218827168cdclaireho  return error;
6415569331642446be05292e3e1f8a51218827168cdclaireho}
6425569331642446be05292e3e1f8a51218827168cdclaireho
6435569331642446be05292e3e1f8a51218827168cdclaireho
6445569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_AlternateSubst( HB_GSUB_SubTable* st )
6455569331642446be05292e3e1f8a51218827168cdclaireho{
6465569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          n, count;
6475569331642446be05292e3e1f8a51218827168cdclaireho  HB_AlternateSubst* as = &st->alternate;
6485569331642446be05292e3e1f8a51218827168cdclaireho
6495569331642446be05292e3e1f8a51218827168cdclaireho  HB_AlternateSet*  aset;
6505569331642446be05292e3e1f8a51218827168cdclaireho
6515569331642446be05292e3e1f8a51218827168cdclaireho
6525569331642446be05292e3e1f8a51218827168cdclaireho  if ( as->AlternateSet )
6535569331642446be05292e3e1f8a51218827168cdclaireho  {
6545569331642446be05292e3e1f8a51218827168cdclaireho    count = as->AlternateSetCount;
6555569331642446be05292e3e1f8a51218827168cdclaireho    aset  = as->AlternateSet;
6565569331642446be05292e3e1f8a51218827168cdclaireho
6575569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
6585569331642446be05292e3e1f8a51218827168cdclaireho      Free_AlternateSet( &aset[n] );
6595569331642446be05292e3e1f8a51218827168cdclaireho
6605569331642446be05292e3e1f8a51218827168cdclaireho    FREE( aset );
6615569331642446be05292e3e1f8a51218827168cdclaireho  }
6625569331642446be05292e3e1f8a51218827168cdclaireho
6635569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &as->Coverage );
6645569331642446be05292e3e1f8a51218827168cdclaireho}
6655569331642446be05292e3e1f8a51218827168cdclaireho
6665569331642446be05292e3e1f8a51218827168cdclaireho
6675569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_AlternateSubst( HB_GSUBHeader*    gsub,
6685569331642446be05292e3e1f8a51218827168cdclaireho					HB_GSUB_SubTable* st,
6695569331642446be05292e3e1f8a51218827168cdclaireho					HB_Buffer         buffer,
6705569331642446be05292e3e1f8a51218827168cdclaireho					HB_UShort          flags,
6715569331642446be05292e3e1f8a51218827168cdclaireho					HB_UShort          context_length,
6725569331642446be05292e3e1f8a51218827168cdclaireho					int                nesting_level )
6735569331642446be05292e3e1f8a51218827168cdclaireho{
6745569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error          error;
6755569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort         index, value, alt_index, property;
6765569331642446be05292e3e1f8a51218827168cdclaireho  HB_AlternateSubst* as = &st->alternate;
6775569331642446be05292e3e1f8a51218827168cdclaireho  HB_GDEFHeader*     gdef = gsub->gdef;
6785569331642446be05292e3e1f8a51218827168cdclaireho  HB_AlternateSet  aset;
6795569331642446be05292e3e1f8a51218827168cdclaireho
6805569331642446be05292e3e1f8a51218827168cdclaireho  HB_UNUSED(nesting_level);
6815569331642446be05292e3e1f8a51218827168cdclaireho
6825569331642446be05292e3e1f8a51218827168cdclaireho  if ( context_length != 0xFFFF && context_length < 1 )
6835569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
6845569331642446be05292e3e1f8a51218827168cdclaireho
6855569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
6865569331642446be05292e3e1f8a51218827168cdclaireho    return error;
6875569331642446be05292e3e1f8a51218827168cdclaireho
6885569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Coverage_Index( &as->Coverage, IN_CURGLYPH(), &index );
6895569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
6905569331642446be05292e3e1f8a51218827168cdclaireho    return error;
6915569331642446be05292e3e1f8a51218827168cdclaireho
6925569331642446be05292e3e1f8a51218827168cdclaireho  aset = as->AlternateSet[index];
6935569331642446be05292e3e1f8a51218827168cdclaireho
6945569331642446be05292e3e1f8a51218827168cdclaireho  /* we use a user-defined callback function to get the alternate index */
6955569331642446be05292e3e1f8a51218827168cdclaireho
6965569331642446be05292e3e1f8a51218827168cdclaireho  if ( gsub->altfunc )
6975569331642446be05292e3e1f8a51218827168cdclaireho    alt_index = (gsub->altfunc)( buffer->out_pos, IN_CURGLYPH(),
6985569331642446be05292e3e1f8a51218827168cdclaireho				 aset.GlyphCount, aset.Alternate,
6995569331642446be05292e3e1f8a51218827168cdclaireho				 gsub->data );
7005569331642446be05292e3e1f8a51218827168cdclaireho  else
7015569331642446be05292e3e1f8a51218827168cdclaireho    alt_index = 0;
7025569331642446be05292e3e1f8a51218827168cdclaireho
7035569331642446be05292e3e1f8a51218827168cdclaireho  value = aset.Alternate[alt_index];
7045569331642446be05292e3e1f8a51218827168cdclaireho  if ( REPLACE_Glyph( buffer, value, nesting_level ) )
7055569331642446be05292e3e1f8a51218827168cdclaireho    return error;
7065569331642446be05292e3e1f8a51218827168cdclaireho
7075569331642446be05292e3e1f8a51218827168cdclaireho  if ( gdef && gdef->NewGlyphClasses )
7085569331642446be05292e3e1f8a51218827168cdclaireho  {
7095569331642446be05292e3e1f8a51218827168cdclaireho    /* we inherit the old glyph class to the substituted glyph */
7105569331642446be05292e3e1f8a51218827168cdclaireho
7115569331642446be05292e3e1f8a51218827168cdclaireho    error = _HB_GDEF_Add_Glyph_Property( gdef, value, property );
7125569331642446be05292e3e1f8a51218827168cdclaireho    if ( error && error != HB_Err_Not_Covered )
7135569331642446be05292e3e1f8a51218827168cdclaireho      return error;
7145569331642446be05292e3e1f8a51218827168cdclaireho  }
7155569331642446be05292e3e1f8a51218827168cdclaireho
7165569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
7175569331642446be05292e3e1f8a51218827168cdclaireho}
7185569331642446be05292e3e1f8a51218827168cdclaireho
7195569331642446be05292e3e1f8a51218827168cdclaireho
7205569331642446be05292e3e1f8a51218827168cdclaireho/* LookupType 4 */
7215569331642446be05292e3e1f8a51218827168cdclaireho
7225569331642446be05292e3e1f8a51218827168cdclaireho/* Ligature */
7235569331642446be05292e3e1f8a51218827168cdclaireho
7245569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_Ligature( HB_Ligature*  l,
7255569331642446be05292e3e1f8a51218827168cdclaireho				HB_Stream      stream )
7265569331642446be05292e3e1f8a51218827168cdclaireho{
7275569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
7285569331642446be05292e3e1f8a51218827168cdclaireho
7295569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort n, count;
7305569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*  c;
7315569331642446be05292e3e1f8a51218827168cdclaireho
7325569331642446be05292e3e1f8a51218827168cdclaireho
7335569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 4L ) )
7345569331642446be05292e3e1f8a51218827168cdclaireho    return error;
7355569331642446be05292e3e1f8a51218827168cdclaireho
7365569331642446be05292e3e1f8a51218827168cdclaireho  l->LigGlyph       = GET_UShort();
7375569331642446be05292e3e1f8a51218827168cdclaireho  l->ComponentCount = GET_UShort();
7385569331642446be05292e3e1f8a51218827168cdclaireho
7395569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
7405569331642446be05292e3e1f8a51218827168cdclaireho
7415569331642446be05292e3e1f8a51218827168cdclaireho  l->Component = NULL;
7425569331642446be05292e3e1f8a51218827168cdclaireho
7435569331642446be05292e3e1f8a51218827168cdclaireho  count = l->ComponentCount - 1;      /* only ComponentCount - 1 elements */
7445569331642446be05292e3e1f8a51218827168cdclaireho
7455569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( l->Component, count, HB_UShort ) )
7465569331642446be05292e3e1f8a51218827168cdclaireho    return error;
7475569331642446be05292e3e1f8a51218827168cdclaireho
7485569331642446be05292e3e1f8a51218827168cdclaireho  c = l->Component;
7495569331642446be05292e3e1f8a51218827168cdclaireho
7505569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
7515569331642446be05292e3e1f8a51218827168cdclaireho  {
7525569331642446be05292e3e1f8a51218827168cdclaireho    FREE( c );
7535569331642446be05292e3e1f8a51218827168cdclaireho    return error;
7545569331642446be05292e3e1f8a51218827168cdclaireho  }
7555569331642446be05292e3e1f8a51218827168cdclaireho
7565569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
7575569331642446be05292e3e1f8a51218827168cdclaireho    c[n] = GET_UShort();
7585569331642446be05292e3e1f8a51218827168cdclaireho
7595569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
7605569331642446be05292e3e1f8a51218827168cdclaireho
7615569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
7625569331642446be05292e3e1f8a51218827168cdclaireho}
7635569331642446be05292e3e1f8a51218827168cdclaireho
7645569331642446be05292e3e1f8a51218827168cdclaireho
7655569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_Ligature( HB_Ligature*  l )
7665569331642446be05292e3e1f8a51218827168cdclaireho{
7675569331642446be05292e3e1f8a51218827168cdclaireho  FREE( l->Component );
7685569331642446be05292e3e1f8a51218827168cdclaireho}
7695569331642446be05292e3e1f8a51218827168cdclaireho
7705569331642446be05292e3e1f8a51218827168cdclaireho
7715569331642446be05292e3e1f8a51218827168cdclaireho/* LigatureSet */
7725569331642446be05292e3e1f8a51218827168cdclaireho
7735569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_LigatureSet( HB_LigatureSet*  ls,
7745569331642446be05292e3e1f8a51218827168cdclaireho				   HB_Stream         stream )
7755569331642446be05292e3e1f8a51218827168cdclaireho{
7765569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
7775569331642446be05292e3e1f8a51218827168cdclaireho
7785569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort      n = 0, m, count;
7795569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt       cur_offset, new_offset, base_offset;
7805569331642446be05292e3e1f8a51218827168cdclaireho
7815569331642446be05292e3e1f8a51218827168cdclaireho  HB_Ligature*  l;
7825569331642446be05292e3e1f8a51218827168cdclaireho
7835569331642446be05292e3e1f8a51218827168cdclaireho
7845569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
7855569331642446be05292e3e1f8a51218827168cdclaireho
7865569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
7875569331642446be05292e3e1f8a51218827168cdclaireho    return error;
7885569331642446be05292e3e1f8a51218827168cdclaireho
7895569331642446be05292e3e1f8a51218827168cdclaireho  count = ls->LigatureCount = GET_UShort();
7905569331642446be05292e3e1f8a51218827168cdclaireho
7915569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
7925569331642446be05292e3e1f8a51218827168cdclaireho
7935569331642446be05292e3e1f8a51218827168cdclaireho  ls->Ligature = NULL;
7945569331642446be05292e3e1f8a51218827168cdclaireho
7955569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ls->Ligature, count, HB_Ligature ) )
7965569331642446be05292e3e1f8a51218827168cdclaireho    return error;
7975569331642446be05292e3e1f8a51218827168cdclaireho
7985569331642446be05292e3e1f8a51218827168cdclaireho  l = ls->Ligature;
7995569331642446be05292e3e1f8a51218827168cdclaireho
8005569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
8015569331642446be05292e3e1f8a51218827168cdclaireho  {
8025569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
8035569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
8045569331642446be05292e3e1f8a51218827168cdclaireho
8055569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
8065569331642446be05292e3e1f8a51218827168cdclaireho
8075569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
8085569331642446be05292e3e1f8a51218827168cdclaireho
8095569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
8105569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
8115569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_Ligature( &l[n], stream ) ) != HB_Err_Ok )
8125569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
8135569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
8145569331642446be05292e3e1f8a51218827168cdclaireho  }
8155569331642446be05292e3e1f8a51218827168cdclaireho
8165569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
8175569331642446be05292e3e1f8a51218827168cdclaireho
8185569331642446be05292e3e1f8a51218827168cdclairehoFail:
8195569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
8205569331642446be05292e3e1f8a51218827168cdclaireho    Free_Ligature( &l[m] );
8215569331642446be05292e3e1f8a51218827168cdclaireho
8225569331642446be05292e3e1f8a51218827168cdclaireho  FREE( l );
8235569331642446be05292e3e1f8a51218827168cdclaireho  return error;
8245569331642446be05292e3e1f8a51218827168cdclaireho}
8255569331642446be05292e3e1f8a51218827168cdclaireho
8265569331642446be05292e3e1f8a51218827168cdclaireho
8275569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_LigatureSet( HB_LigatureSet*  ls )
8285569331642446be05292e3e1f8a51218827168cdclaireho{
8295569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort      n, count;
8305569331642446be05292e3e1f8a51218827168cdclaireho
8315569331642446be05292e3e1f8a51218827168cdclaireho  HB_Ligature*  l;
8325569331642446be05292e3e1f8a51218827168cdclaireho
8335569331642446be05292e3e1f8a51218827168cdclaireho
8345569331642446be05292e3e1f8a51218827168cdclaireho  if ( ls->Ligature )
8355569331642446be05292e3e1f8a51218827168cdclaireho  {
8365569331642446be05292e3e1f8a51218827168cdclaireho    count = ls->LigatureCount;
8375569331642446be05292e3e1f8a51218827168cdclaireho    l     = ls->Ligature;
8385569331642446be05292e3e1f8a51218827168cdclaireho
8395569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
8405569331642446be05292e3e1f8a51218827168cdclaireho      Free_Ligature( &l[n] );
8415569331642446be05292e3e1f8a51218827168cdclaireho
8425569331642446be05292e3e1f8a51218827168cdclaireho    FREE( l );
8435569331642446be05292e3e1f8a51218827168cdclaireho  }
8445569331642446be05292e3e1f8a51218827168cdclaireho}
8455569331642446be05292e3e1f8a51218827168cdclaireho
8465569331642446be05292e3e1f8a51218827168cdclaireho
8475569331642446be05292e3e1f8a51218827168cdclaireho/* LigatureSubstFormat1 */
8485569331642446be05292e3e1f8a51218827168cdclaireho
8495569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_LigatureSubst( HB_GSUB_SubTable* st,
8505569331642446be05292e3e1f8a51218827168cdclaireho				     HB_Stream         stream )
8515569331642446be05292e3e1f8a51218827168cdclaireho{
8525569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
8535569331642446be05292e3e1f8a51218827168cdclaireho  HB_LigatureSubst*  ls = &st->ligature;
8545569331642446be05292e3e1f8a51218827168cdclaireho
8555569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort         n = 0, m, count;
8565569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt          cur_offset, new_offset, base_offset;
8575569331642446be05292e3e1f8a51218827168cdclaireho
8585569331642446be05292e3e1f8a51218827168cdclaireho  HB_LigatureSet*  lset;
8595569331642446be05292e3e1f8a51218827168cdclaireho
8605569331642446be05292e3e1f8a51218827168cdclaireho
8615569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
8625569331642446be05292e3e1f8a51218827168cdclaireho
8635569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 4L ) )
8645569331642446be05292e3e1f8a51218827168cdclaireho    return error;
8655569331642446be05292e3e1f8a51218827168cdclaireho
8665569331642446be05292e3e1f8a51218827168cdclaireho  ls->SubstFormat = GET_UShort();             /* should be 1 */
8675569331642446be05292e3e1f8a51218827168cdclaireho  new_offset      = GET_UShort() + base_offset;
8685569331642446be05292e3e1f8a51218827168cdclaireho
8695569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
8705569331642446be05292e3e1f8a51218827168cdclaireho
8715569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
8725569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
8735569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_Coverage( &ls->Coverage, stream ) ) != HB_Err_Ok )
8745569331642446be05292e3e1f8a51218827168cdclaireho    return error;
8755569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
8765569331642446be05292e3e1f8a51218827168cdclaireho
8775569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
8785569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
8795569331642446be05292e3e1f8a51218827168cdclaireho
8805569331642446be05292e3e1f8a51218827168cdclaireho  count = ls->LigatureSetCount = GET_UShort();
8815569331642446be05292e3e1f8a51218827168cdclaireho
8825569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
8835569331642446be05292e3e1f8a51218827168cdclaireho
8845569331642446be05292e3e1f8a51218827168cdclaireho  ls->LigatureSet = NULL;
8855569331642446be05292e3e1f8a51218827168cdclaireho
8865569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ls->LigatureSet, count, HB_LigatureSet ) )
8875569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
8885569331642446be05292e3e1f8a51218827168cdclaireho
8895569331642446be05292e3e1f8a51218827168cdclaireho  lset = ls->LigatureSet;
8905569331642446be05292e3e1f8a51218827168cdclaireho
8915569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
8925569331642446be05292e3e1f8a51218827168cdclaireho  {
8935569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
8945569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
8955569331642446be05292e3e1f8a51218827168cdclaireho
8965569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
8975569331642446be05292e3e1f8a51218827168cdclaireho
8985569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
8995569331642446be05292e3e1f8a51218827168cdclaireho
9005569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
9015569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
9025569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_LigatureSet( &lset[n], stream ) ) != HB_Err_Ok )
9035569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
9045569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
9055569331642446be05292e3e1f8a51218827168cdclaireho  }
9065569331642446be05292e3e1f8a51218827168cdclaireho
9075569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
9085569331642446be05292e3e1f8a51218827168cdclaireho
9095569331642446be05292e3e1f8a51218827168cdclairehoFail1:
9105569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
9115569331642446be05292e3e1f8a51218827168cdclaireho    Free_LigatureSet( &lset[m] );
9125569331642446be05292e3e1f8a51218827168cdclaireho
9135569331642446be05292e3e1f8a51218827168cdclaireho  FREE( lset );
9145569331642446be05292e3e1f8a51218827168cdclaireho
9155569331642446be05292e3e1f8a51218827168cdclairehoFail2:
9165569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &ls->Coverage );
9175569331642446be05292e3e1f8a51218827168cdclaireho  return error;
9185569331642446be05292e3e1f8a51218827168cdclaireho}
9195569331642446be05292e3e1f8a51218827168cdclaireho
9205569331642446be05292e3e1f8a51218827168cdclaireho
9215569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_LigatureSubst( HB_GSUB_SubTable* st )
9225569331642446be05292e3e1f8a51218827168cdclaireho{
9235569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort         n, count;
9245569331642446be05292e3e1f8a51218827168cdclaireho  HB_LigatureSubst*  ls = &st->ligature;
9255569331642446be05292e3e1f8a51218827168cdclaireho
9265569331642446be05292e3e1f8a51218827168cdclaireho  HB_LigatureSet*  lset;
9275569331642446be05292e3e1f8a51218827168cdclaireho
9285569331642446be05292e3e1f8a51218827168cdclaireho
9295569331642446be05292e3e1f8a51218827168cdclaireho  if ( ls->LigatureSet )
9305569331642446be05292e3e1f8a51218827168cdclaireho  {
9315569331642446be05292e3e1f8a51218827168cdclaireho    count = ls->LigatureSetCount;
9325569331642446be05292e3e1f8a51218827168cdclaireho    lset  = ls->LigatureSet;
9335569331642446be05292e3e1f8a51218827168cdclaireho
9345569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
9355569331642446be05292e3e1f8a51218827168cdclaireho      Free_LigatureSet( &lset[n] );
9365569331642446be05292e3e1f8a51218827168cdclaireho
9375569331642446be05292e3e1f8a51218827168cdclaireho    FREE( lset );
9385569331642446be05292e3e1f8a51218827168cdclaireho  }
9395569331642446be05292e3e1f8a51218827168cdclaireho
9405569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &ls->Coverage );
9415569331642446be05292e3e1f8a51218827168cdclaireho}
9425569331642446be05292e3e1f8a51218827168cdclaireho
9435569331642446be05292e3e1f8a51218827168cdclaireho
9445569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_LigatureSubst( HB_GSUBHeader*    gsub,
9455569331642446be05292e3e1f8a51218827168cdclaireho				       HB_GSUB_SubTable* st,
9465569331642446be05292e3e1f8a51218827168cdclaireho				       HB_Buffer         buffer,
9475569331642446be05292e3e1f8a51218827168cdclaireho				       HB_UShort          flags,
9485569331642446be05292e3e1f8a51218827168cdclaireho				       HB_UShort          context_length,
9495569331642446be05292e3e1f8a51218827168cdclaireho				       int                nesting_level )
9505569331642446be05292e3e1f8a51218827168cdclaireho{
9515569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort      index, property;
9525569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error       error;
9535569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort      numlig, i, j, is_mark, first_is_mark = FALSE;
9545569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*     c;
9555569331642446be05292e3e1f8a51218827168cdclaireho  HB_LigatureSubst*  ls = &st->ligature;
9565569331642446be05292e3e1f8a51218827168cdclaireho  HB_GDEFHeader*     gdef = gsub->gdef;
9575569331642446be05292e3e1f8a51218827168cdclaireho
9585569331642446be05292e3e1f8a51218827168cdclaireho  HB_Ligature*  lig;
9595569331642446be05292e3e1f8a51218827168cdclaireho
9605569331642446be05292e3e1f8a51218827168cdclaireho  HB_UNUSED(nesting_level);
9615569331642446be05292e3e1f8a51218827168cdclaireho
9625569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
9635569331642446be05292e3e1f8a51218827168cdclaireho    return error;
9645569331642446be05292e3e1f8a51218827168cdclaireho
9655569331642446be05292e3e1f8a51218827168cdclaireho  if ( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
9665569331642446be05292e3e1f8a51218827168cdclaireho    first_is_mark = TRUE;
9675569331642446be05292e3e1f8a51218827168cdclaireho
9685569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Coverage_Index( &ls->Coverage, IN_CURGLYPH(), &index );
9695569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
9705569331642446be05292e3e1f8a51218827168cdclaireho    return error;
9715569331642446be05292e3e1f8a51218827168cdclaireho
9725569331642446be05292e3e1f8a51218827168cdclaireho  if ( index >= ls->LigatureSetCount )
9735569331642446be05292e3e1f8a51218827168cdclaireho     return ERR(HB_Err_Invalid_SubTable);
9745569331642446be05292e3e1f8a51218827168cdclaireho
9755569331642446be05292e3e1f8a51218827168cdclaireho  lig = ls->LigatureSet[index].Ligature;
9765569331642446be05292e3e1f8a51218827168cdclaireho
9775569331642446be05292e3e1f8a51218827168cdclaireho  for ( numlig = ls->LigatureSet[index].LigatureCount;
9785569331642446be05292e3e1f8a51218827168cdclaireho	numlig;
9795569331642446be05292e3e1f8a51218827168cdclaireho	numlig--, lig++ )
9805569331642446be05292e3e1f8a51218827168cdclaireho  {
9815569331642446be05292e3e1f8a51218827168cdclaireho    if ( buffer->in_pos + lig->ComponentCount > buffer->in_length )
9825569331642446be05292e3e1f8a51218827168cdclaireho      goto next_ligature;               /* Not enough glyphs in input */
9835569331642446be05292e3e1f8a51218827168cdclaireho
9845569331642446be05292e3e1f8a51218827168cdclaireho    c    = lig->Component;
9855569331642446be05292e3e1f8a51218827168cdclaireho
9865569331642446be05292e3e1f8a51218827168cdclaireho    is_mark = first_is_mark;
9875569331642446be05292e3e1f8a51218827168cdclaireho
9885569331642446be05292e3e1f8a51218827168cdclaireho    if ( context_length != 0xFFFF && context_length < lig->ComponentCount )
9895569331642446be05292e3e1f8a51218827168cdclaireho      break;
9905569331642446be05292e3e1f8a51218827168cdclaireho
9915569331642446be05292e3e1f8a51218827168cdclaireho    for ( i = 1, j = buffer->in_pos + 1; i < lig->ComponentCount; i++, j++ )
9925569331642446be05292e3e1f8a51218827168cdclaireho    {
9935569331642446be05292e3e1f8a51218827168cdclaireho      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
9945569331642446be05292e3e1f8a51218827168cdclaireho      {
9955569331642446be05292e3e1f8a51218827168cdclaireho	if ( error && error != HB_Err_Not_Covered )
9965569331642446be05292e3e1f8a51218827168cdclaireho	  return error;
9975569331642446be05292e3e1f8a51218827168cdclaireho
9985569331642446be05292e3e1f8a51218827168cdclaireho	if ( j + lig->ComponentCount - i == (HB_Int)buffer->in_length )
9995569331642446be05292e3e1f8a51218827168cdclaireho	  goto next_ligature;
10005569331642446be05292e3e1f8a51218827168cdclaireho	j++;
10015569331642446be05292e3e1f8a51218827168cdclaireho      }
10025569331642446be05292e3e1f8a51218827168cdclaireho
10035569331642446be05292e3e1f8a51218827168cdclaireho      if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
10045569331642446be05292e3e1f8a51218827168cdclaireho	is_mark = FALSE;
10055569331642446be05292e3e1f8a51218827168cdclaireho
10065569331642446be05292e3e1f8a51218827168cdclaireho      if ( IN_GLYPH( j ) != c[i - 1] )
10075569331642446be05292e3e1f8a51218827168cdclaireho	goto next_ligature;
10085569331642446be05292e3e1f8a51218827168cdclaireho    }
10095569331642446be05292e3e1f8a51218827168cdclaireho
10105569331642446be05292e3e1f8a51218827168cdclaireho    if ( gdef && gdef->NewGlyphClasses )
10115569331642446be05292e3e1f8a51218827168cdclaireho    {
10125569331642446be05292e3e1f8a51218827168cdclaireho      /* this is just a guess ... */
10135569331642446be05292e3e1f8a51218827168cdclaireho
10145569331642446be05292e3e1f8a51218827168cdclaireho      error = _HB_GDEF_Add_Glyph_Property( gdef, lig->LigGlyph,
10155569331642446be05292e3e1f8a51218827168cdclaireho				  is_mark ? HB_GDEF_MARK : HB_GDEF_LIGATURE );
10165569331642446be05292e3e1f8a51218827168cdclaireho      if ( error && error != HB_Err_Not_Covered )
10175569331642446be05292e3e1f8a51218827168cdclaireho	return error;
10185569331642446be05292e3e1f8a51218827168cdclaireho    }
10195569331642446be05292e3e1f8a51218827168cdclaireho
10205569331642446be05292e3e1f8a51218827168cdclaireho    if ( j == buffer->in_pos + i ) /* No input glyphs skipped */
10215569331642446be05292e3e1f8a51218827168cdclaireho    {
10225569331642446be05292e3e1f8a51218827168cdclaireho      /* We don't use a new ligature ID if there are no skipped
10235569331642446be05292e3e1f8a51218827168cdclaireho	 glyphs and the ligature already has an ID.             */
10245569331642446be05292e3e1f8a51218827168cdclaireho
10255569331642446be05292e3e1f8a51218827168cdclaireho      if ( IN_LIGID( buffer->in_pos ) )
10265569331642446be05292e3e1f8a51218827168cdclaireho      {
10275569331642446be05292e3e1f8a51218827168cdclaireho	if ( ADD_String( buffer, i, 1, &lig->LigGlyph,
10285569331642446be05292e3e1f8a51218827168cdclaireho			0xFFFF, 0xFFFF ) )
10295569331642446be05292e3e1f8a51218827168cdclaireho	  return error;
10305569331642446be05292e3e1f8a51218827168cdclaireho      }
10315569331642446be05292e3e1f8a51218827168cdclaireho      else
10325569331642446be05292e3e1f8a51218827168cdclaireho      {
10335569331642446be05292e3e1f8a51218827168cdclaireho	HB_UShort ligID = _hb_buffer_allocate_ligid( buffer );
10345569331642446be05292e3e1f8a51218827168cdclaireho	if ( ADD_String( buffer, i, 1, &lig->LigGlyph,
10355569331642446be05292e3e1f8a51218827168cdclaireho			0xFFFF, ligID ) )
10365569331642446be05292e3e1f8a51218827168cdclaireho	  return error;
10375569331642446be05292e3e1f8a51218827168cdclaireho      }
10385569331642446be05292e3e1f8a51218827168cdclaireho    }
10395569331642446be05292e3e1f8a51218827168cdclaireho    else
10405569331642446be05292e3e1f8a51218827168cdclaireho    {
10415569331642446be05292e3e1f8a51218827168cdclaireho      HB_UShort ligID = _hb_buffer_allocate_ligid( buffer );
10425569331642446be05292e3e1f8a51218827168cdclaireho      if ( ADD_Glyph( buffer, lig->LigGlyph, 0xFFFF, ligID ) )
10435569331642446be05292e3e1f8a51218827168cdclaireho	return error;
10445569331642446be05292e3e1f8a51218827168cdclaireho
10455569331642446be05292e3e1f8a51218827168cdclaireho      /* Now we must do a second loop to copy the skipped glyphs to
10465569331642446be05292e3e1f8a51218827168cdclaireho	 `out' and assign component values to it.  We start with the
10475569331642446be05292e3e1f8a51218827168cdclaireho	 glyph after the first component.  Glyphs between component
10485569331642446be05292e3e1f8a51218827168cdclaireho	 i and i+1 belong to component i.  Together with the ligID
10495569331642446be05292e3e1f8a51218827168cdclaireho	 value it is later possible to check whether a specific
10505569331642446be05292e3e1f8a51218827168cdclaireho	 component value really belongs to a given ligature.         */
10515569331642446be05292e3e1f8a51218827168cdclaireho
10525569331642446be05292e3e1f8a51218827168cdclaireho      for ( i = 0; i < lig->ComponentCount - 1; i++ )
10535569331642446be05292e3e1f8a51218827168cdclaireho      {
10545569331642446be05292e3e1f8a51218827168cdclaireho	while ( CHECK_Property( gdef, IN_CURITEM(),
10555569331642446be05292e3e1f8a51218827168cdclaireho				flags, &property ) )
10565569331642446be05292e3e1f8a51218827168cdclaireho	  if ( ADD_Glyph( buffer, IN_CURGLYPH(), i, ligID ) )
10575569331642446be05292e3e1f8a51218827168cdclaireho	    return error;
10585569331642446be05292e3e1f8a51218827168cdclaireho
10595569331642446be05292e3e1f8a51218827168cdclaireho	(buffer->in_pos)++;
10605569331642446be05292e3e1f8a51218827168cdclaireho      }
10615569331642446be05292e3e1f8a51218827168cdclaireho    }
10625569331642446be05292e3e1f8a51218827168cdclaireho
10635569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Ok;
10645569331642446be05292e3e1f8a51218827168cdclaireho
10655569331642446be05292e3e1f8a51218827168cdclaireho  next_ligature:
10665569331642446be05292e3e1f8a51218827168cdclaireho    ;
10675569331642446be05292e3e1f8a51218827168cdclaireho  }
10685569331642446be05292e3e1f8a51218827168cdclaireho
10695569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Not_Covered;
10705569331642446be05292e3e1f8a51218827168cdclaireho}
10715569331642446be05292e3e1f8a51218827168cdclaireho
10725569331642446be05292e3e1f8a51218827168cdclaireho
10735569331642446be05292e3e1f8a51218827168cdclaireho/* Do the actual substitution for a context substitution (either format
10745569331642446be05292e3e1f8a51218827168cdclaireho   5 or 6).  This is only called after we've determined that the input
10755569331642446be05292e3e1f8a51218827168cdclaireho   matches the subrule.                                                 */
10765569331642446be05292e3e1f8a51218827168cdclaireho
10775569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Do_ContextSubst( HB_GSUBHeader*        gsub,
10785569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort              GlyphCount,
10795569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort              SubstCount,
10805569331642446be05292e3e1f8a51218827168cdclaireho				  HB_SubstLookupRecord* subst,
10815569331642446be05292e3e1f8a51218827168cdclaireho				  HB_Buffer             buffer,
10825569331642446be05292e3e1f8a51218827168cdclaireho				  int                    nesting_level )
10835569331642446be05292e3e1f8a51218827168cdclaireho{
10845569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
10855569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt   i, old_pos;
10865569331642446be05292e3e1f8a51218827168cdclaireho
10875569331642446be05292e3e1f8a51218827168cdclaireho
10885569331642446be05292e3e1f8a51218827168cdclaireho  i = 0;
10895569331642446be05292e3e1f8a51218827168cdclaireho
10905569331642446be05292e3e1f8a51218827168cdclaireho  while ( i < GlyphCount )
10915569331642446be05292e3e1f8a51218827168cdclaireho  {
10925569331642446be05292e3e1f8a51218827168cdclaireho    if ( SubstCount && i == subst->SequenceIndex )
10935569331642446be05292e3e1f8a51218827168cdclaireho    {
10945569331642446be05292e3e1f8a51218827168cdclaireho      old_pos = buffer->in_pos;
10955569331642446be05292e3e1f8a51218827168cdclaireho
10965569331642446be05292e3e1f8a51218827168cdclaireho      /* Do a substitution */
10975569331642446be05292e3e1f8a51218827168cdclaireho
10985569331642446be05292e3e1f8a51218827168cdclaireho      error = GSUB_Do_Glyph_Lookup( gsub, subst->LookupListIndex, buffer,
10995569331642446be05292e3e1f8a51218827168cdclaireho				    GlyphCount, nesting_level );
11005569331642446be05292e3e1f8a51218827168cdclaireho
11015569331642446be05292e3e1f8a51218827168cdclaireho      subst++;
11025569331642446be05292e3e1f8a51218827168cdclaireho      SubstCount--;
11035569331642446be05292e3e1f8a51218827168cdclaireho      i += buffer->in_pos - old_pos;
11045569331642446be05292e3e1f8a51218827168cdclaireho
11055569331642446be05292e3e1f8a51218827168cdclaireho      if ( error == HB_Err_Not_Covered )
11065569331642446be05292e3e1f8a51218827168cdclaireho      {
11075569331642446be05292e3e1f8a51218827168cdclaireho	if ( COPY_Glyph( buffer ) )
11085569331642446be05292e3e1f8a51218827168cdclaireho	  return error;
11095569331642446be05292e3e1f8a51218827168cdclaireho	i++;
11105569331642446be05292e3e1f8a51218827168cdclaireho      }
11115569331642446be05292e3e1f8a51218827168cdclaireho      else if ( error )
11125569331642446be05292e3e1f8a51218827168cdclaireho	return error;
11135569331642446be05292e3e1f8a51218827168cdclaireho    }
11145569331642446be05292e3e1f8a51218827168cdclaireho    else
11155569331642446be05292e3e1f8a51218827168cdclaireho    {
11165569331642446be05292e3e1f8a51218827168cdclaireho      /* No substitution for this index */
11175569331642446be05292e3e1f8a51218827168cdclaireho
11185569331642446be05292e3e1f8a51218827168cdclaireho      if ( COPY_Glyph( buffer ) )
11195569331642446be05292e3e1f8a51218827168cdclaireho	return error;
11205569331642446be05292e3e1f8a51218827168cdclaireho      i++;
11215569331642446be05292e3e1f8a51218827168cdclaireho    }
11225569331642446be05292e3e1f8a51218827168cdclaireho  }
11235569331642446be05292e3e1f8a51218827168cdclaireho
11245569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
11255569331642446be05292e3e1f8a51218827168cdclaireho}
11265569331642446be05292e3e1f8a51218827168cdclaireho
11275569331642446be05292e3e1f8a51218827168cdclaireho
11285569331642446be05292e3e1f8a51218827168cdclaireho/* LookupType 5 */
11295569331642446be05292e3e1f8a51218827168cdclaireho
11305569331642446be05292e3e1f8a51218827168cdclaireho/* SubRule */
11315569331642446be05292e3e1f8a51218827168cdclaireho
11325569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_SubRule( HB_SubRule*  sr,
11335569331642446be05292e3e1f8a51218827168cdclaireho			       HB_Stream     stream )
11345569331642446be05292e3e1f8a51218827168cdclaireho{
11355569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
11365569331642446be05292e3e1f8a51218827168cdclaireho
11375569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort               n, count;
11385569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*              i;
11395569331642446be05292e3e1f8a51218827168cdclaireho
11405569331642446be05292e3e1f8a51218827168cdclaireho  HB_SubstLookupRecord*  slr;
11415569331642446be05292e3e1f8a51218827168cdclaireho
11425569331642446be05292e3e1f8a51218827168cdclaireho
11435569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 4L ) )
11445569331642446be05292e3e1f8a51218827168cdclaireho    return error;
11455569331642446be05292e3e1f8a51218827168cdclaireho
11465569331642446be05292e3e1f8a51218827168cdclaireho  sr->GlyphCount = GET_UShort();
11475569331642446be05292e3e1f8a51218827168cdclaireho  sr->SubstCount = GET_UShort();
11485569331642446be05292e3e1f8a51218827168cdclaireho
11495569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
11505569331642446be05292e3e1f8a51218827168cdclaireho
11515569331642446be05292e3e1f8a51218827168cdclaireho  sr->Input = NULL;
11525569331642446be05292e3e1f8a51218827168cdclaireho
11535569331642446be05292e3e1f8a51218827168cdclaireho  count = sr->GlyphCount - 1;         /* only GlyphCount - 1 elements */
11545569331642446be05292e3e1f8a51218827168cdclaireho
11555569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( sr->Input, count, HB_UShort ) )
11565569331642446be05292e3e1f8a51218827168cdclaireho    return error;
11575569331642446be05292e3e1f8a51218827168cdclaireho
11585569331642446be05292e3e1f8a51218827168cdclaireho  i = sr->Input;
11595569331642446be05292e3e1f8a51218827168cdclaireho
11605569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
11615569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
11625569331642446be05292e3e1f8a51218827168cdclaireho
11635569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
11645569331642446be05292e3e1f8a51218827168cdclaireho    i[n] = GET_UShort();
11655569331642446be05292e3e1f8a51218827168cdclaireho
11665569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
11675569331642446be05292e3e1f8a51218827168cdclaireho
11685569331642446be05292e3e1f8a51218827168cdclaireho  sr->SubstLookupRecord = NULL;
11695569331642446be05292e3e1f8a51218827168cdclaireho
11705569331642446be05292e3e1f8a51218827168cdclaireho  count = sr->SubstCount;
11715569331642446be05292e3e1f8a51218827168cdclaireho
11725569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( sr->SubstLookupRecord, count, HB_SubstLookupRecord ) )
11735569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
11745569331642446be05292e3e1f8a51218827168cdclaireho
11755569331642446be05292e3e1f8a51218827168cdclaireho  slr = sr->SubstLookupRecord;
11765569331642446be05292e3e1f8a51218827168cdclaireho
11775569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 4L ) )
11785569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail1;
11795569331642446be05292e3e1f8a51218827168cdclaireho
11805569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
11815569331642446be05292e3e1f8a51218827168cdclaireho  {
11825569331642446be05292e3e1f8a51218827168cdclaireho    slr[n].SequenceIndex   = GET_UShort();
11835569331642446be05292e3e1f8a51218827168cdclaireho    slr[n].LookupListIndex = GET_UShort();
11845569331642446be05292e3e1f8a51218827168cdclaireho  }
11855569331642446be05292e3e1f8a51218827168cdclaireho
11865569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
11875569331642446be05292e3e1f8a51218827168cdclaireho
11885569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
11895569331642446be05292e3e1f8a51218827168cdclaireho
11905569331642446be05292e3e1f8a51218827168cdclairehoFail1:
11915569331642446be05292e3e1f8a51218827168cdclaireho  FREE( slr );
11925569331642446be05292e3e1f8a51218827168cdclaireho
11935569331642446be05292e3e1f8a51218827168cdclairehoFail2:
11945569331642446be05292e3e1f8a51218827168cdclaireho  FREE( i );
11955569331642446be05292e3e1f8a51218827168cdclaireho  return error;
11965569331642446be05292e3e1f8a51218827168cdclaireho}
11975569331642446be05292e3e1f8a51218827168cdclaireho
11985569331642446be05292e3e1f8a51218827168cdclaireho
11995569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_SubRule( HB_SubRule*  sr )
12005569331642446be05292e3e1f8a51218827168cdclaireho{
12015569331642446be05292e3e1f8a51218827168cdclaireho  FREE( sr->SubstLookupRecord );
12025569331642446be05292e3e1f8a51218827168cdclaireho  FREE( sr->Input );
12035569331642446be05292e3e1f8a51218827168cdclaireho}
12045569331642446be05292e3e1f8a51218827168cdclaireho
12055569331642446be05292e3e1f8a51218827168cdclaireho
12065569331642446be05292e3e1f8a51218827168cdclaireho/* SubRuleSet */
12075569331642446be05292e3e1f8a51218827168cdclaireho
12085569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_SubRuleSet( HB_SubRuleSet*  srs,
12095569331642446be05292e3e1f8a51218827168cdclaireho				  HB_Stream        stream )
12105569331642446be05292e3e1f8a51218827168cdclaireho{
12115569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
12125569331642446be05292e3e1f8a51218827168cdclaireho
12135569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort     n = 0, m, count;
12145569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt      cur_offset, new_offset, base_offset;
12155569331642446be05292e3e1f8a51218827168cdclaireho
12165569331642446be05292e3e1f8a51218827168cdclaireho  HB_SubRule*  sr;
12175569331642446be05292e3e1f8a51218827168cdclaireho
12185569331642446be05292e3e1f8a51218827168cdclaireho
12195569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
12205569331642446be05292e3e1f8a51218827168cdclaireho
12215569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
12225569331642446be05292e3e1f8a51218827168cdclaireho    return error;
12235569331642446be05292e3e1f8a51218827168cdclaireho
12245569331642446be05292e3e1f8a51218827168cdclaireho  count = srs->SubRuleCount = GET_UShort();
12255569331642446be05292e3e1f8a51218827168cdclaireho
12265569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
12275569331642446be05292e3e1f8a51218827168cdclaireho
12285569331642446be05292e3e1f8a51218827168cdclaireho  srs->SubRule = NULL;
12295569331642446be05292e3e1f8a51218827168cdclaireho
12305569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( srs->SubRule, count, HB_SubRule ) )
12315569331642446be05292e3e1f8a51218827168cdclaireho    return error;
12325569331642446be05292e3e1f8a51218827168cdclaireho
12335569331642446be05292e3e1f8a51218827168cdclaireho  sr = srs->SubRule;
12345569331642446be05292e3e1f8a51218827168cdclaireho
12355569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
12365569331642446be05292e3e1f8a51218827168cdclaireho  {
12375569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
12385569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
12395569331642446be05292e3e1f8a51218827168cdclaireho
12405569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
12415569331642446be05292e3e1f8a51218827168cdclaireho
12425569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
12435569331642446be05292e3e1f8a51218827168cdclaireho
12445569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
12455569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
12465569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_SubRule( &sr[n], stream ) ) != HB_Err_Ok )
12475569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
12485569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
12495569331642446be05292e3e1f8a51218827168cdclaireho  }
12505569331642446be05292e3e1f8a51218827168cdclaireho
12515569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
12525569331642446be05292e3e1f8a51218827168cdclaireho
12535569331642446be05292e3e1f8a51218827168cdclairehoFail:
12545569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
12555569331642446be05292e3e1f8a51218827168cdclaireho    Free_SubRule( &sr[m] );
12565569331642446be05292e3e1f8a51218827168cdclaireho
12575569331642446be05292e3e1f8a51218827168cdclaireho  FREE( sr );
12585569331642446be05292e3e1f8a51218827168cdclaireho  return error;
12595569331642446be05292e3e1f8a51218827168cdclaireho}
12605569331642446be05292e3e1f8a51218827168cdclaireho
12615569331642446be05292e3e1f8a51218827168cdclaireho
12625569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_SubRuleSet( HB_SubRuleSet*  srs )
12635569331642446be05292e3e1f8a51218827168cdclaireho{
12645569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort     n, count;
12655569331642446be05292e3e1f8a51218827168cdclaireho
12665569331642446be05292e3e1f8a51218827168cdclaireho  HB_SubRule*  sr;
12675569331642446be05292e3e1f8a51218827168cdclaireho
12685569331642446be05292e3e1f8a51218827168cdclaireho
12695569331642446be05292e3e1f8a51218827168cdclaireho  if ( srs->SubRule )
12705569331642446be05292e3e1f8a51218827168cdclaireho  {
12715569331642446be05292e3e1f8a51218827168cdclaireho    count = srs->SubRuleCount;
12725569331642446be05292e3e1f8a51218827168cdclaireho    sr    = srs->SubRule;
12735569331642446be05292e3e1f8a51218827168cdclaireho
12745569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
12755569331642446be05292e3e1f8a51218827168cdclaireho      Free_SubRule( &sr[n] );
12765569331642446be05292e3e1f8a51218827168cdclaireho
12775569331642446be05292e3e1f8a51218827168cdclaireho    FREE( sr );
12785569331642446be05292e3e1f8a51218827168cdclaireho  }
12795569331642446be05292e3e1f8a51218827168cdclaireho}
12805569331642446be05292e3e1f8a51218827168cdclaireho
12815569331642446be05292e3e1f8a51218827168cdclaireho
12825569331642446be05292e3e1f8a51218827168cdclaireho/* ContextSubstFormat1 */
12835569331642446be05292e3e1f8a51218827168cdclaireho
12845569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ContextSubst1( HB_ContextSubstFormat1*  csf1,
12855569331642446be05292e3e1f8a51218827168cdclaireho				     HB_Stream                 stream )
12865569331642446be05292e3e1f8a51218827168cdclaireho{
12875569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
12885569331642446be05292e3e1f8a51218827168cdclaireho
12895569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        n = 0, m, count;
12905569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt         cur_offset, new_offset, base_offset;
12915569331642446be05292e3e1f8a51218827168cdclaireho
12925569331642446be05292e3e1f8a51218827168cdclaireho  HB_SubRuleSet*  srs;
12935569331642446be05292e3e1f8a51218827168cdclaireho
12945569331642446be05292e3e1f8a51218827168cdclaireho
12955569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos() - 2L;
12965569331642446be05292e3e1f8a51218827168cdclaireho
12975569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
12985569331642446be05292e3e1f8a51218827168cdclaireho    return error;
12995569331642446be05292e3e1f8a51218827168cdclaireho
13005569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
13015569331642446be05292e3e1f8a51218827168cdclaireho
13025569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
13035569331642446be05292e3e1f8a51218827168cdclaireho
13045569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
13055569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
13065569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_Coverage( &csf1->Coverage, stream ) ) != HB_Err_Ok )
13075569331642446be05292e3e1f8a51218827168cdclaireho    return error;
13085569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
13095569331642446be05292e3e1f8a51218827168cdclaireho
13105569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
13115569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
13125569331642446be05292e3e1f8a51218827168cdclaireho
13135569331642446be05292e3e1f8a51218827168cdclaireho  count = csf1->SubRuleSetCount = GET_UShort();
13145569331642446be05292e3e1f8a51218827168cdclaireho
13155569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
13165569331642446be05292e3e1f8a51218827168cdclaireho
13175569331642446be05292e3e1f8a51218827168cdclaireho  csf1->SubRuleSet = NULL;
13185569331642446be05292e3e1f8a51218827168cdclaireho
13195569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( csf1->SubRuleSet, count, HB_SubRuleSet ) )
13205569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
13215569331642446be05292e3e1f8a51218827168cdclaireho
13225569331642446be05292e3e1f8a51218827168cdclaireho  srs = csf1->SubRuleSet;
13235569331642446be05292e3e1f8a51218827168cdclaireho
13245569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
13255569331642446be05292e3e1f8a51218827168cdclaireho  {
13265569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
13275569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
13285569331642446be05292e3e1f8a51218827168cdclaireho
13295569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
13305569331642446be05292e3e1f8a51218827168cdclaireho
13315569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
13325569331642446be05292e3e1f8a51218827168cdclaireho
13335569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
13345569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
13355569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_SubRuleSet( &srs[n], stream ) ) != HB_Err_Ok )
13365569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
13375569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
13385569331642446be05292e3e1f8a51218827168cdclaireho  }
13395569331642446be05292e3e1f8a51218827168cdclaireho
13405569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
13415569331642446be05292e3e1f8a51218827168cdclaireho
13425569331642446be05292e3e1f8a51218827168cdclairehoFail1:
13435569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
13445569331642446be05292e3e1f8a51218827168cdclaireho    Free_SubRuleSet( &srs[m] );
13455569331642446be05292e3e1f8a51218827168cdclaireho
13465569331642446be05292e3e1f8a51218827168cdclaireho  FREE( srs );
13475569331642446be05292e3e1f8a51218827168cdclaireho
13485569331642446be05292e3e1f8a51218827168cdclairehoFail2:
13495569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &csf1->Coverage );
13505569331642446be05292e3e1f8a51218827168cdclaireho  return error;
13515569331642446be05292e3e1f8a51218827168cdclaireho}
13525569331642446be05292e3e1f8a51218827168cdclaireho
13535569331642446be05292e3e1f8a51218827168cdclaireho
13545569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ContextSubst1( HB_ContextSubstFormat1* csf1 )
13555569331642446be05292e3e1f8a51218827168cdclaireho{
13565569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        n, count;
13575569331642446be05292e3e1f8a51218827168cdclaireho
13585569331642446be05292e3e1f8a51218827168cdclaireho  HB_SubRuleSet*  srs;
13595569331642446be05292e3e1f8a51218827168cdclaireho
13605569331642446be05292e3e1f8a51218827168cdclaireho
13615569331642446be05292e3e1f8a51218827168cdclaireho  if ( csf1->SubRuleSet )
13625569331642446be05292e3e1f8a51218827168cdclaireho  {
13635569331642446be05292e3e1f8a51218827168cdclaireho    count = csf1->SubRuleSetCount;
13645569331642446be05292e3e1f8a51218827168cdclaireho    srs   = csf1->SubRuleSet;
13655569331642446be05292e3e1f8a51218827168cdclaireho
13665569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
13675569331642446be05292e3e1f8a51218827168cdclaireho      Free_SubRuleSet( &srs[n] );
13685569331642446be05292e3e1f8a51218827168cdclaireho
13695569331642446be05292e3e1f8a51218827168cdclaireho    FREE( srs );
13705569331642446be05292e3e1f8a51218827168cdclaireho  }
13715569331642446be05292e3e1f8a51218827168cdclaireho
13725569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &csf1->Coverage );
13735569331642446be05292e3e1f8a51218827168cdclaireho}
13745569331642446be05292e3e1f8a51218827168cdclaireho
13755569331642446be05292e3e1f8a51218827168cdclaireho
13765569331642446be05292e3e1f8a51218827168cdclaireho/* SubClassRule */
13775569331642446be05292e3e1f8a51218827168cdclaireho
13785569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_SubClassRule( HB_ContextSubstFormat2*  csf2,
13795569331642446be05292e3e1f8a51218827168cdclaireho				    HB_SubClassRule*         scr,
13805569331642446be05292e3e1f8a51218827168cdclaireho				    HB_Stream                 stream )
13815569331642446be05292e3e1f8a51218827168cdclaireho{
13825569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
13835569331642446be05292e3e1f8a51218827168cdclaireho
13845569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort               n, count;
13855569331642446be05292e3e1f8a51218827168cdclaireho
13865569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*              c;
13875569331642446be05292e3e1f8a51218827168cdclaireho  HB_SubstLookupRecord*  slr;
13885569331642446be05292e3e1f8a51218827168cdclaireho
13895569331642446be05292e3e1f8a51218827168cdclaireho
13905569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 4L ) )
13915569331642446be05292e3e1f8a51218827168cdclaireho    return error;
13925569331642446be05292e3e1f8a51218827168cdclaireho
13935569331642446be05292e3e1f8a51218827168cdclaireho  scr->GlyphCount = GET_UShort();
13945569331642446be05292e3e1f8a51218827168cdclaireho  scr->SubstCount = GET_UShort();
13955569331642446be05292e3e1f8a51218827168cdclaireho
13965569331642446be05292e3e1f8a51218827168cdclaireho  if ( scr->GlyphCount > csf2->MaxContextLength )
13975569331642446be05292e3e1f8a51218827168cdclaireho    csf2->MaxContextLength = scr->GlyphCount;
13985569331642446be05292e3e1f8a51218827168cdclaireho
13995569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
14005569331642446be05292e3e1f8a51218827168cdclaireho
14015569331642446be05292e3e1f8a51218827168cdclaireho  scr->Class = NULL;
14025569331642446be05292e3e1f8a51218827168cdclaireho
14035569331642446be05292e3e1f8a51218827168cdclaireho  count = scr->GlyphCount - 1;        /* only GlyphCount - 1 elements */
14045569331642446be05292e3e1f8a51218827168cdclaireho
14055569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( scr->Class, count, HB_UShort ) )
14065569331642446be05292e3e1f8a51218827168cdclaireho    return error;
14075569331642446be05292e3e1f8a51218827168cdclaireho
14085569331642446be05292e3e1f8a51218827168cdclaireho  c = scr->Class;
14095569331642446be05292e3e1f8a51218827168cdclaireho
14105569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
14115569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
14125569331642446be05292e3e1f8a51218827168cdclaireho
14135569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
14145569331642446be05292e3e1f8a51218827168cdclaireho    c[n] = GET_UShort();
14155569331642446be05292e3e1f8a51218827168cdclaireho
14165569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
14175569331642446be05292e3e1f8a51218827168cdclaireho
14185569331642446be05292e3e1f8a51218827168cdclaireho  scr->SubstLookupRecord = NULL;
14195569331642446be05292e3e1f8a51218827168cdclaireho
14205569331642446be05292e3e1f8a51218827168cdclaireho  count = scr->SubstCount;
14215569331642446be05292e3e1f8a51218827168cdclaireho
14225569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( scr->SubstLookupRecord, count, HB_SubstLookupRecord ) )
14235569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
14245569331642446be05292e3e1f8a51218827168cdclaireho
14255569331642446be05292e3e1f8a51218827168cdclaireho  slr = scr->SubstLookupRecord;
14265569331642446be05292e3e1f8a51218827168cdclaireho
14275569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 4L ) )
14285569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail1;
14295569331642446be05292e3e1f8a51218827168cdclaireho
14305569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
14315569331642446be05292e3e1f8a51218827168cdclaireho  {
14325569331642446be05292e3e1f8a51218827168cdclaireho    slr[n].SequenceIndex   = GET_UShort();
14335569331642446be05292e3e1f8a51218827168cdclaireho    slr[n].LookupListIndex = GET_UShort();
14345569331642446be05292e3e1f8a51218827168cdclaireho  }
14355569331642446be05292e3e1f8a51218827168cdclaireho
14365569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
14375569331642446be05292e3e1f8a51218827168cdclaireho
14385569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
14395569331642446be05292e3e1f8a51218827168cdclaireho
14405569331642446be05292e3e1f8a51218827168cdclairehoFail1:
14415569331642446be05292e3e1f8a51218827168cdclaireho  FREE( slr );
14425569331642446be05292e3e1f8a51218827168cdclaireho
14435569331642446be05292e3e1f8a51218827168cdclairehoFail2:
14445569331642446be05292e3e1f8a51218827168cdclaireho  FREE( c );
14455569331642446be05292e3e1f8a51218827168cdclaireho  return error;
14465569331642446be05292e3e1f8a51218827168cdclaireho}
14475569331642446be05292e3e1f8a51218827168cdclaireho
14485569331642446be05292e3e1f8a51218827168cdclaireho
14495569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_SubClassRule( HB_SubClassRule*  scr )
14505569331642446be05292e3e1f8a51218827168cdclaireho{
14515569331642446be05292e3e1f8a51218827168cdclaireho  FREE( scr->SubstLookupRecord );
14525569331642446be05292e3e1f8a51218827168cdclaireho  FREE( scr->Class );
14535569331642446be05292e3e1f8a51218827168cdclaireho}
14545569331642446be05292e3e1f8a51218827168cdclaireho
14555569331642446be05292e3e1f8a51218827168cdclaireho
14565569331642446be05292e3e1f8a51218827168cdclaireho/* SubClassSet */
14575569331642446be05292e3e1f8a51218827168cdclaireho
14585569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_SubClassSet( HB_ContextSubstFormat2*  csf2,
14595569331642446be05292e3e1f8a51218827168cdclaireho				   HB_SubClassSet*          scs,
14605569331642446be05292e3e1f8a51218827168cdclaireho				   HB_Stream                 stream )
14615569331642446be05292e3e1f8a51218827168cdclaireho{
14625569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
14635569331642446be05292e3e1f8a51218827168cdclaireho
14645569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          n = 0, m, count;
14655569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt           cur_offset, new_offset, base_offset;
14665569331642446be05292e3e1f8a51218827168cdclaireho
14675569331642446be05292e3e1f8a51218827168cdclaireho  HB_SubClassRule*  scr;
14685569331642446be05292e3e1f8a51218827168cdclaireho
14695569331642446be05292e3e1f8a51218827168cdclaireho
14705569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
14715569331642446be05292e3e1f8a51218827168cdclaireho
14725569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
14735569331642446be05292e3e1f8a51218827168cdclaireho    return error;
14745569331642446be05292e3e1f8a51218827168cdclaireho
14755569331642446be05292e3e1f8a51218827168cdclaireho  count = scs->SubClassRuleCount = GET_UShort();
14765569331642446be05292e3e1f8a51218827168cdclaireho
14775569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
14785569331642446be05292e3e1f8a51218827168cdclaireho
14795569331642446be05292e3e1f8a51218827168cdclaireho  scs->SubClassRule = NULL;
14805569331642446be05292e3e1f8a51218827168cdclaireho
14815569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( scs->SubClassRule, count, HB_SubClassRule ) )
14825569331642446be05292e3e1f8a51218827168cdclaireho    return error;
14835569331642446be05292e3e1f8a51218827168cdclaireho
14845569331642446be05292e3e1f8a51218827168cdclaireho  scr = scs->SubClassRule;
14855569331642446be05292e3e1f8a51218827168cdclaireho
14865569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
14875569331642446be05292e3e1f8a51218827168cdclaireho  {
14885569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
14895569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
14905569331642446be05292e3e1f8a51218827168cdclaireho
14915569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
14925569331642446be05292e3e1f8a51218827168cdclaireho
14935569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
14945569331642446be05292e3e1f8a51218827168cdclaireho
14955569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
14965569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
14975569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_SubClassRule( csf2, &scr[n],
14985569331642446be05292e3e1f8a51218827168cdclaireho				      stream ) ) != HB_Err_Ok )
14995569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
15005569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
15015569331642446be05292e3e1f8a51218827168cdclaireho  }
15025569331642446be05292e3e1f8a51218827168cdclaireho
15035569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
15045569331642446be05292e3e1f8a51218827168cdclaireho
15055569331642446be05292e3e1f8a51218827168cdclairehoFail:
15065569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
15075569331642446be05292e3e1f8a51218827168cdclaireho    Free_SubClassRule( &scr[m] );
15085569331642446be05292e3e1f8a51218827168cdclaireho
15095569331642446be05292e3e1f8a51218827168cdclaireho  FREE( scr );
15105569331642446be05292e3e1f8a51218827168cdclaireho  return error;
15115569331642446be05292e3e1f8a51218827168cdclaireho}
15125569331642446be05292e3e1f8a51218827168cdclaireho
15135569331642446be05292e3e1f8a51218827168cdclaireho
15145569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_SubClassSet( HB_SubClassSet*  scs )
15155569331642446be05292e3e1f8a51218827168cdclaireho{
15165569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          n, count;
15175569331642446be05292e3e1f8a51218827168cdclaireho
15185569331642446be05292e3e1f8a51218827168cdclaireho  HB_SubClassRule*  scr;
15195569331642446be05292e3e1f8a51218827168cdclaireho
15205569331642446be05292e3e1f8a51218827168cdclaireho
15215569331642446be05292e3e1f8a51218827168cdclaireho  if ( scs->SubClassRule )
15225569331642446be05292e3e1f8a51218827168cdclaireho  {
15235569331642446be05292e3e1f8a51218827168cdclaireho    count = scs->SubClassRuleCount;
15245569331642446be05292e3e1f8a51218827168cdclaireho    scr   = scs->SubClassRule;
15255569331642446be05292e3e1f8a51218827168cdclaireho
15265569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
15275569331642446be05292e3e1f8a51218827168cdclaireho      Free_SubClassRule( &scr[n] );
15285569331642446be05292e3e1f8a51218827168cdclaireho
15295569331642446be05292e3e1f8a51218827168cdclaireho    FREE( scr );
15305569331642446be05292e3e1f8a51218827168cdclaireho  }
15315569331642446be05292e3e1f8a51218827168cdclaireho}
15325569331642446be05292e3e1f8a51218827168cdclaireho
15335569331642446be05292e3e1f8a51218827168cdclaireho
15345569331642446be05292e3e1f8a51218827168cdclaireho/* ContextSubstFormat2 */
15355569331642446be05292e3e1f8a51218827168cdclaireho
15365569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ContextSubst2( HB_ContextSubstFormat2*  csf2,
15375569331642446be05292e3e1f8a51218827168cdclaireho				     HB_Stream                 stream )
15385569331642446be05292e3e1f8a51218827168cdclaireho{
15395569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
15405569331642446be05292e3e1f8a51218827168cdclaireho
15415569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort         n = 0, m, count;
15425569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt          cur_offset, new_offset, base_offset;
15435569331642446be05292e3e1f8a51218827168cdclaireho
15445569331642446be05292e3e1f8a51218827168cdclaireho  HB_SubClassSet*  scs;
15455569331642446be05292e3e1f8a51218827168cdclaireho
15465569331642446be05292e3e1f8a51218827168cdclaireho
15475569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos() - 2;
15485569331642446be05292e3e1f8a51218827168cdclaireho
15495569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
15505569331642446be05292e3e1f8a51218827168cdclaireho    return error;
15515569331642446be05292e3e1f8a51218827168cdclaireho
15525569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
15535569331642446be05292e3e1f8a51218827168cdclaireho
15545569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
15555569331642446be05292e3e1f8a51218827168cdclaireho
15565569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
15575569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
15585569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_Coverage( &csf2->Coverage, stream ) ) != HB_Err_Ok )
15595569331642446be05292e3e1f8a51218827168cdclaireho    return error;
15605569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
15615569331642446be05292e3e1f8a51218827168cdclaireho
15625569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 4L ) )
15635569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
15645569331642446be05292e3e1f8a51218827168cdclaireho
15655569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
15665569331642446be05292e3e1f8a51218827168cdclaireho
15675569331642446be05292e3e1f8a51218827168cdclaireho  /* `SubClassSetCount' is the upper limit for class values, thus we
15685569331642446be05292e3e1f8a51218827168cdclaireho     read it now to make an additional safety check.                 */
15695569331642446be05292e3e1f8a51218827168cdclaireho
15705569331642446be05292e3e1f8a51218827168cdclaireho  count = csf2->SubClassSetCount = GET_UShort();
15715569331642446be05292e3e1f8a51218827168cdclaireho
15725569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
15735569331642446be05292e3e1f8a51218827168cdclaireho
15745569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
15755569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
15765569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_ClassDefinition( &csf2->ClassDef, count,
15775569331642446be05292e3e1f8a51218827168cdclaireho				       stream ) ) != HB_Err_Ok )
15785569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
15795569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
15805569331642446be05292e3e1f8a51218827168cdclaireho
15815569331642446be05292e3e1f8a51218827168cdclaireho  csf2->SubClassSet      = NULL;
15825569331642446be05292e3e1f8a51218827168cdclaireho  csf2->MaxContextLength = 0;
15835569331642446be05292e3e1f8a51218827168cdclaireho
15845569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( csf2->SubClassSet, count, HB_SubClassSet ) )
15855569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
15865569331642446be05292e3e1f8a51218827168cdclaireho
15875569331642446be05292e3e1f8a51218827168cdclaireho  scs = csf2->SubClassSet;
15885569331642446be05292e3e1f8a51218827168cdclaireho
15895569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
15905569331642446be05292e3e1f8a51218827168cdclaireho  {
15915569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
15925569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
15935569331642446be05292e3e1f8a51218827168cdclaireho
15945569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
15955569331642446be05292e3e1f8a51218827168cdclaireho
15965569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
15975569331642446be05292e3e1f8a51218827168cdclaireho
15985569331642446be05292e3e1f8a51218827168cdclaireho    if ( new_offset != base_offset )      /* not a NULL offset */
15995569331642446be05292e3e1f8a51218827168cdclaireho    {
16005569331642446be05292e3e1f8a51218827168cdclaireho      cur_offset = FILE_Pos();
16015569331642446be05292e3e1f8a51218827168cdclaireho      if ( FILE_Seek( new_offset ) ||
16025569331642446be05292e3e1f8a51218827168cdclaireho	   ( error = Load_SubClassSet( csf2, &scs[n],
16035569331642446be05292e3e1f8a51218827168cdclaireho				       stream ) ) != HB_Err_Ok )
16045569331642446be05292e3e1f8a51218827168cdclaireho	goto Fail1;
16055569331642446be05292e3e1f8a51218827168cdclaireho      (void)FILE_Seek( cur_offset );
16065569331642446be05292e3e1f8a51218827168cdclaireho    }
16075569331642446be05292e3e1f8a51218827168cdclaireho    else
16085569331642446be05292e3e1f8a51218827168cdclaireho    {
16095569331642446be05292e3e1f8a51218827168cdclaireho      /* we create a SubClassSet table with no entries */
16105569331642446be05292e3e1f8a51218827168cdclaireho
16115569331642446be05292e3e1f8a51218827168cdclaireho      csf2->SubClassSet[n].SubClassRuleCount = 0;
16125569331642446be05292e3e1f8a51218827168cdclaireho      csf2->SubClassSet[n].SubClassRule      = NULL;
16135569331642446be05292e3e1f8a51218827168cdclaireho    }
16145569331642446be05292e3e1f8a51218827168cdclaireho  }
16155569331642446be05292e3e1f8a51218827168cdclaireho
16165569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
16175569331642446be05292e3e1f8a51218827168cdclaireho
16185569331642446be05292e3e1f8a51218827168cdclairehoFail1:
16195569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
16205569331642446be05292e3e1f8a51218827168cdclaireho    Free_SubClassSet( &scs[m] );
16215569331642446be05292e3e1f8a51218827168cdclaireho
16225569331642446be05292e3e1f8a51218827168cdclaireho  FREE( scs );
16235569331642446be05292e3e1f8a51218827168cdclaireho
16245569331642446be05292e3e1f8a51218827168cdclairehoFail2:
16255569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_ClassDefinition( &csf2->ClassDef );
16265569331642446be05292e3e1f8a51218827168cdclaireho
16275569331642446be05292e3e1f8a51218827168cdclairehoFail3:
16285569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &csf2->Coverage );
16295569331642446be05292e3e1f8a51218827168cdclaireho  return error;
16305569331642446be05292e3e1f8a51218827168cdclaireho}
16315569331642446be05292e3e1f8a51218827168cdclaireho
16325569331642446be05292e3e1f8a51218827168cdclaireho
16335569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ContextSubst2( HB_ContextSubstFormat2*  csf2 )
16345569331642446be05292e3e1f8a51218827168cdclaireho{
16355569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort         n, count;
16365569331642446be05292e3e1f8a51218827168cdclaireho
16375569331642446be05292e3e1f8a51218827168cdclaireho  HB_SubClassSet*  scs;
16385569331642446be05292e3e1f8a51218827168cdclaireho
16395569331642446be05292e3e1f8a51218827168cdclaireho
16405569331642446be05292e3e1f8a51218827168cdclaireho  if ( csf2->SubClassSet )
16415569331642446be05292e3e1f8a51218827168cdclaireho  {
16425569331642446be05292e3e1f8a51218827168cdclaireho    count = csf2->SubClassSetCount;
16435569331642446be05292e3e1f8a51218827168cdclaireho    scs   = csf2->SubClassSet;
16445569331642446be05292e3e1f8a51218827168cdclaireho
16455569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
16465569331642446be05292e3e1f8a51218827168cdclaireho      Free_SubClassSet( &scs[n] );
16475569331642446be05292e3e1f8a51218827168cdclaireho
16485569331642446be05292e3e1f8a51218827168cdclaireho    FREE( scs );
16495569331642446be05292e3e1f8a51218827168cdclaireho  }
16505569331642446be05292e3e1f8a51218827168cdclaireho
16515569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_ClassDefinition( &csf2->ClassDef );
16525569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &csf2->Coverage );
16535569331642446be05292e3e1f8a51218827168cdclaireho}
16545569331642446be05292e3e1f8a51218827168cdclaireho
16555569331642446be05292e3e1f8a51218827168cdclaireho
16565569331642446be05292e3e1f8a51218827168cdclaireho/* ContextSubstFormat3 */
16575569331642446be05292e3e1f8a51218827168cdclaireho
16585569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ContextSubst3( HB_ContextSubstFormat3*  csf3,
16595569331642446be05292e3e1f8a51218827168cdclaireho				     HB_Stream                 stream )
16605569331642446be05292e3e1f8a51218827168cdclaireho{
16615569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
16625569331642446be05292e3e1f8a51218827168cdclaireho
16635569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort               n = 0, m, count;
16645569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt                cur_offset, new_offset, base_offset;
16655569331642446be05292e3e1f8a51218827168cdclaireho
16665569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*           c;
16675569331642446be05292e3e1f8a51218827168cdclaireho  HB_SubstLookupRecord*  slr;
16685569331642446be05292e3e1f8a51218827168cdclaireho
16695569331642446be05292e3e1f8a51218827168cdclaireho
16705569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos() - 2L;
16715569331642446be05292e3e1f8a51218827168cdclaireho
16725569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 4L ) )
16735569331642446be05292e3e1f8a51218827168cdclaireho    return error;
16745569331642446be05292e3e1f8a51218827168cdclaireho
16755569331642446be05292e3e1f8a51218827168cdclaireho  csf3->GlyphCount = GET_UShort();
16765569331642446be05292e3e1f8a51218827168cdclaireho  csf3->SubstCount = GET_UShort();
16775569331642446be05292e3e1f8a51218827168cdclaireho
16785569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
16795569331642446be05292e3e1f8a51218827168cdclaireho
16805569331642446be05292e3e1f8a51218827168cdclaireho  csf3->Coverage = NULL;
16815569331642446be05292e3e1f8a51218827168cdclaireho
16825569331642446be05292e3e1f8a51218827168cdclaireho  count = csf3->GlyphCount;
16835569331642446be05292e3e1f8a51218827168cdclaireho
16845569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( csf3->Coverage, count, HB_Coverage ) )
16855569331642446be05292e3e1f8a51218827168cdclaireho    return error;
16865569331642446be05292e3e1f8a51218827168cdclaireho
16875569331642446be05292e3e1f8a51218827168cdclaireho  c = csf3->Coverage;
16885569331642446be05292e3e1f8a51218827168cdclaireho
16895569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
16905569331642446be05292e3e1f8a51218827168cdclaireho  {
16915569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
16925569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail2;
16935569331642446be05292e3e1f8a51218827168cdclaireho
16945569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
16955569331642446be05292e3e1f8a51218827168cdclaireho
16965569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
16975569331642446be05292e3e1f8a51218827168cdclaireho
16985569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
16995569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
17005569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = _HB_OPEN_Load_Coverage( &c[n], stream ) ) != HB_Err_Ok )
17015569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail2;
17025569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
17035569331642446be05292e3e1f8a51218827168cdclaireho  }
17045569331642446be05292e3e1f8a51218827168cdclaireho
17055569331642446be05292e3e1f8a51218827168cdclaireho  csf3->SubstLookupRecord = NULL;
17065569331642446be05292e3e1f8a51218827168cdclaireho
17075569331642446be05292e3e1f8a51218827168cdclaireho  count = csf3->SubstCount;
17085569331642446be05292e3e1f8a51218827168cdclaireho
17095569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( csf3->SubstLookupRecord, count,
17105569331642446be05292e3e1f8a51218827168cdclaireho		    HB_SubstLookupRecord ) )
17115569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
17125569331642446be05292e3e1f8a51218827168cdclaireho
17135569331642446be05292e3e1f8a51218827168cdclaireho  slr = csf3->SubstLookupRecord;
17145569331642446be05292e3e1f8a51218827168cdclaireho
17155569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 4L ) )
17165569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail1;
17175569331642446be05292e3e1f8a51218827168cdclaireho
17185569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
17195569331642446be05292e3e1f8a51218827168cdclaireho  {
17205569331642446be05292e3e1f8a51218827168cdclaireho    slr[n].SequenceIndex   = GET_UShort();
17215569331642446be05292e3e1f8a51218827168cdclaireho    slr[n].LookupListIndex = GET_UShort();
17225569331642446be05292e3e1f8a51218827168cdclaireho  }
17235569331642446be05292e3e1f8a51218827168cdclaireho
17245569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
17255569331642446be05292e3e1f8a51218827168cdclaireho
17265569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
17275569331642446be05292e3e1f8a51218827168cdclaireho
17285569331642446be05292e3e1f8a51218827168cdclairehoFail1:
17295569331642446be05292e3e1f8a51218827168cdclaireho  FREE( slr );
17305569331642446be05292e3e1f8a51218827168cdclaireho
17315569331642446be05292e3e1f8a51218827168cdclairehoFail2:
17325569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
17335569331642446be05292e3e1f8a51218827168cdclaireho    _HB_OPEN_Free_Coverage( &c[m] );
17345569331642446be05292e3e1f8a51218827168cdclaireho
17355569331642446be05292e3e1f8a51218827168cdclaireho  FREE( c );
17365569331642446be05292e3e1f8a51218827168cdclaireho  return error;
17375569331642446be05292e3e1f8a51218827168cdclaireho}
17385569331642446be05292e3e1f8a51218827168cdclaireho
17395569331642446be05292e3e1f8a51218827168cdclaireho
17405569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ContextSubst3( HB_ContextSubstFormat3*  csf3 )
17415569331642446be05292e3e1f8a51218827168cdclaireho{
17425569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort      n, count;
17435569331642446be05292e3e1f8a51218827168cdclaireho
17445569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*  c;
17455569331642446be05292e3e1f8a51218827168cdclaireho
17465569331642446be05292e3e1f8a51218827168cdclaireho
17475569331642446be05292e3e1f8a51218827168cdclaireho  FREE( csf3->SubstLookupRecord );
17485569331642446be05292e3e1f8a51218827168cdclaireho
17495569331642446be05292e3e1f8a51218827168cdclaireho  if ( csf3->Coverage )
17505569331642446be05292e3e1f8a51218827168cdclaireho  {
17515569331642446be05292e3e1f8a51218827168cdclaireho    count = csf3->GlyphCount;
17525569331642446be05292e3e1f8a51218827168cdclaireho    c     = csf3->Coverage;
17535569331642446be05292e3e1f8a51218827168cdclaireho
17545569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
17555569331642446be05292e3e1f8a51218827168cdclaireho      _HB_OPEN_Free_Coverage( &c[n] );
17565569331642446be05292e3e1f8a51218827168cdclaireho
17575569331642446be05292e3e1f8a51218827168cdclaireho    FREE( c );
17585569331642446be05292e3e1f8a51218827168cdclaireho  }
17595569331642446be05292e3e1f8a51218827168cdclaireho}
17605569331642446be05292e3e1f8a51218827168cdclaireho
17615569331642446be05292e3e1f8a51218827168cdclaireho
17625569331642446be05292e3e1f8a51218827168cdclaireho/* ContextSubst */
17635569331642446be05292e3e1f8a51218827168cdclaireho
17645569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ContextSubst( HB_GSUB_SubTable* st,
17655569331642446be05292e3e1f8a51218827168cdclaireho				    HB_Stream         stream )
17665569331642446be05292e3e1f8a51218827168cdclaireho{
17675569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
17685569331642446be05292e3e1f8a51218827168cdclaireho  HB_ContextSubst*  cs = &st->context;
17695569331642446be05292e3e1f8a51218827168cdclaireho
17705569331642446be05292e3e1f8a51218827168cdclaireho
17715569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
17725569331642446be05292e3e1f8a51218827168cdclaireho    return error;
17735569331642446be05292e3e1f8a51218827168cdclaireho
17745569331642446be05292e3e1f8a51218827168cdclaireho  cs->SubstFormat = GET_UShort();
17755569331642446be05292e3e1f8a51218827168cdclaireho
17765569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
17775569331642446be05292e3e1f8a51218827168cdclaireho
17785569331642446be05292e3e1f8a51218827168cdclaireho  switch ( cs->SubstFormat )
17795569331642446be05292e3e1f8a51218827168cdclaireho  {
17805569331642446be05292e3e1f8a51218827168cdclaireho  case 1:  return Load_ContextSubst1( &cs->csf.csf1, stream );
17815569331642446be05292e3e1f8a51218827168cdclaireho  case 2:  return Load_ContextSubst2( &cs->csf.csf2, stream );
17825569331642446be05292e3e1f8a51218827168cdclaireho  case 3:  return Load_ContextSubst3( &cs->csf.csf3, stream );
17835569331642446be05292e3e1f8a51218827168cdclaireho  default: return ERR(HB_Err_Invalid_SubTable_Format);
17845569331642446be05292e3e1f8a51218827168cdclaireho  }
17855569331642446be05292e3e1f8a51218827168cdclaireho
17865569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;               /* never reached */
17875569331642446be05292e3e1f8a51218827168cdclaireho}
17885569331642446be05292e3e1f8a51218827168cdclaireho
17895569331642446be05292e3e1f8a51218827168cdclaireho
17905569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ContextSubst( HB_GSUB_SubTable* st )
17915569331642446be05292e3e1f8a51218827168cdclaireho{
17925569331642446be05292e3e1f8a51218827168cdclaireho  HB_ContextSubst*  cs = &st->context;
17935569331642446be05292e3e1f8a51218827168cdclaireho
17945569331642446be05292e3e1f8a51218827168cdclaireho  switch ( cs->SubstFormat )
17955569331642446be05292e3e1f8a51218827168cdclaireho  {
17965569331642446be05292e3e1f8a51218827168cdclaireho  case 1:  Free_ContextSubst1( &cs->csf.csf1 ); break;
17975569331642446be05292e3e1f8a51218827168cdclaireho  case 2:  Free_ContextSubst2( &cs->csf.csf2 ); break;
17985569331642446be05292e3e1f8a51218827168cdclaireho  case 3:  Free_ContextSubst3( &cs->csf.csf3 ); break;
17995569331642446be05292e3e1f8a51218827168cdclaireho  default:						break;
18005569331642446be05292e3e1f8a51218827168cdclaireho  }
18015569331642446be05292e3e1f8a51218827168cdclaireho}
18025569331642446be05292e3e1f8a51218827168cdclaireho
18035569331642446be05292e3e1f8a51218827168cdclaireho
18045569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_ContextSubst1( HB_GSUBHeader*          gsub,
18055569331642446be05292e3e1f8a51218827168cdclaireho				       HB_ContextSubstFormat1* csf1,
18065569331642446be05292e3e1f8a51218827168cdclaireho				       HB_Buffer               buffer,
18075569331642446be05292e3e1f8a51218827168cdclaireho				       HB_UShort                flags,
18085569331642446be05292e3e1f8a51218827168cdclaireho				       HB_UShort                context_length,
18095569331642446be05292e3e1f8a51218827168cdclaireho				       int                      nesting_level )
18105569331642446be05292e3e1f8a51218827168cdclaireho{
18115569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        index, property;
18125569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        i, j, k, numsr;
18135569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error         error;
18145569331642446be05292e3e1f8a51218827168cdclaireho
18155569331642446be05292e3e1f8a51218827168cdclaireho  HB_SubRule*     sr;
18165569331642446be05292e3e1f8a51218827168cdclaireho  HB_GDEFHeader*  gdef;
18175569331642446be05292e3e1f8a51218827168cdclaireho
18185569331642446be05292e3e1f8a51218827168cdclaireho
18195569331642446be05292e3e1f8a51218827168cdclaireho  gdef = gsub->gdef;
18205569331642446be05292e3e1f8a51218827168cdclaireho
18215569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
18225569331642446be05292e3e1f8a51218827168cdclaireho    return error;
18235569331642446be05292e3e1f8a51218827168cdclaireho
18245569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Coverage_Index( &csf1->Coverage, IN_CURGLYPH(), &index );
18255569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
18265569331642446be05292e3e1f8a51218827168cdclaireho    return error;
18275569331642446be05292e3e1f8a51218827168cdclaireho
18285569331642446be05292e3e1f8a51218827168cdclaireho  sr    = csf1->SubRuleSet[index].SubRule;
18295569331642446be05292e3e1f8a51218827168cdclaireho  numsr = csf1->SubRuleSet[index].SubRuleCount;
18305569331642446be05292e3e1f8a51218827168cdclaireho
18315569331642446be05292e3e1f8a51218827168cdclaireho  for ( k = 0; k < numsr; k++ )
18325569331642446be05292e3e1f8a51218827168cdclaireho  {
18335569331642446be05292e3e1f8a51218827168cdclaireho    if ( context_length != 0xFFFF && context_length < sr[k].GlyphCount )
18345569331642446be05292e3e1f8a51218827168cdclaireho      goto next_subrule;
18355569331642446be05292e3e1f8a51218827168cdclaireho
18365569331642446be05292e3e1f8a51218827168cdclaireho    if ( buffer->in_pos + sr[k].GlyphCount > buffer->in_length )
18375569331642446be05292e3e1f8a51218827168cdclaireho      goto next_subrule;                        /* context is too long */
18385569331642446be05292e3e1f8a51218827168cdclaireho
18395569331642446be05292e3e1f8a51218827168cdclaireho    for ( i = 1, j = buffer->in_pos + 1; i < sr[k].GlyphCount; i++, j++ )
18405569331642446be05292e3e1f8a51218827168cdclaireho    {
18415569331642446be05292e3e1f8a51218827168cdclaireho      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
18425569331642446be05292e3e1f8a51218827168cdclaireho      {
18435569331642446be05292e3e1f8a51218827168cdclaireho	if ( error && error != HB_Err_Not_Covered )
18445569331642446be05292e3e1f8a51218827168cdclaireho	  return error;
18455569331642446be05292e3e1f8a51218827168cdclaireho
18465569331642446be05292e3e1f8a51218827168cdclaireho	if ( j + sr[k].GlyphCount - i == (HB_Int)buffer->in_length )
18475569331642446be05292e3e1f8a51218827168cdclaireho	  goto next_subrule;
18485569331642446be05292e3e1f8a51218827168cdclaireho	j++;
18495569331642446be05292e3e1f8a51218827168cdclaireho      }
18505569331642446be05292e3e1f8a51218827168cdclaireho
18515569331642446be05292e3e1f8a51218827168cdclaireho      if ( IN_GLYPH( j ) != sr[k].Input[i - 1] )
18525569331642446be05292e3e1f8a51218827168cdclaireho	goto next_subrule;
18535569331642446be05292e3e1f8a51218827168cdclaireho    }
18545569331642446be05292e3e1f8a51218827168cdclaireho
18555569331642446be05292e3e1f8a51218827168cdclaireho    return Do_ContextSubst( gsub, sr[k].GlyphCount,
18565569331642446be05292e3e1f8a51218827168cdclaireho			    sr[k].SubstCount, sr[k].SubstLookupRecord,
18575569331642446be05292e3e1f8a51218827168cdclaireho			    buffer,
18585569331642446be05292e3e1f8a51218827168cdclaireho			    nesting_level );
18595569331642446be05292e3e1f8a51218827168cdclaireho  next_subrule:
18605569331642446be05292e3e1f8a51218827168cdclaireho    ;
18615569331642446be05292e3e1f8a51218827168cdclaireho  }
18625569331642446be05292e3e1f8a51218827168cdclaireho
18635569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Not_Covered;
18645569331642446be05292e3e1f8a51218827168cdclaireho}
18655569331642446be05292e3e1f8a51218827168cdclaireho
18665569331642446be05292e3e1f8a51218827168cdclaireho
18675569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_ContextSubst2( HB_GSUBHeader*          gsub,
18685569331642446be05292e3e1f8a51218827168cdclaireho				       HB_ContextSubstFormat2* csf2,
18695569331642446be05292e3e1f8a51218827168cdclaireho				       HB_Buffer               buffer,
18705569331642446be05292e3e1f8a51218827168cdclaireho				       HB_UShort                flags,
18715569331642446be05292e3e1f8a51218827168cdclaireho				       HB_UShort                context_length,
18725569331642446be05292e3e1f8a51218827168cdclaireho				       int                      nesting_level )
18735569331642446be05292e3e1f8a51218827168cdclaireho{
18745569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          index, property;
18755569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error           error;
18765569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          i, j, k, known_classes;
18775569331642446be05292e3e1f8a51218827168cdclaireho
18785569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*         classes;
18795569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*         cl;
18805569331642446be05292e3e1f8a51218827168cdclaireho
18815569331642446be05292e3e1f8a51218827168cdclaireho  HB_SubClassSet*   scs;
18825569331642446be05292e3e1f8a51218827168cdclaireho  HB_SubClassRule*  sr;
18835569331642446be05292e3e1f8a51218827168cdclaireho  HB_GDEFHeader*    gdef;
18845569331642446be05292e3e1f8a51218827168cdclaireho
18855569331642446be05292e3e1f8a51218827168cdclaireho
18865569331642446be05292e3e1f8a51218827168cdclaireho  gdef = gsub->gdef;
18875569331642446be05292e3e1f8a51218827168cdclaireho
18885569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
18895569331642446be05292e3e1f8a51218827168cdclaireho    return error;
18905569331642446be05292e3e1f8a51218827168cdclaireho
18915569331642446be05292e3e1f8a51218827168cdclaireho  /* Note: The coverage table in format 2 doesn't give an index into
18925569331642446be05292e3e1f8a51218827168cdclaireho	   anything.  It just lets us know whether or not we need to
18935569331642446be05292e3e1f8a51218827168cdclaireho	   do any lookup at all.                                     */
18945569331642446be05292e3e1f8a51218827168cdclaireho
18955569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Coverage_Index( &csf2->Coverage, IN_CURGLYPH(), &index );
18965569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
18975569331642446be05292e3e1f8a51218827168cdclaireho    return error;
18985569331642446be05292e3e1f8a51218827168cdclaireho
18995569331642446be05292e3e1f8a51218827168cdclaireho  if (csf2->MaxContextLength < 1)
19005569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
19015569331642446be05292e3e1f8a51218827168cdclaireho
19025569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( classes, csf2->MaxContextLength, HB_UShort ) )
19035569331642446be05292e3e1f8a51218827168cdclaireho    return error;
19045569331642446be05292e3e1f8a51218827168cdclaireho
19055569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Get_Class( &csf2->ClassDef, IN_CURGLYPH(),
19065569331642446be05292e3e1f8a51218827168cdclaireho		     &classes[0], NULL );
19075569331642446be05292e3e1f8a51218827168cdclaireho  if ( error && error != HB_Err_Not_Covered )
19085569331642446be05292e3e1f8a51218827168cdclaireho    goto End;
19095569331642446be05292e3e1f8a51218827168cdclaireho  known_classes = 0;
19105569331642446be05292e3e1f8a51218827168cdclaireho
19115569331642446be05292e3e1f8a51218827168cdclaireho  scs = &csf2->SubClassSet[classes[0]];
19125569331642446be05292e3e1f8a51218827168cdclaireho  if ( !scs )
19135569331642446be05292e3e1f8a51218827168cdclaireho  {
19145569331642446be05292e3e1f8a51218827168cdclaireho    error = ERR(HB_Err_Invalid_SubTable);
19155569331642446be05292e3e1f8a51218827168cdclaireho    goto End;
19165569331642446be05292e3e1f8a51218827168cdclaireho  }
19175569331642446be05292e3e1f8a51218827168cdclaireho
19185569331642446be05292e3e1f8a51218827168cdclaireho  for ( k = 0; k < scs->SubClassRuleCount; k++ )
19195569331642446be05292e3e1f8a51218827168cdclaireho  {
19205569331642446be05292e3e1f8a51218827168cdclaireho    sr  = &scs->SubClassRule[k];
19215569331642446be05292e3e1f8a51218827168cdclaireho
19225569331642446be05292e3e1f8a51218827168cdclaireho    if ( context_length != 0xFFFF && context_length < sr->GlyphCount )
19235569331642446be05292e3e1f8a51218827168cdclaireho      goto next_subclassrule;
19245569331642446be05292e3e1f8a51218827168cdclaireho
19255569331642446be05292e3e1f8a51218827168cdclaireho    if ( buffer->in_pos + sr->GlyphCount > buffer->in_length )
19265569331642446be05292e3e1f8a51218827168cdclaireho      goto next_subclassrule;                      /* context is too long */
19275569331642446be05292e3e1f8a51218827168cdclaireho
19285569331642446be05292e3e1f8a51218827168cdclaireho    cl   = sr->Class;
19295569331642446be05292e3e1f8a51218827168cdclaireho
19305569331642446be05292e3e1f8a51218827168cdclaireho    /* Start at 1 because [0] is implied */
19315569331642446be05292e3e1f8a51218827168cdclaireho
19325569331642446be05292e3e1f8a51218827168cdclaireho    for ( i = 1, j = buffer->in_pos + 1; i < sr->GlyphCount; i++, j++ )
19335569331642446be05292e3e1f8a51218827168cdclaireho    {
19345569331642446be05292e3e1f8a51218827168cdclaireho      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
19355569331642446be05292e3e1f8a51218827168cdclaireho      {
19365569331642446be05292e3e1f8a51218827168cdclaireho	if ( error && error != HB_Err_Not_Covered )
19375569331642446be05292e3e1f8a51218827168cdclaireho	  goto End;
19385569331642446be05292e3e1f8a51218827168cdclaireho
19395569331642446be05292e3e1f8a51218827168cdclaireho	if ( j + sr->GlyphCount - i < (HB_Int)buffer->in_length )
19405569331642446be05292e3e1f8a51218827168cdclaireho	  goto next_subclassrule;
19415569331642446be05292e3e1f8a51218827168cdclaireho	j++;
19425569331642446be05292e3e1f8a51218827168cdclaireho      }
19435569331642446be05292e3e1f8a51218827168cdclaireho
19445569331642446be05292e3e1f8a51218827168cdclaireho      if ( i > known_classes )
19455569331642446be05292e3e1f8a51218827168cdclaireho      {
19465569331642446be05292e3e1f8a51218827168cdclaireho	/* Keeps us from having to do this for each rule */
19475569331642446be05292e3e1f8a51218827168cdclaireho
19485569331642446be05292e3e1f8a51218827168cdclaireho	error = _HB_OPEN_Get_Class( &csf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL );
19495569331642446be05292e3e1f8a51218827168cdclaireho	if ( error && error != HB_Err_Not_Covered )
19505569331642446be05292e3e1f8a51218827168cdclaireho	  goto End;
19515569331642446be05292e3e1f8a51218827168cdclaireho	known_classes = i;
19525569331642446be05292e3e1f8a51218827168cdclaireho      }
19535569331642446be05292e3e1f8a51218827168cdclaireho
19545569331642446be05292e3e1f8a51218827168cdclaireho      if ( cl[i - 1] != classes[i] )
19555569331642446be05292e3e1f8a51218827168cdclaireho	goto next_subclassrule;
19565569331642446be05292e3e1f8a51218827168cdclaireho    }
19575569331642446be05292e3e1f8a51218827168cdclaireho
19585569331642446be05292e3e1f8a51218827168cdclaireho    error = Do_ContextSubst( gsub, sr->GlyphCount,
19595569331642446be05292e3e1f8a51218827168cdclaireho			     sr->SubstCount, sr->SubstLookupRecord,
19605569331642446be05292e3e1f8a51218827168cdclaireho			     buffer,
19615569331642446be05292e3e1f8a51218827168cdclaireho			     nesting_level );
19625569331642446be05292e3e1f8a51218827168cdclaireho    goto End;
19635569331642446be05292e3e1f8a51218827168cdclaireho
19645569331642446be05292e3e1f8a51218827168cdclaireho  next_subclassrule:
19655569331642446be05292e3e1f8a51218827168cdclaireho    ;
19665569331642446be05292e3e1f8a51218827168cdclaireho  }
19675569331642446be05292e3e1f8a51218827168cdclaireho
19685569331642446be05292e3e1f8a51218827168cdclaireho  error = HB_Err_Not_Covered;
19695569331642446be05292e3e1f8a51218827168cdclaireho
19705569331642446be05292e3e1f8a51218827168cdclairehoEnd:
19715569331642446be05292e3e1f8a51218827168cdclaireho  FREE( classes );
19725569331642446be05292e3e1f8a51218827168cdclaireho  return error;
19735569331642446be05292e3e1f8a51218827168cdclaireho}
19745569331642446be05292e3e1f8a51218827168cdclaireho
19755569331642446be05292e3e1f8a51218827168cdclaireho
19765569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_ContextSubst3( HB_GSUBHeader*          gsub,
19775569331642446be05292e3e1f8a51218827168cdclaireho				       HB_ContextSubstFormat3* csf3,
19785569331642446be05292e3e1f8a51218827168cdclaireho				       HB_Buffer               buffer,
19795569331642446be05292e3e1f8a51218827168cdclaireho				       HB_UShort                flags,
19805569331642446be05292e3e1f8a51218827168cdclaireho				       HB_UShort                context_length,
19815569331642446be05292e3e1f8a51218827168cdclaireho				       int                      nesting_level )
19825569331642446be05292e3e1f8a51218827168cdclaireho{
19835569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error         error;
19845569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        index, i, j, property;
19855569331642446be05292e3e1f8a51218827168cdclaireho
19865569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*    c;
19875569331642446be05292e3e1f8a51218827168cdclaireho  HB_GDEFHeader*  gdef;
19885569331642446be05292e3e1f8a51218827168cdclaireho
19895569331642446be05292e3e1f8a51218827168cdclaireho
19905569331642446be05292e3e1f8a51218827168cdclaireho  gdef = gsub->gdef;
19915569331642446be05292e3e1f8a51218827168cdclaireho
19925569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
19935569331642446be05292e3e1f8a51218827168cdclaireho    return error;
19945569331642446be05292e3e1f8a51218827168cdclaireho
19955569331642446be05292e3e1f8a51218827168cdclaireho  if ( context_length != 0xFFFF && context_length < csf3->GlyphCount )
19965569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
19975569331642446be05292e3e1f8a51218827168cdclaireho
19985569331642446be05292e3e1f8a51218827168cdclaireho  if ( buffer->in_pos + csf3->GlyphCount > buffer->in_length )
19995569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;         /* context is too long */
20005569331642446be05292e3e1f8a51218827168cdclaireho
20015569331642446be05292e3e1f8a51218827168cdclaireho  c    = csf3->Coverage;
20025569331642446be05292e3e1f8a51218827168cdclaireho
20035569331642446be05292e3e1f8a51218827168cdclaireho  for ( i = 1, j = buffer->in_pos + 1; i < csf3->GlyphCount; i++, j++ )
20045569331642446be05292e3e1f8a51218827168cdclaireho  {
20055569331642446be05292e3e1f8a51218827168cdclaireho    while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
20065569331642446be05292e3e1f8a51218827168cdclaireho    {
20075569331642446be05292e3e1f8a51218827168cdclaireho      if ( error && error != HB_Err_Not_Covered )
20085569331642446be05292e3e1f8a51218827168cdclaireho	return error;
20095569331642446be05292e3e1f8a51218827168cdclaireho
20105569331642446be05292e3e1f8a51218827168cdclaireho      if ( j + csf3->GlyphCount - i == (HB_Int)buffer->in_length )
20115569331642446be05292e3e1f8a51218827168cdclaireho	return HB_Err_Not_Covered;
20125569331642446be05292e3e1f8a51218827168cdclaireho      j++;
20135569331642446be05292e3e1f8a51218827168cdclaireho    }
20145569331642446be05292e3e1f8a51218827168cdclaireho
20155569331642446be05292e3e1f8a51218827168cdclaireho    error = _HB_OPEN_Coverage_Index( &c[i], IN_GLYPH( j ), &index );
20165569331642446be05292e3e1f8a51218827168cdclaireho    if ( error )
20175569331642446be05292e3e1f8a51218827168cdclaireho      return error;
20185569331642446be05292e3e1f8a51218827168cdclaireho  }
20195569331642446be05292e3e1f8a51218827168cdclaireho
20205569331642446be05292e3e1f8a51218827168cdclaireho  return Do_ContextSubst( gsub, csf3->GlyphCount,
20215569331642446be05292e3e1f8a51218827168cdclaireho			  csf3->SubstCount, csf3->SubstLookupRecord,
20225569331642446be05292e3e1f8a51218827168cdclaireho			  buffer,
20235569331642446be05292e3e1f8a51218827168cdclaireho			  nesting_level );
20245569331642446be05292e3e1f8a51218827168cdclaireho}
20255569331642446be05292e3e1f8a51218827168cdclaireho
20265569331642446be05292e3e1f8a51218827168cdclaireho
20275569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_ContextSubst( HB_GSUBHeader*    gsub,
20285569331642446be05292e3e1f8a51218827168cdclaireho				      HB_GSUB_SubTable* st,
20295569331642446be05292e3e1f8a51218827168cdclaireho				      HB_Buffer         buffer,
20305569331642446be05292e3e1f8a51218827168cdclaireho				      HB_UShort          flags,
20315569331642446be05292e3e1f8a51218827168cdclaireho				      HB_UShort          context_length,
20325569331642446be05292e3e1f8a51218827168cdclaireho				      int                nesting_level )
20335569331642446be05292e3e1f8a51218827168cdclaireho{
20345569331642446be05292e3e1f8a51218827168cdclaireho  HB_ContextSubst*  cs = &st->context;
20355569331642446be05292e3e1f8a51218827168cdclaireho
20365569331642446be05292e3e1f8a51218827168cdclaireho  switch ( cs->SubstFormat )
20375569331642446be05292e3e1f8a51218827168cdclaireho  {
20385569331642446be05292e3e1f8a51218827168cdclaireho  case 1:  return Lookup_ContextSubst1( gsub, &cs->csf.csf1, buffer, flags, context_length, nesting_level );
20395569331642446be05292e3e1f8a51218827168cdclaireho  case 2:  return Lookup_ContextSubst2( gsub, &cs->csf.csf2, buffer, flags, context_length, nesting_level );
20405569331642446be05292e3e1f8a51218827168cdclaireho  case 3:  return Lookup_ContextSubst3( gsub, &cs->csf.csf3, buffer, flags, context_length, nesting_level );
20415569331642446be05292e3e1f8a51218827168cdclaireho  default: return ERR(HB_Err_Invalid_SubTable_Format);
20425569331642446be05292e3e1f8a51218827168cdclaireho  }
20435569331642446be05292e3e1f8a51218827168cdclaireho
20445569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;               /* never reached */
20455569331642446be05292e3e1f8a51218827168cdclaireho}
20465569331642446be05292e3e1f8a51218827168cdclaireho
20475569331642446be05292e3e1f8a51218827168cdclaireho
20485569331642446be05292e3e1f8a51218827168cdclaireho/* LookupType 6 */
20495569331642446be05292e3e1f8a51218827168cdclaireho
20505569331642446be05292e3e1f8a51218827168cdclaireho/* ChainSubRule */
20515569331642446be05292e3e1f8a51218827168cdclaireho
20525569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ChainSubRule( HB_ChainSubRule*  csr,
20535569331642446be05292e3e1f8a51218827168cdclaireho				    HB_Stream          stream )
20545569331642446be05292e3e1f8a51218827168cdclaireho{
20555569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
20565569331642446be05292e3e1f8a51218827168cdclaireho
20575569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort               n, count;
20585569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*              b;
20595569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*              i;
20605569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*              l;
20615569331642446be05292e3e1f8a51218827168cdclaireho
20625569331642446be05292e3e1f8a51218827168cdclaireho  HB_SubstLookupRecord*  slr;
20635569331642446be05292e3e1f8a51218827168cdclaireho
20645569331642446be05292e3e1f8a51218827168cdclaireho
20655569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
20665569331642446be05292e3e1f8a51218827168cdclaireho    return error;
20675569331642446be05292e3e1f8a51218827168cdclaireho
20685569331642446be05292e3e1f8a51218827168cdclaireho  csr->BacktrackGlyphCount = GET_UShort();
20695569331642446be05292e3e1f8a51218827168cdclaireho
20705569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
20715569331642446be05292e3e1f8a51218827168cdclaireho
20725569331642446be05292e3e1f8a51218827168cdclaireho  csr->Backtrack = NULL;
20735569331642446be05292e3e1f8a51218827168cdclaireho
20745569331642446be05292e3e1f8a51218827168cdclaireho  count = csr->BacktrackGlyphCount;
20755569331642446be05292e3e1f8a51218827168cdclaireho
20765569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( csr->Backtrack, count, HB_UShort ) )
20775569331642446be05292e3e1f8a51218827168cdclaireho    return error;
20785569331642446be05292e3e1f8a51218827168cdclaireho
20795569331642446be05292e3e1f8a51218827168cdclaireho  b = csr->Backtrack;
20805569331642446be05292e3e1f8a51218827168cdclaireho
20815569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
20825569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
20835569331642446be05292e3e1f8a51218827168cdclaireho
20845569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
20855569331642446be05292e3e1f8a51218827168cdclaireho    b[n] = GET_UShort();
20865569331642446be05292e3e1f8a51218827168cdclaireho
20875569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
20885569331642446be05292e3e1f8a51218827168cdclaireho
20895569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
20905569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
20915569331642446be05292e3e1f8a51218827168cdclaireho
20925569331642446be05292e3e1f8a51218827168cdclaireho  csr->InputGlyphCount = GET_UShort();
20935569331642446be05292e3e1f8a51218827168cdclaireho
20945569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
20955569331642446be05292e3e1f8a51218827168cdclaireho
20965569331642446be05292e3e1f8a51218827168cdclaireho  csr->Input = NULL;
20975569331642446be05292e3e1f8a51218827168cdclaireho
20985569331642446be05292e3e1f8a51218827168cdclaireho  count = csr->InputGlyphCount - 1;  /* only InputGlyphCount - 1 elements */
20995569331642446be05292e3e1f8a51218827168cdclaireho
21005569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( csr->Input, count, HB_UShort ) )
21015569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
21025569331642446be05292e3e1f8a51218827168cdclaireho
21035569331642446be05292e3e1f8a51218827168cdclaireho  i = csr->Input;
21045569331642446be05292e3e1f8a51218827168cdclaireho
21055569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
21065569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
21075569331642446be05292e3e1f8a51218827168cdclaireho
21085569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
21095569331642446be05292e3e1f8a51218827168cdclaireho    i[n] = GET_UShort();
21105569331642446be05292e3e1f8a51218827168cdclaireho
21115569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
21125569331642446be05292e3e1f8a51218827168cdclaireho
21135569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
21145569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
21155569331642446be05292e3e1f8a51218827168cdclaireho
21165569331642446be05292e3e1f8a51218827168cdclaireho  csr->LookaheadGlyphCount = GET_UShort();
21175569331642446be05292e3e1f8a51218827168cdclaireho
21185569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
21195569331642446be05292e3e1f8a51218827168cdclaireho
21205569331642446be05292e3e1f8a51218827168cdclaireho  csr->Lookahead = NULL;
21215569331642446be05292e3e1f8a51218827168cdclaireho
21225569331642446be05292e3e1f8a51218827168cdclaireho  count = csr->LookaheadGlyphCount;
21235569331642446be05292e3e1f8a51218827168cdclaireho
21245569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( csr->Lookahead, count, HB_UShort ) )
21255569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
21265569331642446be05292e3e1f8a51218827168cdclaireho
21275569331642446be05292e3e1f8a51218827168cdclaireho  l = csr->Lookahead;
21285569331642446be05292e3e1f8a51218827168cdclaireho
21295569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
21305569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
21315569331642446be05292e3e1f8a51218827168cdclaireho
21325569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
21335569331642446be05292e3e1f8a51218827168cdclaireho    l[n] = GET_UShort();
21345569331642446be05292e3e1f8a51218827168cdclaireho
21355569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
21365569331642446be05292e3e1f8a51218827168cdclaireho
21375569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
21385569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
21395569331642446be05292e3e1f8a51218827168cdclaireho
21405569331642446be05292e3e1f8a51218827168cdclaireho  csr->SubstCount = GET_UShort();
21415569331642446be05292e3e1f8a51218827168cdclaireho
21425569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
21435569331642446be05292e3e1f8a51218827168cdclaireho
21445569331642446be05292e3e1f8a51218827168cdclaireho  csr->SubstLookupRecord = NULL;
21455569331642446be05292e3e1f8a51218827168cdclaireho
21465569331642446be05292e3e1f8a51218827168cdclaireho  count = csr->SubstCount;
21475569331642446be05292e3e1f8a51218827168cdclaireho
21485569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( csr->SubstLookupRecord, count, HB_SubstLookupRecord ) )
21495569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
21505569331642446be05292e3e1f8a51218827168cdclaireho
21515569331642446be05292e3e1f8a51218827168cdclaireho  slr = csr->SubstLookupRecord;
21525569331642446be05292e3e1f8a51218827168cdclaireho
21535569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 4L ) )
21545569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail1;
21555569331642446be05292e3e1f8a51218827168cdclaireho
21565569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
21575569331642446be05292e3e1f8a51218827168cdclaireho  {
21585569331642446be05292e3e1f8a51218827168cdclaireho    slr[n].SequenceIndex   = GET_UShort();
21595569331642446be05292e3e1f8a51218827168cdclaireho    slr[n].LookupListIndex = GET_UShort();
21605569331642446be05292e3e1f8a51218827168cdclaireho  }
21615569331642446be05292e3e1f8a51218827168cdclaireho
21625569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
21635569331642446be05292e3e1f8a51218827168cdclaireho
21645569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
21655569331642446be05292e3e1f8a51218827168cdclaireho
21665569331642446be05292e3e1f8a51218827168cdclairehoFail1:
21675569331642446be05292e3e1f8a51218827168cdclaireho  FREE( slr );
21685569331642446be05292e3e1f8a51218827168cdclaireho
21695569331642446be05292e3e1f8a51218827168cdclairehoFail2:
21705569331642446be05292e3e1f8a51218827168cdclaireho  FREE( l );
21715569331642446be05292e3e1f8a51218827168cdclaireho
21725569331642446be05292e3e1f8a51218827168cdclairehoFail3:
21735569331642446be05292e3e1f8a51218827168cdclaireho  FREE( i );
21745569331642446be05292e3e1f8a51218827168cdclaireho
21755569331642446be05292e3e1f8a51218827168cdclairehoFail4:
21765569331642446be05292e3e1f8a51218827168cdclaireho  FREE( b );
21775569331642446be05292e3e1f8a51218827168cdclaireho  return error;
21785569331642446be05292e3e1f8a51218827168cdclaireho}
21795569331642446be05292e3e1f8a51218827168cdclaireho
21805569331642446be05292e3e1f8a51218827168cdclaireho
21815569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ChainSubRule( HB_ChainSubRule*  csr )
21825569331642446be05292e3e1f8a51218827168cdclaireho{
21835569331642446be05292e3e1f8a51218827168cdclaireho  FREE( csr->SubstLookupRecord );
21845569331642446be05292e3e1f8a51218827168cdclaireho  FREE( csr->Lookahead );
21855569331642446be05292e3e1f8a51218827168cdclaireho  FREE( csr->Input );
21865569331642446be05292e3e1f8a51218827168cdclaireho  FREE( csr->Backtrack );
21875569331642446be05292e3e1f8a51218827168cdclaireho}
21885569331642446be05292e3e1f8a51218827168cdclaireho
21895569331642446be05292e3e1f8a51218827168cdclaireho
21905569331642446be05292e3e1f8a51218827168cdclaireho/* ChainSubRuleSet */
21915569331642446be05292e3e1f8a51218827168cdclaireho
21925569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ChainSubRuleSet( HB_ChainSubRuleSet*  csrs,
21935569331642446be05292e3e1f8a51218827168cdclaireho				       HB_Stream             stream )
21945569331642446be05292e3e1f8a51218827168cdclaireho{
21955569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
21965569331642446be05292e3e1f8a51218827168cdclaireho
21975569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          n = 0, m, count;
21985569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt           cur_offset, new_offset, base_offset;
21995569331642446be05292e3e1f8a51218827168cdclaireho
22005569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainSubRule*  csr;
22015569331642446be05292e3e1f8a51218827168cdclaireho
22025569331642446be05292e3e1f8a51218827168cdclaireho
22035569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
22045569331642446be05292e3e1f8a51218827168cdclaireho
22055569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
22065569331642446be05292e3e1f8a51218827168cdclaireho    return error;
22075569331642446be05292e3e1f8a51218827168cdclaireho
22085569331642446be05292e3e1f8a51218827168cdclaireho  count = csrs->ChainSubRuleCount = GET_UShort();
22095569331642446be05292e3e1f8a51218827168cdclaireho
22105569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
22115569331642446be05292e3e1f8a51218827168cdclaireho
22125569331642446be05292e3e1f8a51218827168cdclaireho  csrs->ChainSubRule = NULL;
22135569331642446be05292e3e1f8a51218827168cdclaireho
22145569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( csrs->ChainSubRule, count, HB_ChainSubRule ) )
22155569331642446be05292e3e1f8a51218827168cdclaireho    return error;
22165569331642446be05292e3e1f8a51218827168cdclaireho
22175569331642446be05292e3e1f8a51218827168cdclaireho  csr = csrs->ChainSubRule;
22185569331642446be05292e3e1f8a51218827168cdclaireho
22195569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
22205569331642446be05292e3e1f8a51218827168cdclaireho  {
22215569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
22225569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
22235569331642446be05292e3e1f8a51218827168cdclaireho
22245569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
22255569331642446be05292e3e1f8a51218827168cdclaireho
22265569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
22275569331642446be05292e3e1f8a51218827168cdclaireho
22285569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
22295569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
22305569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_ChainSubRule( &csr[n], stream ) ) != HB_Err_Ok )
22315569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
22325569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
22335569331642446be05292e3e1f8a51218827168cdclaireho  }
22345569331642446be05292e3e1f8a51218827168cdclaireho
22355569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
22365569331642446be05292e3e1f8a51218827168cdclaireho
22375569331642446be05292e3e1f8a51218827168cdclairehoFail:
22385569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
22395569331642446be05292e3e1f8a51218827168cdclaireho    Free_ChainSubRule( &csr[m] );
22405569331642446be05292e3e1f8a51218827168cdclaireho
22415569331642446be05292e3e1f8a51218827168cdclaireho  FREE( csr );
22425569331642446be05292e3e1f8a51218827168cdclaireho  return error;
22435569331642446be05292e3e1f8a51218827168cdclaireho}
22445569331642446be05292e3e1f8a51218827168cdclaireho
22455569331642446be05292e3e1f8a51218827168cdclaireho
22465569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ChainSubRuleSet( HB_ChainSubRuleSet*  csrs )
22475569331642446be05292e3e1f8a51218827168cdclaireho{
22485569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          n, count;
22495569331642446be05292e3e1f8a51218827168cdclaireho
22505569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainSubRule*  csr;
22515569331642446be05292e3e1f8a51218827168cdclaireho
22525569331642446be05292e3e1f8a51218827168cdclaireho
22535569331642446be05292e3e1f8a51218827168cdclaireho  if ( csrs->ChainSubRule )
22545569331642446be05292e3e1f8a51218827168cdclaireho  {
22555569331642446be05292e3e1f8a51218827168cdclaireho    count = csrs->ChainSubRuleCount;
22565569331642446be05292e3e1f8a51218827168cdclaireho    csr   = csrs->ChainSubRule;
22575569331642446be05292e3e1f8a51218827168cdclaireho
22585569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
22595569331642446be05292e3e1f8a51218827168cdclaireho      Free_ChainSubRule( &csr[n] );
22605569331642446be05292e3e1f8a51218827168cdclaireho
22615569331642446be05292e3e1f8a51218827168cdclaireho    FREE( csr );
22625569331642446be05292e3e1f8a51218827168cdclaireho  }
22635569331642446be05292e3e1f8a51218827168cdclaireho}
22645569331642446be05292e3e1f8a51218827168cdclaireho
22655569331642446be05292e3e1f8a51218827168cdclaireho
22665569331642446be05292e3e1f8a51218827168cdclaireho/* ChainContextSubstFormat1 */
22675569331642446be05292e3e1f8a51218827168cdclaireho
22685569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ChainContextSubst1(
22695569331642446be05292e3e1f8a51218827168cdclaireho		   HB_ChainContextSubstFormat1*  ccsf1,
22705569331642446be05292e3e1f8a51218827168cdclaireho		   HB_Stream                      stream )
22715569331642446be05292e3e1f8a51218827168cdclaireho{
22725569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
22735569331642446be05292e3e1f8a51218827168cdclaireho
22745569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort             n = 0, m, count;
22755569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt              cur_offset, new_offset, base_offset;
22765569331642446be05292e3e1f8a51218827168cdclaireho
22775569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainSubRuleSet*  csrs;
22785569331642446be05292e3e1f8a51218827168cdclaireho
22795569331642446be05292e3e1f8a51218827168cdclaireho
22805569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos() - 2L;
22815569331642446be05292e3e1f8a51218827168cdclaireho
22825569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
22835569331642446be05292e3e1f8a51218827168cdclaireho    return error;
22845569331642446be05292e3e1f8a51218827168cdclaireho
22855569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
22865569331642446be05292e3e1f8a51218827168cdclaireho
22875569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
22885569331642446be05292e3e1f8a51218827168cdclaireho
22895569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
22905569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
22915569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_Coverage( &ccsf1->Coverage, stream ) ) != HB_Err_Ok )
22925569331642446be05292e3e1f8a51218827168cdclaireho    return error;
22935569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
22945569331642446be05292e3e1f8a51218827168cdclaireho
22955569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
22965569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
22975569331642446be05292e3e1f8a51218827168cdclaireho
22985569331642446be05292e3e1f8a51218827168cdclaireho  count = ccsf1->ChainSubRuleSetCount = GET_UShort();
22995569331642446be05292e3e1f8a51218827168cdclaireho
23005569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
23015569331642446be05292e3e1f8a51218827168cdclaireho
23025569331642446be05292e3e1f8a51218827168cdclaireho  ccsf1->ChainSubRuleSet = NULL;
23035569331642446be05292e3e1f8a51218827168cdclaireho
23045569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ccsf1->ChainSubRuleSet, count, HB_ChainSubRuleSet ) )
23055569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
23065569331642446be05292e3e1f8a51218827168cdclaireho
23075569331642446be05292e3e1f8a51218827168cdclaireho  csrs = ccsf1->ChainSubRuleSet;
23085569331642446be05292e3e1f8a51218827168cdclaireho
23095569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
23105569331642446be05292e3e1f8a51218827168cdclaireho  {
23115569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
23125569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
23135569331642446be05292e3e1f8a51218827168cdclaireho
23145569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
23155569331642446be05292e3e1f8a51218827168cdclaireho
23165569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
23175569331642446be05292e3e1f8a51218827168cdclaireho
23185569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
23195569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
23205569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_ChainSubRuleSet( &csrs[n], stream ) ) != HB_Err_Ok )
23215569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
23225569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
23235569331642446be05292e3e1f8a51218827168cdclaireho  }
23245569331642446be05292e3e1f8a51218827168cdclaireho
23255569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
23265569331642446be05292e3e1f8a51218827168cdclaireho
23275569331642446be05292e3e1f8a51218827168cdclairehoFail1:
23285569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
23295569331642446be05292e3e1f8a51218827168cdclaireho    Free_ChainSubRuleSet( &csrs[m] );
23305569331642446be05292e3e1f8a51218827168cdclaireho
23315569331642446be05292e3e1f8a51218827168cdclaireho  FREE( csrs );
23325569331642446be05292e3e1f8a51218827168cdclaireho
23335569331642446be05292e3e1f8a51218827168cdclairehoFail2:
23345569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &ccsf1->Coverage );
23355569331642446be05292e3e1f8a51218827168cdclaireho  return error;
23365569331642446be05292e3e1f8a51218827168cdclaireho}
23375569331642446be05292e3e1f8a51218827168cdclaireho
23385569331642446be05292e3e1f8a51218827168cdclaireho
23395569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ChainContextSubst1( HB_ChainContextSubstFormat1*  ccsf1 )
23405569331642446be05292e3e1f8a51218827168cdclaireho{
23415569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort             n, count;
23425569331642446be05292e3e1f8a51218827168cdclaireho
23435569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainSubRuleSet*  csrs;
23445569331642446be05292e3e1f8a51218827168cdclaireho
23455569331642446be05292e3e1f8a51218827168cdclaireho
23465569331642446be05292e3e1f8a51218827168cdclaireho  if ( ccsf1->ChainSubRuleSet )
23475569331642446be05292e3e1f8a51218827168cdclaireho  {
23485569331642446be05292e3e1f8a51218827168cdclaireho    count = ccsf1->ChainSubRuleSetCount;
23495569331642446be05292e3e1f8a51218827168cdclaireho    csrs  = ccsf1->ChainSubRuleSet;
23505569331642446be05292e3e1f8a51218827168cdclaireho
23515569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
23525569331642446be05292e3e1f8a51218827168cdclaireho      Free_ChainSubRuleSet( &csrs[n] );
23535569331642446be05292e3e1f8a51218827168cdclaireho
23545569331642446be05292e3e1f8a51218827168cdclaireho    FREE( csrs );
23555569331642446be05292e3e1f8a51218827168cdclaireho  }
23565569331642446be05292e3e1f8a51218827168cdclaireho
23575569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &ccsf1->Coverage );
23585569331642446be05292e3e1f8a51218827168cdclaireho}
23595569331642446be05292e3e1f8a51218827168cdclaireho
23605569331642446be05292e3e1f8a51218827168cdclaireho
23615569331642446be05292e3e1f8a51218827168cdclaireho/* ChainSubClassRule */
23625569331642446be05292e3e1f8a51218827168cdclaireho
23635569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ChainSubClassRule(
23645569331642446be05292e3e1f8a51218827168cdclaireho		   HB_ChainContextSubstFormat2*  ccsf2,
23655569331642446be05292e3e1f8a51218827168cdclaireho		   HB_ChainSubClassRule*         cscr,
23665569331642446be05292e3e1f8a51218827168cdclaireho		   HB_Stream                      stream )
23675569331642446be05292e3e1f8a51218827168cdclaireho{
23685569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
23695569331642446be05292e3e1f8a51218827168cdclaireho
23705569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort               n, count;
23715569331642446be05292e3e1f8a51218827168cdclaireho
23725569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*              b;
23735569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*              i;
23745569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*              l;
23755569331642446be05292e3e1f8a51218827168cdclaireho  HB_SubstLookupRecord*  slr;
23765569331642446be05292e3e1f8a51218827168cdclaireho
23775569331642446be05292e3e1f8a51218827168cdclaireho
23785569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
23795569331642446be05292e3e1f8a51218827168cdclaireho    return error;
23805569331642446be05292e3e1f8a51218827168cdclaireho
23815569331642446be05292e3e1f8a51218827168cdclaireho  cscr->BacktrackGlyphCount = GET_UShort();
23825569331642446be05292e3e1f8a51218827168cdclaireho
23835569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
23845569331642446be05292e3e1f8a51218827168cdclaireho
23855569331642446be05292e3e1f8a51218827168cdclaireho  if ( cscr->BacktrackGlyphCount > ccsf2->MaxBacktrackLength )
23865569331642446be05292e3e1f8a51218827168cdclaireho    ccsf2->MaxBacktrackLength = cscr->BacktrackGlyphCount;
23875569331642446be05292e3e1f8a51218827168cdclaireho
23885569331642446be05292e3e1f8a51218827168cdclaireho  cscr->Backtrack = NULL;
23895569331642446be05292e3e1f8a51218827168cdclaireho
23905569331642446be05292e3e1f8a51218827168cdclaireho  count = cscr->BacktrackGlyphCount;
23915569331642446be05292e3e1f8a51218827168cdclaireho
23925569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cscr->Backtrack, count, HB_UShort ) )
23935569331642446be05292e3e1f8a51218827168cdclaireho    return error;
23945569331642446be05292e3e1f8a51218827168cdclaireho
23955569331642446be05292e3e1f8a51218827168cdclaireho  b = cscr->Backtrack;
23965569331642446be05292e3e1f8a51218827168cdclaireho
23975569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
23985569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
23995569331642446be05292e3e1f8a51218827168cdclaireho
24005569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
24015569331642446be05292e3e1f8a51218827168cdclaireho    b[n] = GET_UShort();
24025569331642446be05292e3e1f8a51218827168cdclaireho
24035569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
24045569331642446be05292e3e1f8a51218827168cdclaireho
24055569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
24065569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
24075569331642446be05292e3e1f8a51218827168cdclaireho
24085569331642446be05292e3e1f8a51218827168cdclaireho  cscr->InputGlyphCount = GET_UShort();
24095569331642446be05292e3e1f8a51218827168cdclaireho
24105569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
24115569331642446be05292e3e1f8a51218827168cdclaireho
24125569331642446be05292e3e1f8a51218827168cdclaireho  if ( cscr->InputGlyphCount > ccsf2->MaxInputLength )
24135569331642446be05292e3e1f8a51218827168cdclaireho    ccsf2->MaxInputLength = cscr->InputGlyphCount;
24145569331642446be05292e3e1f8a51218827168cdclaireho
24155569331642446be05292e3e1f8a51218827168cdclaireho  cscr->Input = NULL;
24165569331642446be05292e3e1f8a51218827168cdclaireho
24175569331642446be05292e3e1f8a51218827168cdclaireho  count = cscr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
24185569331642446be05292e3e1f8a51218827168cdclaireho
24195569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cscr->Input, count, HB_UShort ) )
24205569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
24215569331642446be05292e3e1f8a51218827168cdclaireho
24225569331642446be05292e3e1f8a51218827168cdclaireho  i = cscr->Input;
24235569331642446be05292e3e1f8a51218827168cdclaireho
24245569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
24255569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
24265569331642446be05292e3e1f8a51218827168cdclaireho
24275569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
24285569331642446be05292e3e1f8a51218827168cdclaireho    i[n] = GET_UShort();
24295569331642446be05292e3e1f8a51218827168cdclaireho
24305569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
24315569331642446be05292e3e1f8a51218827168cdclaireho
24325569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
24335569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
24345569331642446be05292e3e1f8a51218827168cdclaireho
24355569331642446be05292e3e1f8a51218827168cdclaireho  cscr->LookaheadGlyphCount = GET_UShort();
24365569331642446be05292e3e1f8a51218827168cdclaireho
24375569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
24385569331642446be05292e3e1f8a51218827168cdclaireho
24395569331642446be05292e3e1f8a51218827168cdclaireho  if ( cscr->LookaheadGlyphCount > ccsf2->MaxLookaheadLength )
24405569331642446be05292e3e1f8a51218827168cdclaireho    ccsf2->MaxLookaheadLength = cscr->LookaheadGlyphCount;
24415569331642446be05292e3e1f8a51218827168cdclaireho
24425569331642446be05292e3e1f8a51218827168cdclaireho  cscr->Lookahead = NULL;
24435569331642446be05292e3e1f8a51218827168cdclaireho
24445569331642446be05292e3e1f8a51218827168cdclaireho  count = cscr->LookaheadGlyphCount;
24455569331642446be05292e3e1f8a51218827168cdclaireho
24465569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cscr->Lookahead, count, HB_UShort ) )
24475569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
24485569331642446be05292e3e1f8a51218827168cdclaireho
24495569331642446be05292e3e1f8a51218827168cdclaireho  l = cscr->Lookahead;
24505569331642446be05292e3e1f8a51218827168cdclaireho
24515569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
24525569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
24535569331642446be05292e3e1f8a51218827168cdclaireho
24545569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
24555569331642446be05292e3e1f8a51218827168cdclaireho    l[n] = GET_UShort();
24565569331642446be05292e3e1f8a51218827168cdclaireho
24575569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
24585569331642446be05292e3e1f8a51218827168cdclaireho
24595569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
24605569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
24615569331642446be05292e3e1f8a51218827168cdclaireho
24625569331642446be05292e3e1f8a51218827168cdclaireho  cscr->SubstCount = GET_UShort();
24635569331642446be05292e3e1f8a51218827168cdclaireho
24645569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
24655569331642446be05292e3e1f8a51218827168cdclaireho
24665569331642446be05292e3e1f8a51218827168cdclaireho  cscr->SubstLookupRecord = NULL;
24675569331642446be05292e3e1f8a51218827168cdclaireho
24685569331642446be05292e3e1f8a51218827168cdclaireho  count = cscr->SubstCount;
24695569331642446be05292e3e1f8a51218827168cdclaireho
24705569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cscr->SubstLookupRecord, count,
24715569331642446be05292e3e1f8a51218827168cdclaireho		    HB_SubstLookupRecord ) )
24725569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
24735569331642446be05292e3e1f8a51218827168cdclaireho
24745569331642446be05292e3e1f8a51218827168cdclaireho  slr = cscr->SubstLookupRecord;
24755569331642446be05292e3e1f8a51218827168cdclaireho
24765569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 4L ) )
24775569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail1;
24785569331642446be05292e3e1f8a51218827168cdclaireho
24795569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
24805569331642446be05292e3e1f8a51218827168cdclaireho  {
24815569331642446be05292e3e1f8a51218827168cdclaireho    slr[n].SequenceIndex   = GET_UShort();
24825569331642446be05292e3e1f8a51218827168cdclaireho    slr[n].LookupListIndex = GET_UShort();
24835569331642446be05292e3e1f8a51218827168cdclaireho  }
24845569331642446be05292e3e1f8a51218827168cdclaireho
24855569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
24865569331642446be05292e3e1f8a51218827168cdclaireho
24875569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
24885569331642446be05292e3e1f8a51218827168cdclaireho
24895569331642446be05292e3e1f8a51218827168cdclairehoFail1:
24905569331642446be05292e3e1f8a51218827168cdclaireho  FREE( slr );
24915569331642446be05292e3e1f8a51218827168cdclaireho
24925569331642446be05292e3e1f8a51218827168cdclairehoFail2:
24935569331642446be05292e3e1f8a51218827168cdclaireho  FREE( l );
24945569331642446be05292e3e1f8a51218827168cdclaireho
24955569331642446be05292e3e1f8a51218827168cdclairehoFail3:
24965569331642446be05292e3e1f8a51218827168cdclaireho  FREE( i );
24975569331642446be05292e3e1f8a51218827168cdclaireho
24985569331642446be05292e3e1f8a51218827168cdclairehoFail4:
24995569331642446be05292e3e1f8a51218827168cdclaireho  FREE( b );
25005569331642446be05292e3e1f8a51218827168cdclaireho  return error;
25015569331642446be05292e3e1f8a51218827168cdclaireho}
25025569331642446be05292e3e1f8a51218827168cdclaireho
25035569331642446be05292e3e1f8a51218827168cdclaireho
25045569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ChainSubClassRule( HB_ChainSubClassRule*  cscr )
25055569331642446be05292e3e1f8a51218827168cdclaireho{
25065569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cscr->SubstLookupRecord );
25075569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cscr->Lookahead );
25085569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cscr->Input );
25095569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cscr->Backtrack );
25105569331642446be05292e3e1f8a51218827168cdclaireho}
25115569331642446be05292e3e1f8a51218827168cdclaireho
25125569331642446be05292e3e1f8a51218827168cdclaireho
25135569331642446be05292e3e1f8a51218827168cdclaireho/* SubClassSet */
25145569331642446be05292e3e1f8a51218827168cdclaireho
25155569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ChainSubClassSet(
25165569331642446be05292e3e1f8a51218827168cdclaireho		   HB_ChainContextSubstFormat2*  ccsf2,
25175569331642446be05292e3e1f8a51218827168cdclaireho		   HB_ChainSubClassSet*          cscs,
25185569331642446be05292e3e1f8a51218827168cdclaireho		   HB_Stream                      stream )
25195569331642446be05292e3e1f8a51218827168cdclaireho{
25205569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
25215569331642446be05292e3e1f8a51218827168cdclaireho
25225569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort               n = 0, m, count;
25235569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt                cur_offset, new_offset, base_offset;
25245569331642446be05292e3e1f8a51218827168cdclaireho
25255569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainSubClassRule*  cscr;
25265569331642446be05292e3e1f8a51218827168cdclaireho
25275569331642446be05292e3e1f8a51218827168cdclaireho
25285569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
25295569331642446be05292e3e1f8a51218827168cdclaireho
25305569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
25315569331642446be05292e3e1f8a51218827168cdclaireho    return error;
25325569331642446be05292e3e1f8a51218827168cdclaireho
25335569331642446be05292e3e1f8a51218827168cdclaireho  count = cscs->ChainSubClassRuleCount = GET_UShort();
25345569331642446be05292e3e1f8a51218827168cdclaireho
25355569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
25365569331642446be05292e3e1f8a51218827168cdclaireho
25375569331642446be05292e3e1f8a51218827168cdclaireho  cscs->ChainSubClassRule = NULL;
25385569331642446be05292e3e1f8a51218827168cdclaireho
25395569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cscs->ChainSubClassRule, count,
25405569331642446be05292e3e1f8a51218827168cdclaireho		    HB_ChainSubClassRule ) )
25415569331642446be05292e3e1f8a51218827168cdclaireho    return error;
25425569331642446be05292e3e1f8a51218827168cdclaireho
25435569331642446be05292e3e1f8a51218827168cdclaireho  cscr = cscs->ChainSubClassRule;
25445569331642446be05292e3e1f8a51218827168cdclaireho
25455569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
25465569331642446be05292e3e1f8a51218827168cdclaireho  {
25475569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
25485569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
25495569331642446be05292e3e1f8a51218827168cdclaireho
25505569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
25515569331642446be05292e3e1f8a51218827168cdclaireho
25525569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
25535569331642446be05292e3e1f8a51218827168cdclaireho
25545569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
25555569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
25565569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_ChainSubClassRule( ccsf2, &cscr[n],
25575569331642446be05292e3e1f8a51218827168cdclaireho					   stream ) ) != HB_Err_Ok )
25585569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
25595569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
25605569331642446be05292e3e1f8a51218827168cdclaireho  }
25615569331642446be05292e3e1f8a51218827168cdclaireho
25625569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
25635569331642446be05292e3e1f8a51218827168cdclaireho
25645569331642446be05292e3e1f8a51218827168cdclairehoFail:
25655569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
25665569331642446be05292e3e1f8a51218827168cdclaireho    Free_ChainSubClassRule( &cscr[m] );
25675569331642446be05292e3e1f8a51218827168cdclaireho
25685569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cscr );
25695569331642446be05292e3e1f8a51218827168cdclaireho  return error;
25705569331642446be05292e3e1f8a51218827168cdclaireho}
25715569331642446be05292e3e1f8a51218827168cdclaireho
25725569331642446be05292e3e1f8a51218827168cdclaireho
25735569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ChainSubClassSet( HB_ChainSubClassSet*  cscs )
25745569331642446be05292e3e1f8a51218827168cdclaireho{
25755569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort               n, count;
25765569331642446be05292e3e1f8a51218827168cdclaireho
25775569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainSubClassRule*  cscr;
25785569331642446be05292e3e1f8a51218827168cdclaireho
25795569331642446be05292e3e1f8a51218827168cdclaireho
25805569331642446be05292e3e1f8a51218827168cdclaireho  if ( cscs->ChainSubClassRule )
25815569331642446be05292e3e1f8a51218827168cdclaireho  {
25825569331642446be05292e3e1f8a51218827168cdclaireho    count = cscs->ChainSubClassRuleCount;
25835569331642446be05292e3e1f8a51218827168cdclaireho    cscr  = cscs->ChainSubClassRule;
25845569331642446be05292e3e1f8a51218827168cdclaireho
25855569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
25865569331642446be05292e3e1f8a51218827168cdclaireho      Free_ChainSubClassRule( &cscr[n] );
25875569331642446be05292e3e1f8a51218827168cdclaireho
25885569331642446be05292e3e1f8a51218827168cdclaireho    FREE( cscr );
25895569331642446be05292e3e1f8a51218827168cdclaireho  }
25905569331642446be05292e3e1f8a51218827168cdclaireho}
25915569331642446be05292e3e1f8a51218827168cdclaireho
25925569331642446be05292e3e1f8a51218827168cdclaireho
25935569331642446be05292e3e1f8a51218827168cdclaireho/* ChainContextSubstFormat2 */
25945569331642446be05292e3e1f8a51218827168cdclaireho
25955569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ChainContextSubst2(
25965569331642446be05292e3e1f8a51218827168cdclaireho		   HB_ChainContextSubstFormat2*  ccsf2,
25975569331642446be05292e3e1f8a51218827168cdclaireho		   HB_Stream                      stream )
25985569331642446be05292e3e1f8a51218827168cdclaireho{
25995569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
26005569331642446be05292e3e1f8a51218827168cdclaireho
26015569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort              n = 0, m, count;
26025569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt               cur_offset, new_offset, base_offset;
26035569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt               backtrack_offset, input_offset, lookahead_offset;
26045569331642446be05292e3e1f8a51218827168cdclaireho
26055569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainSubClassSet*  cscs;
26065569331642446be05292e3e1f8a51218827168cdclaireho
26075569331642446be05292e3e1f8a51218827168cdclaireho
26085569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos() - 2;
26095569331642446be05292e3e1f8a51218827168cdclaireho
26105569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
26115569331642446be05292e3e1f8a51218827168cdclaireho    return error;
26125569331642446be05292e3e1f8a51218827168cdclaireho
26135569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
26145569331642446be05292e3e1f8a51218827168cdclaireho
26155569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
26165569331642446be05292e3e1f8a51218827168cdclaireho
26175569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
26185569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
26195569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_Coverage( &ccsf2->Coverage, stream ) ) != HB_Err_Ok )
26205569331642446be05292e3e1f8a51218827168cdclaireho    return error;
26215569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
26225569331642446be05292e3e1f8a51218827168cdclaireho
26235569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 8L ) )
26245569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail5;
26255569331642446be05292e3e1f8a51218827168cdclaireho
26265569331642446be05292e3e1f8a51218827168cdclaireho  backtrack_offset = GET_UShort();
26275569331642446be05292e3e1f8a51218827168cdclaireho  input_offset     = GET_UShort();
26285569331642446be05292e3e1f8a51218827168cdclaireho  lookahead_offset = GET_UShort();
26295569331642446be05292e3e1f8a51218827168cdclaireho
26305569331642446be05292e3e1f8a51218827168cdclaireho  /* `ChainSubClassSetCount' is the upper limit for input class values,
26315569331642446be05292e3e1f8a51218827168cdclaireho     thus we read it now to make an additional safety check. No limit
26325569331642446be05292e3e1f8a51218827168cdclaireho     is known or needed for the other two class definitions          */
26335569331642446be05292e3e1f8a51218827168cdclaireho
26345569331642446be05292e3e1f8a51218827168cdclaireho  count = ccsf2->ChainSubClassSetCount = GET_UShort();
26355569331642446be05292e3e1f8a51218827168cdclaireho
26365569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
26375569331642446be05292e3e1f8a51218827168cdclaireho
26385569331642446be05292e3e1f8a51218827168cdclaireho  if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->BacktrackClassDef, 65535,
26395569331642446be05292e3e1f8a51218827168cdclaireho						       backtrack_offset, base_offset,
26405569331642446be05292e3e1f8a51218827168cdclaireho						       stream ) ) != HB_Err_Ok )
26415569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail5;
26425569331642446be05292e3e1f8a51218827168cdclaireho
26435569331642446be05292e3e1f8a51218827168cdclaireho  if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->InputClassDef, count,
26445569331642446be05292e3e1f8a51218827168cdclaireho						       input_offset, base_offset,
26455569331642446be05292e3e1f8a51218827168cdclaireho						       stream ) ) != HB_Err_Ok )
26465569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail4;
26475569331642446be05292e3e1f8a51218827168cdclaireho  if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->LookaheadClassDef, 65535,
26485569331642446be05292e3e1f8a51218827168cdclaireho						       lookahead_offset, base_offset,
26495569331642446be05292e3e1f8a51218827168cdclaireho						       stream ) ) != HB_Err_Ok )
26505569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
26515569331642446be05292e3e1f8a51218827168cdclaireho
26525569331642446be05292e3e1f8a51218827168cdclaireho  ccsf2->ChainSubClassSet   = NULL;
26535569331642446be05292e3e1f8a51218827168cdclaireho  ccsf2->MaxBacktrackLength = 0;
26545569331642446be05292e3e1f8a51218827168cdclaireho  ccsf2->MaxInputLength     = 0;
26555569331642446be05292e3e1f8a51218827168cdclaireho  ccsf2->MaxLookaheadLength = 0;
26565569331642446be05292e3e1f8a51218827168cdclaireho
26575569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ccsf2->ChainSubClassSet, count, HB_ChainSubClassSet ) )
26585569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
26595569331642446be05292e3e1f8a51218827168cdclaireho
26605569331642446be05292e3e1f8a51218827168cdclaireho  cscs = ccsf2->ChainSubClassSet;
26615569331642446be05292e3e1f8a51218827168cdclaireho
26625569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
26635569331642446be05292e3e1f8a51218827168cdclaireho  {
26645569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
26655569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
26665569331642446be05292e3e1f8a51218827168cdclaireho
26675569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
26685569331642446be05292e3e1f8a51218827168cdclaireho
26695569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
26705569331642446be05292e3e1f8a51218827168cdclaireho
26715569331642446be05292e3e1f8a51218827168cdclaireho    if ( new_offset != base_offset )      /* not a NULL offset */
26725569331642446be05292e3e1f8a51218827168cdclaireho    {
26735569331642446be05292e3e1f8a51218827168cdclaireho      cur_offset = FILE_Pos();
26745569331642446be05292e3e1f8a51218827168cdclaireho      if ( FILE_Seek( new_offset ) ||
26755569331642446be05292e3e1f8a51218827168cdclaireho	   ( error = Load_ChainSubClassSet( ccsf2, &cscs[n],
26765569331642446be05292e3e1f8a51218827168cdclaireho					    stream ) ) != HB_Err_Ok )
26775569331642446be05292e3e1f8a51218827168cdclaireho	goto Fail1;
26785569331642446be05292e3e1f8a51218827168cdclaireho      (void)FILE_Seek( cur_offset );
26795569331642446be05292e3e1f8a51218827168cdclaireho    }
26805569331642446be05292e3e1f8a51218827168cdclaireho    else
26815569331642446be05292e3e1f8a51218827168cdclaireho    {
26825569331642446be05292e3e1f8a51218827168cdclaireho      /* we create a ChainSubClassSet table with no entries */
26835569331642446be05292e3e1f8a51218827168cdclaireho
26845569331642446be05292e3e1f8a51218827168cdclaireho      ccsf2->ChainSubClassSet[n].ChainSubClassRuleCount = 0;
26855569331642446be05292e3e1f8a51218827168cdclaireho      ccsf2->ChainSubClassSet[n].ChainSubClassRule      = NULL;
26865569331642446be05292e3e1f8a51218827168cdclaireho    }
26875569331642446be05292e3e1f8a51218827168cdclaireho  }
26885569331642446be05292e3e1f8a51218827168cdclaireho
26895569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
26905569331642446be05292e3e1f8a51218827168cdclaireho
26915569331642446be05292e3e1f8a51218827168cdclairehoFail1:
26925569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
26935569331642446be05292e3e1f8a51218827168cdclaireho    Free_ChainSubClassSet( &cscs[m] );
26945569331642446be05292e3e1f8a51218827168cdclaireho
26955569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cscs );
26965569331642446be05292e3e1f8a51218827168cdclaireho
26975569331642446be05292e3e1f8a51218827168cdclairehoFail2:
26985569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_ClassDefinition( &ccsf2->LookaheadClassDef );
26995569331642446be05292e3e1f8a51218827168cdclaireho
27005569331642446be05292e3e1f8a51218827168cdclairehoFail3:
27015569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_ClassDefinition( &ccsf2->InputClassDef );
27025569331642446be05292e3e1f8a51218827168cdclaireho
27035569331642446be05292e3e1f8a51218827168cdclairehoFail4:
27045569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_ClassDefinition( &ccsf2->BacktrackClassDef );
27055569331642446be05292e3e1f8a51218827168cdclaireho
27065569331642446be05292e3e1f8a51218827168cdclairehoFail5:
27075569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &ccsf2->Coverage );
27085569331642446be05292e3e1f8a51218827168cdclaireho  return error;
27095569331642446be05292e3e1f8a51218827168cdclaireho}
27105569331642446be05292e3e1f8a51218827168cdclaireho
27115569331642446be05292e3e1f8a51218827168cdclaireho
27125569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ChainContextSubst2( HB_ChainContextSubstFormat2*  ccsf2 )
27135569331642446be05292e3e1f8a51218827168cdclaireho{
27145569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort              n, count;
27155569331642446be05292e3e1f8a51218827168cdclaireho
27165569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainSubClassSet*  cscs;
27175569331642446be05292e3e1f8a51218827168cdclaireho
27185569331642446be05292e3e1f8a51218827168cdclaireho
27195569331642446be05292e3e1f8a51218827168cdclaireho  if ( ccsf2->ChainSubClassSet )
27205569331642446be05292e3e1f8a51218827168cdclaireho  {
27215569331642446be05292e3e1f8a51218827168cdclaireho    count = ccsf2->ChainSubClassSetCount;
27225569331642446be05292e3e1f8a51218827168cdclaireho    cscs  = ccsf2->ChainSubClassSet;
27235569331642446be05292e3e1f8a51218827168cdclaireho
27245569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
27255569331642446be05292e3e1f8a51218827168cdclaireho      Free_ChainSubClassSet( &cscs[n] );
27265569331642446be05292e3e1f8a51218827168cdclaireho
27275569331642446be05292e3e1f8a51218827168cdclaireho    FREE( cscs );
27285569331642446be05292e3e1f8a51218827168cdclaireho  }
27295569331642446be05292e3e1f8a51218827168cdclaireho
27305569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_ClassDefinition( &ccsf2->LookaheadClassDef );
27315569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_ClassDefinition( &ccsf2->InputClassDef );
27325569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_ClassDefinition( &ccsf2->BacktrackClassDef );
27335569331642446be05292e3e1f8a51218827168cdclaireho
27345569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &ccsf2->Coverage );
27355569331642446be05292e3e1f8a51218827168cdclaireho}
27365569331642446be05292e3e1f8a51218827168cdclaireho
27375569331642446be05292e3e1f8a51218827168cdclaireho
27385569331642446be05292e3e1f8a51218827168cdclaireho/* ChainContextSubstFormat3 */
27395569331642446be05292e3e1f8a51218827168cdclaireho
27405569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ChainContextSubst3(
27415569331642446be05292e3e1f8a51218827168cdclaireho		   HB_ChainContextSubstFormat3*  ccsf3,
27425569331642446be05292e3e1f8a51218827168cdclaireho		   HB_Stream                      stream )
27435569331642446be05292e3e1f8a51218827168cdclaireho{
27445569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
27455569331642446be05292e3e1f8a51218827168cdclaireho
27465569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort               n, nb = 0, ni =0, nl = 0, m, count;
27475569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort               backtrack_count, input_count, lookahead_count;
27485569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt                cur_offset, new_offset, base_offset;
27495569331642446be05292e3e1f8a51218827168cdclaireho
27505569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*           b;
27515569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*           i;
27525569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*           l;
27535569331642446be05292e3e1f8a51218827168cdclaireho  HB_SubstLookupRecord*  slr;
27545569331642446be05292e3e1f8a51218827168cdclaireho
27555569331642446be05292e3e1f8a51218827168cdclaireho
27565569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos() - 2L;
27575569331642446be05292e3e1f8a51218827168cdclaireho
27585569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
27595569331642446be05292e3e1f8a51218827168cdclaireho    return error;
27605569331642446be05292e3e1f8a51218827168cdclaireho
27615569331642446be05292e3e1f8a51218827168cdclaireho  ccsf3->BacktrackGlyphCount = GET_UShort();
27625569331642446be05292e3e1f8a51218827168cdclaireho
27635569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
27645569331642446be05292e3e1f8a51218827168cdclaireho
27655569331642446be05292e3e1f8a51218827168cdclaireho  ccsf3->BacktrackCoverage = NULL;
27665569331642446be05292e3e1f8a51218827168cdclaireho
27675569331642446be05292e3e1f8a51218827168cdclaireho  backtrack_count = ccsf3->BacktrackGlyphCount;
27685569331642446be05292e3e1f8a51218827168cdclaireho
27695569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ccsf3->BacktrackCoverage, backtrack_count,
27705569331642446be05292e3e1f8a51218827168cdclaireho		    HB_Coverage ) )
27715569331642446be05292e3e1f8a51218827168cdclaireho    return error;
27725569331642446be05292e3e1f8a51218827168cdclaireho
27735569331642446be05292e3e1f8a51218827168cdclaireho  b = ccsf3->BacktrackCoverage;
27745569331642446be05292e3e1f8a51218827168cdclaireho
27755569331642446be05292e3e1f8a51218827168cdclaireho  for ( nb = 0; nb < backtrack_count; nb++ )
27765569331642446be05292e3e1f8a51218827168cdclaireho  {
27775569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
27785569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail4;
27795569331642446be05292e3e1f8a51218827168cdclaireho
27805569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
27815569331642446be05292e3e1f8a51218827168cdclaireho
27825569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
27835569331642446be05292e3e1f8a51218827168cdclaireho
27845569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
27855569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
27865569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != HB_Err_Ok )
27875569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail4;
27885569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
27895569331642446be05292e3e1f8a51218827168cdclaireho  }
27905569331642446be05292e3e1f8a51218827168cdclaireho
27915569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
27925569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
27935569331642446be05292e3e1f8a51218827168cdclaireho
27945569331642446be05292e3e1f8a51218827168cdclaireho  ccsf3->InputGlyphCount = GET_UShort();
27955569331642446be05292e3e1f8a51218827168cdclaireho
27965569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
27975569331642446be05292e3e1f8a51218827168cdclaireho
27985569331642446be05292e3e1f8a51218827168cdclaireho  ccsf3->InputCoverage = NULL;
27995569331642446be05292e3e1f8a51218827168cdclaireho
28005569331642446be05292e3e1f8a51218827168cdclaireho  input_count = ccsf3->InputGlyphCount;
28015569331642446be05292e3e1f8a51218827168cdclaireho
28025569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ccsf3->InputCoverage, input_count, HB_Coverage ) )
28035569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
28045569331642446be05292e3e1f8a51218827168cdclaireho
28055569331642446be05292e3e1f8a51218827168cdclaireho  i = ccsf3->InputCoverage;
28065569331642446be05292e3e1f8a51218827168cdclaireho
28075569331642446be05292e3e1f8a51218827168cdclaireho  for ( ni = 0; ni < input_count; ni++ )
28085569331642446be05292e3e1f8a51218827168cdclaireho  {
28095569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
28105569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail3;
28115569331642446be05292e3e1f8a51218827168cdclaireho
28125569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
28135569331642446be05292e3e1f8a51218827168cdclaireho
28145569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
28155569331642446be05292e3e1f8a51218827168cdclaireho
28165569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
28175569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
28185569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = _HB_OPEN_Load_Coverage( &i[ni], stream ) ) != HB_Err_Ok )
28195569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail3;
28205569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
28215569331642446be05292e3e1f8a51218827168cdclaireho  }
28225569331642446be05292e3e1f8a51218827168cdclaireho
28235569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
28245569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
28255569331642446be05292e3e1f8a51218827168cdclaireho
28265569331642446be05292e3e1f8a51218827168cdclaireho  ccsf3->LookaheadGlyphCount = GET_UShort();
28275569331642446be05292e3e1f8a51218827168cdclaireho
28285569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
28295569331642446be05292e3e1f8a51218827168cdclaireho
28305569331642446be05292e3e1f8a51218827168cdclaireho  ccsf3->LookaheadCoverage = NULL;
28315569331642446be05292e3e1f8a51218827168cdclaireho
28325569331642446be05292e3e1f8a51218827168cdclaireho  lookahead_count = ccsf3->LookaheadGlyphCount;
28335569331642446be05292e3e1f8a51218827168cdclaireho
28345569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ccsf3->LookaheadCoverage, lookahead_count,
28355569331642446be05292e3e1f8a51218827168cdclaireho		    HB_Coverage ) )
28365569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
28375569331642446be05292e3e1f8a51218827168cdclaireho
28385569331642446be05292e3e1f8a51218827168cdclaireho  l = ccsf3->LookaheadCoverage;
28395569331642446be05292e3e1f8a51218827168cdclaireho
28405569331642446be05292e3e1f8a51218827168cdclaireho  for ( nl = 0; nl < lookahead_count; nl++ )
28415569331642446be05292e3e1f8a51218827168cdclaireho  {
28425569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
28435569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail2;
28445569331642446be05292e3e1f8a51218827168cdclaireho
28455569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
28465569331642446be05292e3e1f8a51218827168cdclaireho
28475569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
28485569331642446be05292e3e1f8a51218827168cdclaireho
28495569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
28505569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
28515569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != HB_Err_Ok )
28525569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail2;
28535569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
28545569331642446be05292e3e1f8a51218827168cdclaireho  }
28555569331642446be05292e3e1f8a51218827168cdclaireho
28565569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
28575569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
28585569331642446be05292e3e1f8a51218827168cdclaireho
28595569331642446be05292e3e1f8a51218827168cdclaireho  ccsf3->SubstCount = GET_UShort();
28605569331642446be05292e3e1f8a51218827168cdclaireho
28615569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
28625569331642446be05292e3e1f8a51218827168cdclaireho
28635569331642446be05292e3e1f8a51218827168cdclaireho  ccsf3->SubstLookupRecord = NULL;
28645569331642446be05292e3e1f8a51218827168cdclaireho
28655569331642446be05292e3e1f8a51218827168cdclaireho  count = ccsf3->SubstCount;
28665569331642446be05292e3e1f8a51218827168cdclaireho
28675569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ccsf3->SubstLookupRecord, count,
28685569331642446be05292e3e1f8a51218827168cdclaireho		    HB_SubstLookupRecord ) )
28695569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
28705569331642446be05292e3e1f8a51218827168cdclaireho
28715569331642446be05292e3e1f8a51218827168cdclaireho  slr = ccsf3->SubstLookupRecord;
28725569331642446be05292e3e1f8a51218827168cdclaireho
28735569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 4L ) )
28745569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail1;
28755569331642446be05292e3e1f8a51218827168cdclaireho
28765569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
28775569331642446be05292e3e1f8a51218827168cdclaireho  {
28785569331642446be05292e3e1f8a51218827168cdclaireho    slr[n].SequenceIndex   = GET_UShort();
28795569331642446be05292e3e1f8a51218827168cdclaireho    slr[n].LookupListIndex = GET_UShort();
28805569331642446be05292e3e1f8a51218827168cdclaireho  }
28815569331642446be05292e3e1f8a51218827168cdclaireho
28825569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
28835569331642446be05292e3e1f8a51218827168cdclaireho
28845569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
28855569331642446be05292e3e1f8a51218827168cdclaireho
28865569331642446be05292e3e1f8a51218827168cdclairehoFail1:
28875569331642446be05292e3e1f8a51218827168cdclaireho  FREE( slr );
28885569331642446be05292e3e1f8a51218827168cdclaireho
28895569331642446be05292e3e1f8a51218827168cdclairehoFail2:
28905569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < nl; m++ )
28915569331642446be05292e3e1f8a51218827168cdclaireho    _HB_OPEN_Free_Coverage( &l[m] );
28925569331642446be05292e3e1f8a51218827168cdclaireho
28935569331642446be05292e3e1f8a51218827168cdclaireho  FREE( l );
28945569331642446be05292e3e1f8a51218827168cdclaireho
28955569331642446be05292e3e1f8a51218827168cdclairehoFail3:
28965569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < ni; m++ )
28975569331642446be05292e3e1f8a51218827168cdclaireho    _HB_OPEN_Free_Coverage( &i[m] );
28985569331642446be05292e3e1f8a51218827168cdclaireho
28995569331642446be05292e3e1f8a51218827168cdclaireho  FREE( i );
29005569331642446be05292e3e1f8a51218827168cdclaireho
29015569331642446be05292e3e1f8a51218827168cdclairehoFail4:
29025569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < nb; m++ )
29035569331642446be05292e3e1f8a51218827168cdclaireho    _HB_OPEN_Free_Coverage( &b[m] );
29045569331642446be05292e3e1f8a51218827168cdclaireho
29055569331642446be05292e3e1f8a51218827168cdclaireho  FREE( b );
29065569331642446be05292e3e1f8a51218827168cdclaireho  return error;
29075569331642446be05292e3e1f8a51218827168cdclaireho}
29085569331642446be05292e3e1f8a51218827168cdclaireho
29095569331642446be05292e3e1f8a51218827168cdclaireho
29105569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ChainContextSubst3( HB_ChainContextSubstFormat3*  ccsf3 )
29115569331642446be05292e3e1f8a51218827168cdclaireho{
29125569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort      n, count;
29135569331642446be05292e3e1f8a51218827168cdclaireho
29145569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*  c;
29155569331642446be05292e3e1f8a51218827168cdclaireho
29165569331642446be05292e3e1f8a51218827168cdclaireho
29175569331642446be05292e3e1f8a51218827168cdclaireho  FREE( ccsf3->SubstLookupRecord );
29185569331642446be05292e3e1f8a51218827168cdclaireho
29195569331642446be05292e3e1f8a51218827168cdclaireho  if ( ccsf3->LookaheadCoverage )
29205569331642446be05292e3e1f8a51218827168cdclaireho  {
29215569331642446be05292e3e1f8a51218827168cdclaireho    count = ccsf3->LookaheadGlyphCount;
29225569331642446be05292e3e1f8a51218827168cdclaireho    c     = ccsf3->LookaheadCoverage;
29235569331642446be05292e3e1f8a51218827168cdclaireho
29245569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
29255569331642446be05292e3e1f8a51218827168cdclaireho      _HB_OPEN_Free_Coverage( &c[n] );
29265569331642446be05292e3e1f8a51218827168cdclaireho
29275569331642446be05292e3e1f8a51218827168cdclaireho    FREE( c );
29285569331642446be05292e3e1f8a51218827168cdclaireho  }
29295569331642446be05292e3e1f8a51218827168cdclaireho
29305569331642446be05292e3e1f8a51218827168cdclaireho  if ( ccsf3->InputCoverage )
29315569331642446be05292e3e1f8a51218827168cdclaireho  {
29325569331642446be05292e3e1f8a51218827168cdclaireho    count = ccsf3->InputGlyphCount;
29335569331642446be05292e3e1f8a51218827168cdclaireho    c     = ccsf3->InputCoverage;
29345569331642446be05292e3e1f8a51218827168cdclaireho
29355569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
29365569331642446be05292e3e1f8a51218827168cdclaireho      _HB_OPEN_Free_Coverage( &c[n] );
29375569331642446be05292e3e1f8a51218827168cdclaireho
29385569331642446be05292e3e1f8a51218827168cdclaireho    FREE( c );
29395569331642446be05292e3e1f8a51218827168cdclaireho  }
29405569331642446be05292e3e1f8a51218827168cdclaireho
29415569331642446be05292e3e1f8a51218827168cdclaireho  if ( ccsf3->BacktrackCoverage )
29425569331642446be05292e3e1f8a51218827168cdclaireho  {
29435569331642446be05292e3e1f8a51218827168cdclaireho    count = ccsf3->BacktrackGlyphCount;
29445569331642446be05292e3e1f8a51218827168cdclaireho    c     = ccsf3->BacktrackCoverage;
29455569331642446be05292e3e1f8a51218827168cdclaireho
29465569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
29475569331642446be05292e3e1f8a51218827168cdclaireho      _HB_OPEN_Free_Coverage( &c[n] );
29485569331642446be05292e3e1f8a51218827168cdclaireho
29495569331642446be05292e3e1f8a51218827168cdclaireho    FREE( c );
29505569331642446be05292e3e1f8a51218827168cdclaireho  }
29515569331642446be05292e3e1f8a51218827168cdclaireho}
29525569331642446be05292e3e1f8a51218827168cdclaireho
29535569331642446be05292e3e1f8a51218827168cdclaireho
29545569331642446be05292e3e1f8a51218827168cdclaireho/* ChainContextSubst */
29555569331642446be05292e3e1f8a51218827168cdclaireho
29565569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ChainContextSubst( HB_GSUB_SubTable* st,
29575569331642446be05292e3e1f8a51218827168cdclaireho					 HB_Stream         stream )
29585569331642446be05292e3e1f8a51218827168cdclaireho{
29595569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
29605569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainContextSubst*  ccs = &st->chain;
29615569331642446be05292e3e1f8a51218827168cdclaireho
29625569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
29635569331642446be05292e3e1f8a51218827168cdclaireho    return error;
29645569331642446be05292e3e1f8a51218827168cdclaireho
29655569331642446be05292e3e1f8a51218827168cdclaireho  ccs->SubstFormat = GET_UShort();
29665569331642446be05292e3e1f8a51218827168cdclaireho
29675569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
29685569331642446be05292e3e1f8a51218827168cdclaireho
29695569331642446be05292e3e1f8a51218827168cdclaireho  switch ( ccs->SubstFormat ) {
29705569331642446be05292e3e1f8a51218827168cdclaireho    case 1:  return Load_ChainContextSubst1( &ccs->ccsf.ccsf1, stream );
29715569331642446be05292e3e1f8a51218827168cdclaireho    case 2:  return Load_ChainContextSubst2( &ccs->ccsf.ccsf2, stream );
29725569331642446be05292e3e1f8a51218827168cdclaireho    case 3:  return Load_ChainContextSubst3( &ccs->ccsf.ccsf3, stream );
29735569331642446be05292e3e1f8a51218827168cdclaireho    default: return ERR(HB_Err_Invalid_SubTable_Format);
29745569331642446be05292e3e1f8a51218827168cdclaireho  }
29755569331642446be05292e3e1f8a51218827168cdclaireho
29765569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;               /* never reached */
29775569331642446be05292e3e1f8a51218827168cdclaireho}
29785569331642446be05292e3e1f8a51218827168cdclaireho
29795569331642446be05292e3e1f8a51218827168cdclaireho
29805569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ChainContextSubst( HB_GSUB_SubTable* st )
29815569331642446be05292e3e1f8a51218827168cdclaireho{
29825569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainContextSubst*  ccs = &st->chain;
29835569331642446be05292e3e1f8a51218827168cdclaireho
29845569331642446be05292e3e1f8a51218827168cdclaireho  switch ( ccs->SubstFormat ) {
29855569331642446be05292e3e1f8a51218827168cdclaireho    case 1:  Free_ChainContextSubst1( &ccs->ccsf.ccsf1 ); break;
29865569331642446be05292e3e1f8a51218827168cdclaireho    case 2:  Free_ChainContextSubst2( &ccs->ccsf.ccsf2 ); break;
29875569331642446be05292e3e1f8a51218827168cdclaireho    case 3:  Free_ChainContextSubst3( &ccs->ccsf.ccsf3 ); break;
29885569331642446be05292e3e1f8a51218827168cdclaireho    default:							  break;
29895569331642446be05292e3e1f8a51218827168cdclaireho  }
29905569331642446be05292e3e1f8a51218827168cdclaireho}
29915569331642446be05292e3e1f8a51218827168cdclaireho
29925569331642446be05292e3e1f8a51218827168cdclaireho
29935569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_ChainContextSubst1( HB_GSUBHeader*               gsub,
29945569331642446be05292e3e1f8a51218827168cdclaireho					    HB_ChainContextSubstFormat1* ccsf1,
29955569331642446be05292e3e1f8a51218827168cdclaireho					    HB_Buffer                    buffer,
29965569331642446be05292e3e1f8a51218827168cdclaireho					    HB_UShort                     flags,
29975569331642446be05292e3e1f8a51218827168cdclaireho					    HB_UShort                     context_length,
29985569331642446be05292e3e1f8a51218827168cdclaireho					    int                           nesting_level )
29995569331642446be05292e3e1f8a51218827168cdclaireho{
30005569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          index, property;
30015569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          i, j, k, num_csr;
30025569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          bgc, igc, lgc;
30035569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error           error;
30045569331642446be05292e3e1f8a51218827168cdclaireho
30055569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainSubRule*  csr;
30065569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainSubRule   curr_csr;
30075569331642446be05292e3e1f8a51218827168cdclaireho  HB_GDEFHeader*    gdef;
30085569331642446be05292e3e1f8a51218827168cdclaireho
30095569331642446be05292e3e1f8a51218827168cdclaireho
30105569331642446be05292e3e1f8a51218827168cdclaireho  gdef = gsub->gdef;
30115569331642446be05292e3e1f8a51218827168cdclaireho
30125569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
30135569331642446be05292e3e1f8a51218827168cdclaireho    return error;
30145569331642446be05292e3e1f8a51218827168cdclaireho
30155569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Coverage_Index( &ccsf1->Coverage, IN_CURGLYPH(), &index );
30165569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
30175569331642446be05292e3e1f8a51218827168cdclaireho    return error;
30185569331642446be05292e3e1f8a51218827168cdclaireho
30195569331642446be05292e3e1f8a51218827168cdclaireho  csr     = ccsf1->ChainSubRuleSet[index].ChainSubRule;
30205569331642446be05292e3e1f8a51218827168cdclaireho  num_csr = ccsf1->ChainSubRuleSet[index].ChainSubRuleCount;
30215569331642446be05292e3e1f8a51218827168cdclaireho
30225569331642446be05292e3e1f8a51218827168cdclaireho  for ( k = 0; k < num_csr; k++ )
30235569331642446be05292e3e1f8a51218827168cdclaireho  {
30245569331642446be05292e3e1f8a51218827168cdclaireho    curr_csr = csr[k];
30255569331642446be05292e3e1f8a51218827168cdclaireho    bgc      = curr_csr.BacktrackGlyphCount;
30265569331642446be05292e3e1f8a51218827168cdclaireho    igc      = curr_csr.InputGlyphCount;
30275569331642446be05292e3e1f8a51218827168cdclaireho    lgc      = curr_csr.LookaheadGlyphCount;
30285569331642446be05292e3e1f8a51218827168cdclaireho
30295569331642446be05292e3e1f8a51218827168cdclaireho    if ( context_length != 0xFFFF && context_length < igc )
30305569331642446be05292e3e1f8a51218827168cdclaireho      goto next_chainsubrule;
30315569331642446be05292e3e1f8a51218827168cdclaireho
30325569331642446be05292e3e1f8a51218827168cdclaireho    /* check whether context is too long; it is a first guess only */
30335569331642446be05292e3e1f8a51218827168cdclaireho
30345569331642446be05292e3e1f8a51218827168cdclaireho    if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length )
30355569331642446be05292e3e1f8a51218827168cdclaireho      goto next_chainsubrule;
30365569331642446be05292e3e1f8a51218827168cdclaireho
30375569331642446be05292e3e1f8a51218827168cdclaireho    if ( bgc )
30385569331642446be05292e3e1f8a51218827168cdclaireho    {
30395569331642446be05292e3e1f8a51218827168cdclaireho      /* since we don't know in advance the number of glyphs to inspect,
30405569331642446be05292e3e1f8a51218827168cdclaireho	 we search backwards for matches in the backtrack glyph array    */
30415569331642446be05292e3e1f8a51218827168cdclaireho
30425569331642446be05292e3e1f8a51218827168cdclaireho      for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
30435569331642446be05292e3e1f8a51218827168cdclaireho      {
30445569331642446be05292e3e1f8a51218827168cdclaireho	while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )
30455569331642446be05292e3e1f8a51218827168cdclaireho	{
30465569331642446be05292e3e1f8a51218827168cdclaireho	  if ( error && error != HB_Err_Not_Covered )
30475569331642446be05292e3e1f8a51218827168cdclaireho	    return error;
30485569331642446be05292e3e1f8a51218827168cdclaireho
30495569331642446be05292e3e1f8a51218827168cdclaireho	  if ( j + 1 == bgc - i )
30505569331642446be05292e3e1f8a51218827168cdclaireho	    goto next_chainsubrule;
30515569331642446be05292e3e1f8a51218827168cdclaireho	  j--;
30525569331642446be05292e3e1f8a51218827168cdclaireho	}
30535569331642446be05292e3e1f8a51218827168cdclaireho
30545569331642446be05292e3e1f8a51218827168cdclaireho	/* In OpenType 1.3, it is undefined whether the offsets of
30555569331642446be05292e3e1f8a51218827168cdclaireho	   backtrack glyphs is in logical order or not.  Version 1.4
30565569331642446be05292e3e1f8a51218827168cdclaireho	   will clarify this:
30575569331642446be05292e3e1f8a51218827168cdclaireho
30585569331642446be05292e3e1f8a51218827168cdclaireho	     Logical order -      a  b  c  d  e  f  g  h  i  j
30595569331642446be05292e3e1f8a51218827168cdclaireho					      i
30605569331642446be05292e3e1f8a51218827168cdclaireho	     Input offsets -                  0  1
30615569331642446be05292e3e1f8a51218827168cdclaireho	     Backtrack offsets -  3  2  1  0
30625569331642446be05292e3e1f8a51218827168cdclaireho	     Lookahead offsets -                    0  1  2  3           */
30635569331642446be05292e3e1f8a51218827168cdclaireho
30645569331642446be05292e3e1f8a51218827168cdclaireho	if ( OUT_GLYPH( j ) != curr_csr.Backtrack[i] )
30655569331642446be05292e3e1f8a51218827168cdclaireho	  goto next_chainsubrule;
30665569331642446be05292e3e1f8a51218827168cdclaireho      }
30675569331642446be05292e3e1f8a51218827168cdclaireho    }
30685569331642446be05292e3e1f8a51218827168cdclaireho
30695569331642446be05292e3e1f8a51218827168cdclaireho    /* Start at 1 because [0] is implied */
30705569331642446be05292e3e1f8a51218827168cdclaireho
30715569331642446be05292e3e1f8a51218827168cdclaireho    for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
30725569331642446be05292e3e1f8a51218827168cdclaireho    {
30735569331642446be05292e3e1f8a51218827168cdclaireho      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
30745569331642446be05292e3e1f8a51218827168cdclaireho      {
30755569331642446be05292e3e1f8a51218827168cdclaireho	if ( error && error != HB_Err_Not_Covered )
30765569331642446be05292e3e1f8a51218827168cdclaireho	  return error;
30775569331642446be05292e3e1f8a51218827168cdclaireho
30785569331642446be05292e3e1f8a51218827168cdclaireho	if ( j + igc - i + lgc == (HB_Int)buffer->in_length )
30795569331642446be05292e3e1f8a51218827168cdclaireho	  goto next_chainsubrule;
30805569331642446be05292e3e1f8a51218827168cdclaireho	j++;
30815569331642446be05292e3e1f8a51218827168cdclaireho      }
30825569331642446be05292e3e1f8a51218827168cdclaireho
30835569331642446be05292e3e1f8a51218827168cdclaireho      if ( IN_GLYPH( j ) != curr_csr.Input[i - 1] )
30845569331642446be05292e3e1f8a51218827168cdclaireho	  goto next_chainsubrule;
30855569331642446be05292e3e1f8a51218827168cdclaireho    }
30865569331642446be05292e3e1f8a51218827168cdclaireho
30875569331642446be05292e3e1f8a51218827168cdclaireho    /* we are starting to check for lookahead glyphs right after the
30885569331642446be05292e3e1f8a51218827168cdclaireho       last context glyph                                            */
30895569331642446be05292e3e1f8a51218827168cdclaireho
30905569331642446be05292e3e1f8a51218827168cdclaireho    for ( i = 0; i < lgc; i++, j++ )
30915569331642446be05292e3e1f8a51218827168cdclaireho    {
30925569331642446be05292e3e1f8a51218827168cdclaireho      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
30935569331642446be05292e3e1f8a51218827168cdclaireho      {
30945569331642446be05292e3e1f8a51218827168cdclaireho	if ( error && error != HB_Err_Not_Covered )
30955569331642446be05292e3e1f8a51218827168cdclaireho	  return error;
30965569331642446be05292e3e1f8a51218827168cdclaireho
30975569331642446be05292e3e1f8a51218827168cdclaireho	if ( j + lgc - i == (HB_Int)buffer->in_length )
30985569331642446be05292e3e1f8a51218827168cdclaireho	  goto next_chainsubrule;
30995569331642446be05292e3e1f8a51218827168cdclaireho	j++;
31005569331642446be05292e3e1f8a51218827168cdclaireho      }
31015569331642446be05292e3e1f8a51218827168cdclaireho
31025569331642446be05292e3e1f8a51218827168cdclaireho      if ( IN_GLYPH( j ) != curr_csr.Lookahead[i] )
31035569331642446be05292e3e1f8a51218827168cdclaireho	goto next_chainsubrule;
31045569331642446be05292e3e1f8a51218827168cdclaireho    }
31055569331642446be05292e3e1f8a51218827168cdclaireho
31065569331642446be05292e3e1f8a51218827168cdclaireho    return Do_ContextSubst( gsub, igc,
31075569331642446be05292e3e1f8a51218827168cdclaireho			    curr_csr.SubstCount,
31085569331642446be05292e3e1f8a51218827168cdclaireho			    curr_csr.SubstLookupRecord,
31095569331642446be05292e3e1f8a51218827168cdclaireho			    buffer,
31105569331642446be05292e3e1f8a51218827168cdclaireho			    nesting_level );
31115569331642446be05292e3e1f8a51218827168cdclaireho
31125569331642446be05292e3e1f8a51218827168cdclaireho  next_chainsubrule:
31135569331642446be05292e3e1f8a51218827168cdclaireho    ;
31145569331642446be05292e3e1f8a51218827168cdclaireho  }
31155569331642446be05292e3e1f8a51218827168cdclaireho
31165569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Not_Covered;
31175569331642446be05292e3e1f8a51218827168cdclaireho}
31185569331642446be05292e3e1f8a51218827168cdclaireho
31195569331642446be05292e3e1f8a51218827168cdclaireho
31205569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_ChainContextSubst2( HB_GSUBHeader*               gsub,
31215569331642446be05292e3e1f8a51218827168cdclaireho					    HB_ChainContextSubstFormat2* ccsf2,
31225569331642446be05292e3e1f8a51218827168cdclaireho					    HB_Buffer                    buffer,
31235569331642446be05292e3e1f8a51218827168cdclaireho					    HB_UShort                     flags,
31245569331642446be05292e3e1f8a51218827168cdclaireho					    HB_UShort                     context_length,
31255569331642446be05292e3e1f8a51218827168cdclaireho					    int                           nesting_level )
31265569331642446be05292e3e1f8a51218827168cdclaireho{
31275569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort              index, property;
31285569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error               error;
31295569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort              i, j, k;
31305569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort              bgc, igc, lgc;
31315569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort              known_backtrack_classes,
31325569331642446be05292e3e1f8a51218827168cdclaireho			 known_input_classes,
31335569331642446be05292e3e1f8a51218827168cdclaireho			 known_lookahead_classes;
31345569331642446be05292e3e1f8a51218827168cdclaireho
31355569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*             backtrack_classes;
31365569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*             input_classes;
31375569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*             lookahead_classes;
31385569331642446be05292e3e1f8a51218827168cdclaireho
31395569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*             bc;
31405569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*             ic;
31415569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*             lc;
31425569331642446be05292e3e1f8a51218827168cdclaireho
31435569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainSubClassSet*  cscs;
31445569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainSubClassRule  ccsr;
31455569331642446be05292e3e1f8a51218827168cdclaireho  HB_GDEFHeader*        gdef;
31465569331642446be05292e3e1f8a51218827168cdclaireho
31475569331642446be05292e3e1f8a51218827168cdclaireho
31485569331642446be05292e3e1f8a51218827168cdclaireho  gdef = gsub->gdef;
31495569331642446be05292e3e1f8a51218827168cdclaireho
31505569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
31515569331642446be05292e3e1f8a51218827168cdclaireho    return error;
31525569331642446be05292e3e1f8a51218827168cdclaireho
31535569331642446be05292e3e1f8a51218827168cdclaireho  /* Note: The coverage table in format 2 doesn't give an index into
31545569331642446be05292e3e1f8a51218827168cdclaireho	   anything.  It just lets us know whether or not we need to
31555569331642446be05292e3e1f8a51218827168cdclaireho	   do any lookup at all.                                     */
31565569331642446be05292e3e1f8a51218827168cdclaireho
31575569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Coverage_Index( &ccsf2->Coverage, IN_CURGLYPH(), &index );
31585569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
31595569331642446be05292e3e1f8a51218827168cdclaireho    return error;
31605569331642446be05292e3e1f8a51218827168cdclaireho
3161d124f9692dc8dad8f5f77c293fe6d4ec1a0c02eaRaph Levien  if (ccsf2->MaxInputLength < 1)
3162d124f9692dc8dad8f5f77c293fe6d4ec1a0c02eaRaph Levien    return HB_Err_Not_Covered;
3163d124f9692dc8dad8f5f77c293fe6d4ec1a0c02eaRaph Levien
31645569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( backtrack_classes, ccsf2->MaxBacktrackLength, HB_UShort ) )
31655569331642446be05292e3e1f8a51218827168cdclaireho    return error;
31665569331642446be05292e3e1f8a51218827168cdclaireho  known_backtrack_classes = 0;
31675569331642446be05292e3e1f8a51218827168cdclaireho
31685569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( input_classes, ccsf2->MaxInputLength, HB_UShort ) )
31695569331642446be05292e3e1f8a51218827168cdclaireho    goto End3;
31705569331642446be05292e3e1f8a51218827168cdclaireho  known_input_classes = 1;
31715569331642446be05292e3e1f8a51218827168cdclaireho
31725569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( lookahead_classes, ccsf2->MaxLookaheadLength, HB_UShort ) )
31735569331642446be05292e3e1f8a51218827168cdclaireho    goto End2;
31745569331642446be05292e3e1f8a51218827168cdclaireho  known_lookahead_classes = 0;
31755569331642446be05292e3e1f8a51218827168cdclaireho
31765569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Get_Class( &ccsf2->InputClassDef, IN_CURGLYPH(),
31775569331642446be05292e3e1f8a51218827168cdclaireho		     &input_classes[0], NULL );
31785569331642446be05292e3e1f8a51218827168cdclaireho  if ( error && error != HB_Err_Not_Covered )
31795569331642446be05292e3e1f8a51218827168cdclaireho    goto End1;
31805569331642446be05292e3e1f8a51218827168cdclaireho
31815569331642446be05292e3e1f8a51218827168cdclaireho  cscs = &ccsf2->ChainSubClassSet[input_classes[0]];
31825569331642446be05292e3e1f8a51218827168cdclaireho  if ( !cscs )
31835569331642446be05292e3e1f8a51218827168cdclaireho  {
31845569331642446be05292e3e1f8a51218827168cdclaireho    error = ERR(HB_Err_Invalid_SubTable);
31855569331642446be05292e3e1f8a51218827168cdclaireho    goto End1;
31865569331642446be05292e3e1f8a51218827168cdclaireho  }
31875569331642446be05292e3e1f8a51218827168cdclaireho
31885569331642446be05292e3e1f8a51218827168cdclaireho  for ( k = 0; k < cscs->ChainSubClassRuleCount; k++ )
31895569331642446be05292e3e1f8a51218827168cdclaireho  {
31905569331642446be05292e3e1f8a51218827168cdclaireho    ccsr = cscs->ChainSubClassRule[k];
31915569331642446be05292e3e1f8a51218827168cdclaireho    bgc  = ccsr.BacktrackGlyphCount;
31925569331642446be05292e3e1f8a51218827168cdclaireho    igc  = ccsr.InputGlyphCount;
31935569331642446be05292e3e1f8a51218827168cdclaireho    lgc  = ccsr.LookaheadGlyphCount;
31945569331642446be05292e3e1f8a51218827168cdclaireho
31955569331642446be05292e3e1f8a51218827168cdclaireho    if ( context_length != 0xFFFF && context_length < igc )
31965569331642446be05292e3e1f8a51218827168cdclaireho      goto next_chainsubclassrule;
31975569331642446be05292e3e1f8a51218827168cdclaireho
31985569331642446be05292e3e1f8a51218827168cdclaireho    /* check whether context is too long; it is a first guess only */
31995569331642446be05292e3e1f8a51218827168cdclaireho
32005569331642446be05292e3e1f8a51218827168cdclaireho    if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length )
32015569331642446be05292e3e1f8a51218827168cdclaireho      goto next_chainsubclassrule;
32025569331642446be05292e3e1f8a51218827168cdclaireho
32035569331642446be05292e3e1f8a51218827168cdclaireho    if ( bgc )
32045569331642446be05292e3e1f8a51218827168cdclaireho    {
32055569331642446be05292e3e1f8a51218827168cdclaireho      /* Since we don't know in advance the number of glyphs to inspect,
32065569331642446be05292e3e1f8a51218827168cdclaireho	 we search backwards for matches in the backtrack glyph array.
32075569331642446be05292e3e1f8a51218827168cdclaireho	 Note that `known_backtrack_classes' starts at index 0.         */
32085569331642446be05292e3e1f8a51218827168cdclaireho
32095569331642446be05292e3e1f8a51218827168cdclaireho      bc       = ccsr.Backtrack;
32105569331642446be05292e3e1f8a51218827168cdclaireho
32115569331642446be05292e3e1f8a51218827168cdclaireho      for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
32125569331642446be05292e3e1f8a51218827168cdclaireho      {
32135569331642446be05292e3e1f8a51218827168cdclaireho	while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )
32145569331642446be05292e3e1f8a51218827168cdclaireho	{
32155569331642446be05292e3e1f8a51218827168cdclaireho	  if ( error && error != HB_Err_Not_Covered )
32165569331642446be05292e3e1f8a51218827168cdclaireho	    goto End1;
32175569331642446be05292e3e1f8a51218827168cdclaireho
32185569331642446be05292e3e1f8a51218827168cdclaireho	  if ( j + 1 == bgc - i )
32195569331642446be05292e3e1f8a51218827168cdclaireho	    goto next_chainsubclassrule;
32205569331642446be05292e3e1f8a51218827168cdclaireho	  j--;
32215569331642446be05292e3e1f8a51218827168cdclaireho	}
32225569331642446be05292e3e1f8a51218827168cdclaireho
32235569331642446be05292e3e1f8a51218827168cdclaireho	if ( i >= known_backtrack_classes )
32245569331642446be05292e3e1f8a51218827168cdclaireho	{
32255569331642446be05292e3e1f8a51218827168cdclaireho	  /* Keeps us from having to do this for each rule */
32265569331642446be05292e3e1f8a51218827168cdclaireho
32275569331642446be05292e3e1f8a51218827168cdclaireho	  error = _HB_OPEN_Get_Class( &ccsf2->BacktrackClassDef, OUT_GLYPH( j ),
32285569331642446be05292e3e1f8a51218827168cdclaireho			     &backtrack_classes[i], NULL );
32295569331642446be05292e3e1f8a51218827168cdclaireho	  if ( error && error != HB_Err_Not_Covered )
32305569331642446be05292e3e1f8a51218827168cdclaireho	    goto End1;
32315569331642446be05292e3e1f8a51218827168cdclaireho	  known_backtrack_classes = i;
32325569331642446be05292e3e1f8a51218827168cdclaireho	}
32335569331642446be05292e3e1f8a51218827168cdclaireho
32345569331642446be05292e3e1f8a51218827168cdclaireho	if ( bc[i] != backtrack_classes[i] )
32355569331642446be05292e3e1f8a51218827168cdclaireho	  goto next_chainsubclassrule;
32365569331642446be05292e3e1f8a51218827168cdclaireho      }
32375569331642446be05292e3e1f8a51218827168cdclaireho    }
32385569331642446be05292e3e1f8a51218827168cdclaireho
32395569331642446be05292e3e1f8a51218827168cdclaireho    ic       = ccsr.Input;
32405569331642446be05292e3e1f8a51218827168cdclaireho
32415569331642446be05292e3e1f8a51218827168cdclaireho    /* Start at 1 because [0] is implied */
32425569331642446be05292e3e1f8a51218827168cdclaireho
32435569331642446be05292e3e1f8a51218827168cdclaireho    for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
32445569331642446be05292e3e1f8a51218827168cdclaireho    {
32455569331642446be05292e3e1f8a51218827168cdclaireho      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
32465569331642446be05292e3e1f8a51218827168cdclaireho      {
32475569331642446be05292e3e1f8a51218827168cdclaireho	if ( error && error != HB_Err_Not_Covered )
32485569331642446be05292e3e1f8a51218827168cdclaireho	  goto End1;
32495569331642446be05292e3e1f8a51218827168cdclaireho
32505569331642446be05292e3e1f8a51218827168cdclaireho	if ( j + igc - i + lgc == (HB_Int)buffer->in_length )
32515569331642446be05292e3e1f8a51218827168cdclaireho	  goto next_chainsubclassrule;
32525569331642446be05292e3e1f8a51218827168cdclaireho	j++;
32535569331642446be05292e3e1f8a51218827168cdclaireho      }
32545569331642446be05292e3e1f8a51218827168cdclaireho
32555569331642446be05292e3e1f8a51218827168cdclaireho      if ( i >= known_input_classes )
32565569331642446be05292e3e1f8a51218827168cdclaireho      {
32575569331642446be05292e3e1f8a51218827168cdclaireho	error = _HB_OPEN_Get_Class( &ccsf2->InputClassDef, IN_GLYPH( j ),
32585569331642446be05292e3e1f8a51218827168cdclaireho			   &input_classes[i], NULL );
32595569331642446be05292e3e1f8a51218827168cdclaireho	if ( error && error != HB_Err_Not_Covered )
32605569331642446be05292e3e1f8a51218827168cdclaireho	  goto End1;
32615569331642446be05292e3e1f8a51218827168cdclaireho	known_input_classes = i;
32625569331642446be05292e3e1f8a51218827168cdclaireho      }
32635569331642446be05292e3e1f8a51218827168cdclaireho
32645569331642446be05292e3e1f8a51218827168cdclaireho      if ( ic[i - 1] != input_classes[i] )
32655569331642446be05292e3e1f8a51218827168cdclaireho	goto next_chainsubclassrule;
32665569331642446be05292e3e1f8a51218827168cdclaireho    }
32675569331642446be05292e3e1f8a51218827168cdclaireho
32685569331642446be05292e3e1f8a51218827168cdclaireho    /* we are starting to check for lookahead glyphs right after the
32695569331642446be05292e3e1f8a51218827168cdclaireho       last context glyph                                            */
32705569331642446be05292e3e1f8a51218827168cdclaireho
32715569331642446be05292e3e1f8a51218827168cdclaireho    lc       = ccsr.Lookahead;
32725569331642446be05292e3e1f8a51218827168cdclaireho
32735569331642446be05292e3e1f8a51218827168cdclaireho    for ( i = 0; i < lgc; i++, j++ )
32745569331642446be05292e3e1f8a51218827168cdclaireho    {
32755569331642446be05292e3e1f8a51218827168cdclaireho      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
32765569331642446be05292e3e1f8a51218827168cdclaireho      {
32775569331642446be05292e3e1f8a51218827168cdclaireho	if ( error && error != HB_Err_Not_Covered )
32785569331642446be05292e3e1f8a51218827168cdclaireho	  goto End1;
32795569331642446be05292e3e1f8a51218827168cdclaireho
32805569331642446be05292e3e1f8a51218827168cdclaireho	if ( j + lgc - i == (HB_Int)buffer->in_length )
32815569331642446be05292e3e1f8a51218827168cdclaireho	  goto next_chainsubclassrule;
32825569331642446be05292e3e1f8a51218827168cdclaireho	j++;
32835569331642446be05292e3e1f8a51218827168cdclaireho      }
32845569331642446be05292e3e1f8a51218827168cdclaireho
32855569331642446be05292e3e1f8a51218827168cdclaireho      if ( i >= known_lookahead_classes )
32865569331642446be05292e3e1f8a51218827168cdclaireho      {
32875569331642446be05292e3e1f8a51218827168cdclaireho	error = _HB_OPEN_Get_Class( &ccsf2->LookaheadClassDef, IN_GLYPH( j ),
32885569331642446be05292e3e1f8a51218827168cdclaireho			   &lookahead_classes[i], NULL );
32895569331642446be05292e3e1f8a51218827168cdclaireho	if ( error && error != HB_Err_Not_Covered )
32905569331642446be05292e3e1f8a51218827168cdclaireho	  goto End1;
32915569331642446be05292e3e1f8a51218827168cdclaireho	known_lookahead_classes = i;
32925569331642446be05292e3e1f8a51218827168cdclaireho      }
32935569331642446be05292e3e1f8a51218827168cdclaireho
32945569331642446be05292e3e1f8a51218827168cdclaireho      if ( lc[i] != lookahead_classes[i] )
32955569331642446be05292e3e1f8a51218827168cdclaireho	goto next_chainsubclassrule;
32965569331642446be05292e3e1f8a51218827168cdclaireho    }
32975569331642446be05292e3e1f8a51218827168cdclaireho
32985569331642446be05292e3e1f8a51218827168cdclaireho    error = Do_ContextSubst( gsub, igc,
32995569331642446be05292e3e1f8a51218827168cdclaireho			     ccsr.SubstCount,
33005569331642446be05292e3e1f8a51218827168cdclaireho			     ccsr.SubstLookupRecord,
33015569331642446be05292e3e1f8a51218827168cdclaireho			     buffer,
33025569331642446be05292e3e1f8a51218827168cdclaireho			     nesting_level );
33035569331642446be05292e3e1f8a51218827168cdclaireho    goto End1;
33045569331642446be05292e3e1f8a51218827168cdclaireho
33055569331642446be05292e3e1f8a51218827168cdclaireho  next_chainsubclassrule:
33065569331642446be05292e3e1f8a51218827168cdclaireho    ;
33075569331642446be05292e3e1f8a51218827168cdclaireho  }
33085569331642446be05292e3e1f8a51218827168cdclaireho
33095569331642446be05292e3e1f8a51218827168cdclaireho  error = HB_Err_Not_Covered;
33105569331642446be05292e3e1f8a51218827168cdclaireho
33115569331642446be05292e3e1f8a51218827168cdclairehoEnd1:
33125569331642446be05292e3e1f8a51218827168cdclaireho  FREE( lookahead_classes );
33135569331642446be05292e3e1f8a51218827168cdclaireho
33145569331642446be05292e3e1f8a51218827168cdclairehoEnd2:
33155569331642446be05292e3e1f8a51218827168cdclaireho  FREE( input_classes );
33165569331642446be05292e3e1f8a51218827168cdclaireho
33175569331642446be05292e3e1f8a51218827168cdclairehoEnd3:
33185569331642446be05292e3e1f8a51218827168cdclaireho  FREE( backtrack_classes );
33195569331642446be05292e3e1f8a51218827168cdclaireho  return error;
33205569331642446be05292e3e1f8a51218827168cdclaireho}
33215569331642446be05292e3e1f8a51218827168cdclaireho
33225569331642446be05292e3e1f8a51218827168cdclaireho
33235569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_ChainContextSubst3( HB_GSUBHeader*               gsub,
33245569331642446be05292e3e1f8a51218827168cdclaireho					    HB_ChainContextSubstFormat3* ccsf3,
33255569331642446be05292e3e1f8a51218827168cdclaireho					    HB_Buffer                    buffer,
33265569331642446be05292e3e1f8a51218827168cdclaireho					    HB_UShort                     flags,
33275569331642446be05292e3e1f8a51218827168cdclaireho					    HB_UShort                     context_length,
33285569331642446be05292e3e1f8a51218827168cdclaireho					    int                           nesting_level )
33295569331642446be05292e3e1f8a51218827168cdclaireho{
33305569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        index, i, j, property;
33315569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        bgc, igc, lgc;
33325569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error         error;
33335569331642446be05292e3e1f8a51218827168cdclaireho
33345569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*    bc;
33355569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*    ic;
33365569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*    lc;
33375569331642446be05292e3e1f8a51218827168cdclaireho  HB_GDEFHeader*  gdef;
33385569331642446be05292e3e1f8a51218827168cdclaireho
33395569331642446be05292e3e1f8a51218827168cdclaireho
33405569331642446be05292e3e1f8a51218827168cdclaireho  gdef = gsub->gdef;
33415569331642446be05292e3e1f8a51218827168cdclaireho
33425569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
33435569331642446be05292e3e1f8a51218827168cdclaireho    return error;
33445569331642446be05292e3e1f8a51218827168cdclaireho
33455569331642446be05292e3e1f8a51218827168cdclaireho  bgc = ccsf3->BacktrackGlyphCount;
33465569331642446be05292e3e1f8a51218827168cdclaireho  igc = ccsf3->InputGlyphCount;
33475569331642446be05292e3e1f8a51218827168cdclaireho  lgc = ccsf3->LookaheadGlyphCount;
33485569331642446be05292e3e1f8a51218827168cdclaireho
33495569331642446be05292e3e1f8a51218827168cdclaireho  if ( context_length != 0xFFFF && context_length < igc )
33505569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
33515569331642446be05292e3e1f8a51218827168cdclaireho
33525569331642446be05292e3e1f8a51218827168cdclaireho  /* check whether context is too long; it is a first guess only */
33535569331642446be05292e3e1f8a51218827168cdclaireho
33545569331642446be05292e3e1f8a51218827168cdclaireho  if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length )
33555569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
33565569331642446be05292e3e1f8a51218827168cdclaireho
33575569331642446be05292e3e1f8a51218827168cdclaireho  if ( bgc )
33585569331642446be05292e3e1f8a51218827168cdclaireho  {
33595569331642446be05292e3e1f8a51218827168cdclaireho    /* Since we don't know in advance the number of glyphs to inspect,
33605569331642446be05292e3e1f8a51218827168cdclaireho       we search backwards for matches in the backtrack glyph array    */
33615569331642446be05292e3e1f8a51218827168cdclaireho
33625569331642446be05292e3e1f8a51218827168cdclaireho    bc       = ccsf3->BacktrackCoverage;
33635569331642446be05292e3e1f8a51218827168cdclaireho
33645569331642446be05292e3e1f8a51218827168cdclaireho    for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
33655569331642446be05292e3e1f8a51218827168cdclaireho    {
33665569331642446be05292e3e1f8a51218827168cdclaireho      while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )
33675569331642446be05292e3e1f8a51218827168cdclaireho      {
33685569331642446be05292e3e1f8a51218827168cdclaireho	if ( error && error != HB_Err_Not_Covered )
33695569331642446be05292e3e1f8a51218827168cdclaireho	  return error;
33705569331642446be05292e3e1f8a51218827168cdclaireho
33715569331642446be05292e3e1f8a51218827168cdclaireho	if ( j + 1 == bgc - i )
33725569331642446be05292e3e1f8a51218827168cdclaireho	  return HB_Err_Not_Covered;
33735569331642446be05292e3e1f8a51218827168cdclaireho	j--;
33745569331642446be05292e3e1f8a51218827168cdclaireho      }
33755569331642446be05292e3e1f8a51218827168cdclaireho
33765569331642446be05292e3e1f8a51218827168cdclaireho      error = _HB_OPEN_Coverage_Index( &bc[i], OUT_GLYPH( j ), &index );
33775569331642446be05292e3e1f8a51218827168cdclaireho      if ( error )
33785569331642446be05292e3e1f8a51218827168cdclaireho	return error;
33795569331642446be05292e3e1f8a51218827168cdclaireho    }
33805569331642446be05292e3e1f8a51218827168cdclaireho  }
33815569331642446be05292e3e1f8a51218827168cdclaireho
33825569331642446be05292e3e1f8a51218827168cdclaireho  ic       = ccsf3->InputCoverage;
33835569331642446be05292e3e1f8a51218827168cdclaireho
33845569331642446be05292e3e1f8a51218827168cdclaireho  for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ )
33855569331642446be05292e3e1f8a51218827168cdclaireho  {
33865569331642446be05292e3e1f8a51218827168cdclaireho    /* We already called CHECK_Property for IN_GLYPH( buffer->in_pos ) */
33875569331642446be05292e3e1f8a51218827168cdclaireho    while ( j > buffer->in_pos && CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
33885569331642446be05292e3e1f8a51218827168cdclaireho    {
33895569331642446be05292e3e1f8a51218827168cdclaireho      if ( error && error != HB_Err_Not_Covered )
33905569331642446be05292e3e1f8a51218827168cdclaireho	return error;
33915569331642446be05292e3e1f8a51218827168cdclaireho
33925569331642446be05292e3e1f8a51218827168cdclaireho      if ( j + igc - i + lgc == (HB_Int)buffer->in_length )
33935569331642446be05292e3e1f8a51218827168cdclaireho	return HB_Err_Not_Covered;
33945569331642446be05292e3e1f8a51218827168cdclaireho      j++;
33955569331642446be05292e3e1f8a51218827168cdclaireho    }
33965569331642446be05292e3e1f8a51218827168cdclaireho
33975569331642446be05292e3e1f8a51218827168cdclaireho    error = _HB_OPEN_Coverage_Index( &ic[i], IN_GLYPH( j ), &index );
33985569331642446be05292e3e1f8a51218827168cdclaireho    if ( error )
33995569331642446be05292e3e1f8a51218827168cdclaireho      return error;
34005569331642446be05292e3e1f8a51218827168cdclaireho  }
34015569331642446be05292e3e1f8a51218827168cdclaireho
34025569331642446be05292e3e1f8a51218827168cdclaireho  /* we are starting for lookahead glyphs right after the last context
34035569331642446be05292e3e1f8a51218827168cdclaireho     glyph                                                             */
34045569331642446be05292e3e1f8a51218827168cdclaireho
34055569331642446be05292e3e1f8a51218827168cdclaireho  lc       = ccsf3->LookaheadCoverage;
34065569331642446be05292e3e1f8a51218827168cdclaireho
34075569331642446be05292e3e1f8a51218827168cdclaireho  for ( i = 0; i < lgc; i++, j++ )
34085569331642446be05292e3e1f8a51218827168cdclaireho  {
34095569331642446be05292e3e1f8a51218827168cdclaireho    while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
34105569331642446be05292e3e1f8a51218827168cdclaireho    {
34115569331642446be05292e3e1f8a51218827168cdclaireho      if ( error && error != HB_Err_Not_Covered )
34125569331642446be05292e3e1f8a51218827168cdclaireho	return error;
34135569331642446be05292e3e1f8a51218827168cdclaireho
34145569331642446be05292e3e1f8a51218827168cdclaireho      if ( j + lgc - i == (HB_Int)buffer->in_length )
34155569331642446be05292e3e1f8a51218827168cdclaireho	return HB_Err_Not_Covered;
34165569331642446be05292e3e1f8a51218827168cdclaireho      j++;
34175569331642446be05292e3e1f8a51218827168cdclaireho    }
34185569331642446be05292e3e1f8a51218827168cdclaireho
34195569331642446be05292e3e1f8a51218827168cdclaireho    error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index );
34205569331642446be05292e3e1f8a51218827168cdclaireho    if ( error )
34215569331642446be05292e3e1f8a51218827168cdclaireho      return error;
34225569331642446be05292e3e1f8a51218827168cdclaireho  }
34235569331642446be05292e3e1f8a51218827168cdclaireho
34245569331642446be05292e3e1f8a51218827168cdclaireho  return Do_ContextSubst( gsub, igc,
34255569331642446be05292e3e1f8a51218827168cdclaireho			  ccsf3->SubstCount,
34265569331642446be05292e3e1f8a51218827168cdclaireho			  ccsf3->SubstLookupRecord,
34275569331642446be05292e3e1f8a51218827168cdclaireho			  buffer,
34285569331642446be05292e3e1f8a51218827168cdclaireho			  nesting_level );
34295569331642446be05292e3e1f8a51218827168cdclaireho}
34305569331642446be05292e3e1f8a51218827168cdclaireho
34315569331642446be05292e3e1f8a51218827168cdclaireho
34325569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_ChainContextSubst( HB_GSUBHeader*    gsub,
34335569331642446be05292e3e1f8a51218827168cdclaireho					   HB_GSUB_SubTable* st,
34345569331642446be05292e3e1f8a51218827168cdclaireho					   HB_Buffer         buffer,
34355569331642446be05292e3e1f8a51218827168cdclaireho					   HB_UShort          flags,
34365569331642446be05292e3e1f8a51218827168cdclaireho					   HB_UShort          context_length,
34375569331642446be05292e3e1f8a51218827168cdclaireho					   int                nesting_level )
34385569331642446be05292e3e1f8a51218827168cdclaireho{
34395569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainContextSubst*  ccs = &st->chain;
34405569331642446be05292e3e1f8a51218827168cdclaireho
34415569331642446be05292e3e1f8a51218827168cdclaireho  switch ( ccs->SubstFormat ) {
34425569331642446be05292e3e1f8a51218827168cdclaireho    case 1:  return Lookup_ChainContextSubst1( gsub, &ccs->ccsf.ccsf1, buffer, flags, context_length, nesting_level );
34435569331642446be05292e3e1f8a51218827168cdclaireho    case 2:  return Lookup_ChainContextSubst2( gsub, &ccs->ccsf.ccsf2, buffer, flags, context_length, nesting_level );
34445569331642446be05292e3e1f8a51218827168cdclaireho    case 3:  return Lookup_ChainContextSubst3( gsub, &ccs->ccsf.ccsf3, buffer, flags, context_length, nesting_level );
34455569331642446be05292e3e1f8a51218827168cdclaireho    default: return ERR(HB_Err_Invalid_SubTable_Format);
34465569331642446be05292e3e1f8a51218827168cdclaireho  }
34475569331642446be05292e3e1f8a51218827168cdclaireho}
34485569331642446be05292e3e1f8a51218827168cdclaireho
34495569331642446be05292e3e1f8a51218827168cdclaireho
34505569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ReverseChainContextSubst( HB_GSUB_SubTable* st,
34515569331642446be05292e3e1f8a51218827168cdclaireho					        HB_Stream         stream )
34525569331642446be05292e3e1f8a51218827168cdclaireho{
34535569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
34545569331642446be05292e3e1f8a51218827168cdclaireho  HB_ReverseChainContextSubst*  rccs = &st->reverse;
34555569331642446be05292e3e1f8a51218827168cdclaireho
34565569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort               m, count;
34575569331642446be05292e3e1f8a51218827168cdclaireho
34585569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort               nb = 0, nl = 0, n;
34595569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort               backtrack_count, lookahead_count;
34605569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt                cur_offset, new_offset, base_offset;
34615569331642446be05292e3e1f8a51218827168cdclaireho
34625569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*           b;
34635569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*           l;
34645569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*              sub;
34655569331642446be05292e3e1f8a51218827168cdclaireho
34665569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
34675569331642446be05292e3e1f8a51218827168cdclaireho
34685569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
34695569331642446be05292e3e1f8a51218827168cdclaireho    return error;
34705569331642446be05292e3e1f8a51218827168cdclaireho
34715569331642446be05292e3e1f8a51218827168cdclaireho  rccs->SubstFormat = GET_UShort();
34725569331642446be05292e3e1f8a51218827168cdclaireho
34735569331642446be05292e3e1f8a51218827168cdclaireho  if ( rccs->SubstFormat != 1 )
34745569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable_Format);
34755569331642446be05292e3e1f8a51218827168cdclaireho
34765569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
34775569331642446be05292e3e1f8a51218827168cdclaireho
34785569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
34795569331642446be05292e3e1f8a51218827168cdclaireho    return error;
34805569331642446be05292e3e1f8a51218827168cdclaireho
34815569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
34825569331642446be05292e3e1f8a51218827168cdclaireho
34835569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
34845569331642446be05292e3e1f8a51218827168cdclaireho
34855569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
34865569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
34875569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_Coverage( &rccs->Coverage, stream ) ) != HB_Err_Ok )
34885569331642446be05292e3e1f8a51218827168cdclaireho    return error;
34895569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
34905569331642446be05292e3e1f8a51218827168cdclaireho
34915569331642446be05292e3e1f8a51218827168cdclaireho
34925569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
34935569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
34945569331642446be05292e3e1f8a51218827168cdclaireho
34955569331642446be05292e3e1f8a51218827168cdclaireho  rccs->BacktrackGlyphCount = GET_UShort();
34965569331642446be05292e3e1f8a51218827168cdclaireho
34975569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
34985569331642446be05292e3e1f8a51218827168cdclaireho
34995569331642446be05292e3e1f8a51218827168cdclaireho  rccs->BacktrackCoverage = NULL;
35005569331642446be05292e3e1f8a51218827168cdclaireho
35015569331642446be05292e3e1f8a51218827168cdclaireho  backtrack_count = rccs->BacktrackGlyphCount;
35025569331642446be05292e3e1f8a51218827168cdclaireho
35035569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( rccs->BacktrackCoverage, backtrack_count,
35045569331642446be05292e3e1f8a51218827168cdclaireho		    HB_Coverage ) )
35055569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
35065569331642446be05292e3e1f8a51218827168cdclaireho
35075569331642446be05292e3e1f8a51218827168cdclaireho  b = rccs->BacktrackCoverage;
35085569331642446be05292e3e1f8a51218827168cdclaireho
35095569331642446be05292e3e1f8a51218827168cdclaireho  for ( nb = 0; nb < backtrack_count; nb++ )
35105569331642446be05292e3e1f8a51218827168cdclaireho  {
35115569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
35125569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail3;
35135569331642446be05292e3e1f8a51218827168cdclaireho
35145569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
35155569331642446be05292e3e1f8a51218827168cdclaireho
35165569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
35175569331642446be05292e3e1f8a51218827168cdclaireho
35185569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
35195569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
35205569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != HB_Err_Ok )
35215569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail3;
35225569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
35235569331642446be05292e3e1f8a51218827168cdclaireho  }
35245569331642446be05292e3e1f8a51218827168cdclaireho
35255569331642446be05292e3e1f8a51218827168cdclaireho
35265569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
35275569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
35285569331642446be05292e3e1f8a51218827168cdclaireho
35295569331642446be05292e3e1f8a51218827168cdclaireho  rccs->LookaheadGlyphCount = GET_UShort();
35305569331642446be05292e3e1f8a51218827168cdclaireho
35315569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
35325569331642446be05292e3e1f8a51218827168cdclaireho
35335569331642446be05292e3e1f8a51218827168cdclaireho  rccs->LookaheadCoverage = NULL;
35345569331642446be05292e3e1f8a51218827168cdclaireho
35355569331642446be05292e3e1f8a51218827168cdclaireho  lookahead_count = rccs->LookaheadGlyphCount;
35365569331642446be05292e3e1f8a51218827168cdclaireho
35375569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( rccs->LookaheadCoverage, lookahead_count,
35385569331642446be05292e3e1f8a51218827168cdclaireho		    HB_Coverage ) )
35395569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
35405569331642446be05292e3e1f8a51218827168cdclaireho
35415569331642446be05292e3e1f8a51218827168cdclaireho  l = rccs->LookaheadCoverage;
35425569331642446be05292e3e1f8a51218827168cdclaireho
35435569331642446be05292e3e1f8a51218827168cdclaireho  for ( nl = 0; nl < lookahead_count; nl++ )
35445569331642446be05292e3e1f8a51218827168cdclaireho  {
35455569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
35465569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail2;
35475569331642446be05292e3e1f8a51218827168cdclaireho
35485569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
35495569331642446be05292e3e1f8a51218827168cdclaireho
35505569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
35515569331642446be05292e3e1f8a51218827168cdclaireho
35525569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
35535569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
35545569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != HB_Err_Ok )
35555569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail2;
35565569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
35575569331642446be05292e3e1f8a51218827168cdclaireho  }
35585569331642446be05292e3e1f8a51218827168cdclaireho
35595569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
35605569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
35615569331642446be05292e3e1f8a51218827168cdclaireho
35625569331642446be05292e3e1f8a51218827168cdclaireho  rccs->GlyphCount = GET_UShort();
35635569331642446be05292e3e1f8a51218827168cdclaireho
35645569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
35655569331642446be05292e3e1f8a51218827168cdclaireho
35665569331642446be05292e3e1f8a51218827168cdclaireho  rccs->Substitute = NULL;
35675569331642446be05292e3e1f8a51218827168cdclaireho
35685569331642446be05292e3e1f8a51218827168cdclaireho  count = rccs->GlyphCount;
35695569331642446be05292e3e1f8a51218827168cdclaireho
35705569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( rccs->Substitute, count,
35715569331642446be05292e3e1f8a51218827168cdclaireho		    HB_UShort ) )
35725569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
35735569331642446be05292e3e1f8a51218827168cdclaireho
35745569331642446be05292e3e1f8a51218827168cdclaireho  sub = rccs->Substitute;
35755569331642446be05292e3e1f8a51218827168cdclaireho
35765569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
35775569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail1;
35785569331642446be05292e3e1f8a51218827168cdclaireho
35795569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
35805569331642446be05292e3e1f8a51218827168cdclaireho    sub[n] = GET_UShort();
35815569331642446be05292e3e1f8a51218827168cdclaireho
35825569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
35835569331642446be05292e3e1f8a51218827168cdclaireho
35845569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
35855569331642446be05292e3e1f8a51218827168cdclaireho
35865569331642446be05292e3e1f8a51218827168cdclairehoFail1:
35875569331642446be05292e3e1f8a51218827168cdclaireho  FREE( sub );
35885569331642446be05292e3e1f8a51218827168cdclaireho
35895569331642446be05292e3e1f8a51218827168cdclairehoFail2:
35905569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < nl; m++ )
35915569331642446be05292e3e1f8a51218827168cdclaireho    _HB_OPEN_Free_Coverage( &l[m] );
35925569331642446be05292e3e1f8a51218827168cdclaireho
35935569331642446be05292e3e1f8a51218827168cdclaireho  FREE( l );
35945569331642446be05292e3e1f8a51218827168cdclaireho
35955569331642446be05292e3e1f8a51218827168cdclairehoFail3:
35965569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < nb; m++ )
35975569331642446be05292e3e1f8a51218827168cdclaireho    _HB_OPEN_Free_Coverage( &b[m] );
35985569331642446be05292e3e1f8a51218827168cdclaireho
35995569331642446be05292e3e1f8a51218827168cdclaireho  FREE( b );
36005569331642446be05292e3e1f8a51218827168cdclaireho
36015569331642446be05292e3e1f8a51218827168cdclairehoFail4:
36025569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &rccs->Coverage );
36035569331642446be05292e3e1f8a51218827168cdclaireho  return error;
36045569331642446be05292e3e1f8a51218827168cdclaireho}
36055569331642446be05292e3e1f8a51218827168cdclaireho
36065569331642446be05292e3e1f8a51218827168cdclaireho
36075569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ReverseChainContextSubst( HB_GSUB_SubTable* st )
36085569331642446be05292e3e1f8a51218827168cdclaireho{
36095569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort      n, count;
36105569331642446be05292e3e1f8a51218827168cdclaireho  HB_ReverseChainContextSubst*  rccs = &st->reverse;
36115569331642446be05292e3e1f8a51218827168cdclaireho
36125569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*  c;
36135569331642446be05292e3e1f8a51218827168cdclaireho
36145569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &rccs->Coverage );
36155569331642446be05292e3e1f8a51218827168cdclaireho
36165569331642446be05292e3e1f8a51218827168cdclaireho  if ( rccs->LookaheadCoverage )
36175569331642446be05292e3e1f8a51218827168cdclaireho  {
36185569331642446be05292e3e1f8a51218827168cdclaireho    count = rccs->LookaheadGlyphCount;
36195569331642446be05292e3e1f8a51218827168cdclaireho    c     = rccs->LookaheadCoverage;
36205569331642446be05292e3e1f8a51218827168cdclaireho
36215569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
36225569331642446be05292e3e1f8a51218827168cdclaireho      _HB_OPEN_Free_Coverage( &c[n] );
36235569331642446be05292e3e1f8a51218827168cdclaireho
36245569331642446be05292e3e1f8a51218827168cdclaireho    FREE( c );
36255569331642446be05292e3e1f8a51218827168cdclaireho  }
36265569331642446be05292e3e1f8a51218827168cdclaireho
36275569331642446be05292e3e1f8a51218827168cdclaireho  if ( rccs->BacktrackCoverage )
36285569331642446be05292e3e1f8a51218827168cdclaireho  {
36295569331642446be05292e3e1f8a51218827168cdclaireho    count = rccs->BacktrackGlyphCount;
36305569331642446be05292e3e1f8a51218827168cdclaireho    c     = rccs->BacktrackCoverage;
36315569331642446be05292e3e1f8a51218827168cdclaireho
36325569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
36335569331642446be05292e3e1f8a51218827168cdclaireho      _HB_OPEN_Free_Coverage( &c[n] );
36345569331642446be05292e3e1f8a51218827168cdclaireho
36355569331642446be05292e3e1f8a51218827168cdclaireho    FREE( c );
36365569331642446be05292e3e1f8a51218827168cdclaireho  }
36375569331642446be05292e3e1f8a51218827168cdclaireho
36385569331642446be05292e3e1f8a51218827168cdclaireho  FREE ( rccs->Substitute );
36395569331642446be05292e3e1f8a51218827168cdclaireho}
36405569331642446be05292e3e1f8a51218827168cdclaireho
36415569331642446be05292e3e1f8a51218827168cdclaireho
36425569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_ReverseChainContextSubst( HB_GSUBHeader*    gsub,
36435569331642446be05292e3e1f8a51218827168cdclaireho						  HB_GSUB_SubTable* st,
36445569331642446be05292e3e1f8a51218827168cdclaireho						  HB_Buffer         buffer,
36455569331642446be05292e3e1f8a51218827168cdclaireho						  HB_UShort          flags,
36465569331642446be05292e3e1f8a51218827168cdclaireho						  HB_UShort         context_length,
36475569331642446be05292e3e1f8a51218827168cdclaireho						  int               nesting_level )
36485569331642446be05292e3e1f8a51218827168cdclaireho{
36495569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        index, input_index, i, j, property;
36505569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        bgc, lgc;
36515569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error         error;
36525569331642446be05292e3e1f8a51218827168cdclaireho
36535569331642446be05292e3e1f8a51218827168cdclaireho  HB_ReverseChainContextSubst*  rccs = &st->reverse;
36545569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*    bc;
36555569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*    lc;
36565569331642446be05292e3e1f8a51218827168cdclaireho  HB_GDEFHeader*  gdef;
36575569331642446be05292e3e1f8a51218827168cdclaireho
36585569331642446be05292e3e1f8a51218827168cdclaireho  if ( nesting_level != 1 || context_length != 0xFFFF )
36595569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
36605569331642446be05292e3e1f8a51218827168cdclaireho
36615569331642446be05292e3e1f8a51218827168cdclaireho  gdef = gsub->gdef;
36625569331642446be05292e3e1f8a51218827168cdclaireho
36635569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
36645569331642446be05292e3e1f8a51218827168cdclaireho    return error;
36655569331642446be05292e3e1f8a51218827168cdclaireho
36665569331642446be05292e3e1f8a51218827168cdclaireho  bgc = rccs->BacktrackGlyphCount;
36675569331642446be05292e3e1f8a51218827168cdclaireho  lgc = rccs->LookaheadGlyphCount;
36685569331642446be05292e3e1f8a51218827168cdclaireho
36695569331642446be05292e3e1f8a51218827168cdclaireho  /* check whether context is too long; it is a first guess only */
36705569331642446be05292e3e1f8a51218827168cdclaireho
36715569331642446be05292e3e1f8a51218827168cdclaireho  if ( bgc > buffer->in_pos || buffer->in_pos + 1 + lgc > buffer->in_length )
36725569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
36735569331642446be05292e3e1f8a51218827168cdclaireho
36745569331642446be05292e3e1f8a51218827168cdclaireho  if ( bgc )
36755569331642446be05292e3e1f8a51218827168cdclaireho  {
36765569331642446be05292e3e1f8a51218827168cdclaireho    /* Since we don't know in advance the number of glyphs to inspect,
36775569331642446be05292e3e1f8a51218827168cdclaireho       we search backwards for matches in the backtrack glyph array    */
36785569331642446be05292e3e1f8a51218827168cdclaireho
36795569331642446be05292e3e1f8a51218827168cdclaireho    bc       = rccs->BacktrackCoverage;
36805569331642446be05292e3e1f8a51218827168cdclaireho
36815569331642446be05292e3e1f8a51218827168cdclaireho    for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
36825569331642446be05292e3e1f8a51218827168cdclaireho    {
36835569331642446be05292e3e1f8a51218827168cdclaireho      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
36845569331642446be05292e3e1f8a51218827168cdclaireho      {
36855569331642446be05292e3e1f8a51218827168cdclaireho	if ( error && error != HB_Err_Not_Covered )
36865569331642446be05292e3e1f8a51218827168cdclaireho	  return error;
36875569331642446be05292e3e1f8a51218827168cdclaireho
36885569331642446be05292e3e1f8a51218827168cdclaireho	if ( j + 1 == bgc - i )
36895569331642446be05292e3e1f8a51218827168cdclaireho	  return HB_Err_Not_Covered;
36905569331642446be05292e3e1f8a51218827168cdclaireho	j--;
36915569331642446be05292e3e1f8a51218827168cdclaireho      }
36925569331642446be05292e3e1f8a51218827168cdclaireho
36935569331642446be05292e3e1f8a51218827168cdclaireho      error = _HB_OPEN_Coverage_Index( &bc[i], IN_GLYPH( j ), &index );
36945569331642446be05292e3e1f8a51218827168cdclaireho      if ( error )
36955569331642446be05292e3e1f8a51218827168cdclaireho	return error;
36965569331642446be05292e3e1f8a51218827168cdclaireho    }
36975569331642446be05292e3e1f8a51218827168cdclaireho  }
36985569331642446be05292e3e1f8a51218827168cdclaireho
36995569331642446be05292e3e1f8a51218827168cdclaireho  j = buffer->in_pos;
37005569331642446be05292e3e1f8a51218827168cdclaireho
37015569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Coverage_Index( &rccs->Coverage, IN_GLYPH( j ), &input_index );
37025569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
37035569331642446be05292e3e1f8a51218827168cdclaireho      return error;
37045569331642446be05292e3e1f8a51218827168cdclaireho
37055569331642446be05292e3e1f8a51218827168cdclaireho  lc       = rccs->LookaheadCoverage;
37065569331642446be05292e3e1f8a51218827168cdclaireho
37075569331642446be05292e3e1f8a51218827168cdclaireho  for ( i = 0, j = buffer->in_pos + 1; i < lgc; i++, j++ )
37085569331642446be05292e3e1f8a51218827168cdclaireho  {
37095569331642446be05292e3e1f8a51218827168cdclaireho    while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
37105569331642446be05292e3e1f8a51218827168cdclaireho    {
37115569331642446be05292e3e1f8a51218827168cdclaireho      if ( error && error != HB_Err_Not_Covered )
37125569331642446be05292e3e1f8a51218827168cdclaireho	return error;
37135569331642446be05292e3e1f8a51218827168cdclaireho
37145569331642446be05292e3e1f8a51218827168cdclaireho      if ( j + lgc - i == (HB_Int)buffer->in_length )
37155569331642446be05292e3e1f8a51218827168cdclaireho	return HB_Err_Not_Covered;
37165569331642446be05292e3e1f8a51218827168cdclaireho      j++;
37175569331642446be05292e3e1f8a51218827168cdclaireho    }
37185569331642446be05292e3e1f8a51218827168cdclaireho
37195569331642446be05292e3e1f8a51218827168cdclaireho    error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index );
37205569331642446be05292e3e1f8a51218827168cdclaireho    if ( error )
37215569331642446be05292e3e1f8a51218827168cdclaireho      return error;
37225569331642446be05292e3e1f8a51218827168cdclaireho  }
37235569331642446be05292e3e1f8a51218827168cdclaireho
37245569331642446be05292e3e1f8a51218827168cdclaireho  IN_CURGLYPH() = rccs->Substitute[input_index];
37255569331642446be05292e3e1f8a51218827168cdclaireho  buffer->in_pos--; /* Reverse! */
37265569331642446be05292e3e1f8a51218827168cdclaireho
37275569331642446be05292e3e1f8a51218827168cdclaireho  return error;
37285569331642446be05292e3e1f8a51218827168cdclaireho}
37295569331642446be05292e3e1f8a51218827168cdclaireho
37305569331642446be05292e3e1f8a51218827168cdclaireho
37315569331642446be05292e3e1f8a51218827168cdclaireho
37325569331642446be05292e3e1f8a51218827168cdclaireho/***********
37335569331642446be05292e3e1f8a51218827168cdclaireho * GSUB API
37345569331642446be05292e3e1f8a51218827168cdclaireho ***********/
37355569331642446be05292e3e1f8a51218827168cdclaireho
37365569331642446be05292e3e1f8a51218827168cdclaireho
37375569331642446be05292e3e1f8a51218827168cdclaireho
37385569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_GSUB_Select_Script( HB_GSUBHeader*  gsub,
37395569331642446be05292e3e1f8a51218827168cdclaireho				 HB_UInt         script_tag,
37405569331642446be05292e3e1f8a51218827168cdclaireho				 HB_UShort*       script_index )
37415569331642446be05292e3e1f8a51218827168cdclaireho{
37425569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          n;
37435569331642446be05292e3e1f8a51218827168cdclaireho
37445569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptList*    sl;
37455569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptRecord*  sr;
37465569331642446be05292e3e1f8a51218827168cdclaireho
37475569331642446be05292e3e1f8a51218827168cdclaireho
37485569331642446be05292e3e1f8a51218827168cdclaireho  if ( !gsub || !script_index )
37495569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
37505569331642446be05292e3e1f8a51218827168cdclaireho
37515569331642446be05292e3e1f8a51218827168cdclaireho  sl = &gsub->ScriptList;
37525569331642446be05292e3e1f8a51218827168cdclaireho  sr = sl->ScriptRecord;
37535569331642446be05292e3e1f8a51218827168cdclaireho
37545569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < sl->ScriptCount; n++ )
37555569331642446be05292e3e1f8a51218827168cdclaireho    if ( script_tag == sr[n].ScriptTag )
37565569331642446be05292e3e1f8a51218827168cdclaireho    {
37575569331642446be05292e3e1f8a51218827168cdclaireho      *script_index = n;
37585569331642446be05292e3e1f8a51218827168cdclaireho
37595569331642446be05292e3e1f8a51218827168cdclaireho      return HB_Err_Ok;
37605569331642446be05292e3e1f8a51218827168cdclaireho    }
37615569331642446be05292e3e1f8a51218827168cdclaireho
37625569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Not_Covered;
37635569331642446be05292e3e1f8a51218827168cdclaireho}
37645569331642446be05292e3e1f8a51218827168cdclaireho
37655569331642446be05292e3e1f8a51218827168cdclaireho
37665569331642446be05292e3e1f8a51218827168cdclaireho
37675569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_GSUB_Select_Language( HB_GSUBHeader*  gsub,
37685569331642446be05292e3e1f8a51218827168cdclaireho				   HB_UInt         language_tag,
37695569331642446be05292e3e1f8a51218827168cdclaireho				   HB_UShort        script_index,
37705569331642446be05292e3e1f8a51218827168cdclaireho				   HB_UShort*       language_index,
37715569331642446be05292e3e1f8a51218827168cdclaireho				   HB_UShort*       req_feature_index )
37725569331642446be05292e3e1f8a51218827168cdclaireho{
37735569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort           n;
37745569331642446be05292e3e1f8a51218827168cdclaireho
37755569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptList*     sl;
37765569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptRecord*   sr;
37775569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptTable*    s;
37785569331642446be05292e3e1f8a51218827168cdclaireho  HB_LangSysRecord*  lsr;
37795569331642446be05292e3e1f8a51218827168cdclaireho
37805569331642446be05292e3e1f8a51218827168cdclaireho
37815569331642446be05292e3e1f8a51218827168cdclaireho  if ( !gsub || !language_index || !req_feature_index )
37825569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
37835569331642446be05292e3e1f8a51218827168cdclaireho
37845569331642446be05292e3e1f8a51218827168cdclaireho  sl = &gsub->ScriptList;
37855569331642446be05292e3e1f8a51218827168cdclaireho  sr = sl->ScriptRecord;
37865569331642446be05292e3e1f8a51218827168cdclaireho
37875569331642446be05292e3e1f8a51218827168cdclaireho  if ( script_index >= sl->ScriptCount )
37885569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
37895569331642446be05292e3e1f8a51218827168cdclaireho
37905569331642446be05292e3e1f8a51218827168cdclaireho  s   = &sr[script_index].Script;
37915569331642446be05292e3e1f8a51218827168cdclaireho  lsr = s->LangSysRecord;
37925569331642446be05292e3e1f8a51218827168cdclaireho
37935569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < s->LangSysCount; n++ )
37945569331642446be05292e3e1f8a51218827168cdclaireho    if ( language_tag == lsr[n].LangSysTag )
37955569331642446be05292e3e1f8a51218827168cdclaireho    {
37965569331642446be05292e3e1f8a51218827168cdclaireho      *language_index = n;
37975569331642446be05292e3e1f8a51218827168cdclaireho      *req_feature_index = lsr[n].LangSys.ReqFeatureIndex;
37985569331642446be05292e3e1f8a51218827168cdclaireho
37995569331642446be05292e3e1f8a51218827168cdclaireho      return HB_Err_Ok;
38005569331642446be05292e3e1f8a51218827168cdclaireho    }
38015569331642446be05292e3e1f8a51218827168cdclaireho
38025569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Not_Covered;
38035569331642446be05292e3e1f8a51218827168cdclaireho}
38045569331642446be05292e3e1f8a51218827168cdclaireho
38055569331642446be05292e3e1f8a51218827168cdclaireho
38065569331642446be05292e3e1f8a51218827168cdclaireho/* selecting 0xFFFF for language_index asks for the values of the
38075569331642446be05292e3e1f8a51218827168cdclaireho   default language (DefaultLangSys)                              */
38085569331642446be05292e3e1f8a51218827168cdclaireho
38095569331642446be05292e3e1f8a51218827168cdclaireho
38105569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_GSUB_Select_Feature( HB_GSUBHeader*  gsub,
38115569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UInt         feature_tag,
38125569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort        script_index,
38135569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort        language_index,
38145569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort*       feature_index )
38155569331642446be05292e3e1f8a51218827168cdclaireho{
38165569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort           n;
38175569331642446be05292e3e1f8a51218827168cdclaireho
38185569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptList*     sl;
38195569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptRecord*   sr;
38205569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptTable*    s;
38215569331642446be05292e3e1f8a51218827168cdclaireho  HB_LangSysRecord*  lsr;
38225569331642446be05292e3e1f8a51218827168cdclaireho  HB_LangSys*        ls;
38235569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*          fi;
38245569331642446be05292e3e1f8a51218827168cdclaireho
38255569331642446be05292e3e1f8a51218827168cdclaireho  HB_FeatureList*    fl;
38265569331642446be05292e3e1f8a51218827168cdclaireho  HB_FeatureRecord*  fr;
38275569331642446be05292e3e1f8a51218827168cdclaireho
38285569331642446be05292e3e1f8a51218827168cdclaireho
38295569331642446be05292e3e1f8a51218827168cdclaireho  if ( !gsub || !feature_index )
38305569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
38315569331642446be05292e3e1f8a51218827168cdclaireho
38325569331642446be05292e3e1f8a51218827168cdclaireho  sl = &gsub->ScriptList;
38335569331642446be05292e3e1f8a51218827168cdclaireho  sr = sl->ScriptRecord;
38345569331642446be05292e3e1f8a51218827168cdclaireho
38355569331642446be05292e3e1f8a51218827168cdclaireho  fl = &gsub->FeatureList;
38365569331642446be05292e3e1f8a51218827168cdclaireho  fr = fl->FeatureRecord;
38375569331642446be05292e3e1f8a51218827168cdclaireho
38385569331642446be05292e3e1f8a51218827168cdclaireho  if ( script_index >= sl->ScriptCount )
38395569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
38405569331642446be05292e3e1f8a51218827168cdclaireho
38415569331642446be05292e3e1f8a51218827168cdclaireho  s   = &sr[script_index].Script;
38425569331642446be05292e3e1f8a51218827168cdclaireho  lsr = s->LangSysRecord;
38435569331642446be05292e3e1f8a51218827168cdclaireho
38445569331642446be05292e3e1f8a51218827168cdclaireho  if ( language_index == 0xFFFF )
38455569331642446be05292e3e1f8a51218827168cdclaireho    ls = &s->DefaultLangSys;
38465569331642446be05292e3e1f8a51218827168cdclaireho  else
38475569331642446be05292e3e1f8a51218827168cdclaireho  {
38485569331642446be05292e3e1f8a51218827168cdclaireho    if ( language_index >= s->LangSysCount )
38495569331642446be05292e3e1f8a51218827168cdclaireho      return ERR(HB_Err_Invalid_Argument);
38505569331642446be05292e3e1f8a51218827168cdclaireho
38515569331642446be05292e3e1f8a51218827168cdclaireho    ls = &lsr[language_index].LangSys;
38525569331642446be05292e3e1f8a51218827168cdclaireho  }
38535569331642446be05292e3e1f8a51218827168cdclaireho
38545569331642446be05292e3e1f8a51218827168cdclaireho  fi = ls->FeatureIndex;
38555569331642446be05292e3e1f8a51218827168cdclaireho
38565569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < ls->FeatureCount; n++ )
38575569331642446be05292e3e1f8a51218827168cdclaireho  {
38585569331642446be05292e3e1f8a51218827168cdclaireho    if ( fi[n] >= fl->FeatureCount )
38595569331642446be05292e3e1f8a51218827168cdclaireho      return ERR(HB_Err_Invalid_SubTable_Format);
38605569331642446be05292e3e1f8a51218827168cdclaireho
38615569331642446be05292e3e1f8a51218827168cdclaireho    if ( feature_tag == fr[fi[n]].FeatureTag )
38625569331642446be05292e3e1f8a51218827168cdclaireho    {
38635569331642446be05292e3e1f8a51218827168cdclaireho      *feature_index = fi[n];
38645569331642446be05292e3e1f8a51218827168cdclaireho
38655569331642446be05292e3e1f8a51218827168cdclaireho      return HB_Err_Ok;
38665569331642446be05292e3e1f8a51218827168cdclaireho    }
38675569331642446be05292e3e1f8a51218827168cdclaireho  }
38685569331642446be05292e3e1f8a51218827168cdclaireho
38695569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Not_Covered;
38705569331642446be05292e3e1f8a51218827168cdclaireho}
38715569331642446be05292e3e1f8a51218827168cdclaireho
38725569331642446be05292e3e1f8a51218827168cdclaireho
38735569331642446be05292e3e1f8a51218827168cdclaireho/* The next three functions return a null-terminated list */
38745569331642446be05292e3e1f8a51218827168cdclaireho
38755569331642446be05292e3e1f8a51218827168cdclaireho
38765569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_GSUB_Query_Scripts( HB_GSUBHeader*  gsub,
38775569331642446be05292e3e1f8a51218827168cdclaireho				 HB_UInt**       script_tag_list )
38785569331642446be05292e3e1f8a51218827168cdclaireho{
38795569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          n;
38805569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error           error;
38815569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt*          stl;
38825569331642446be05292e3e1f8a51218827168cdclaireho
38835569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptList*    sl;
38845569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptRecord*  sr;
38855569331642446be05292e3e1f8a51218827168cdclaireho
38865569331642446be05292e3e1f8a51218827168cdclaireho
38875569331642446be05292e3e1f8a51218827168cdclaireho  if ( !gsub || !script_tag_list )
38885569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
38895569331642446be05292e3e1f8a51218827168cdclaireho
38905569331642446be05292e3e1f8a51218827168cdclaireho  sl = &gsub->ScriptList;
38915569331642446be05292e3e1f8a51218827168cdclaireho  sr = sl->ScriptRecord;
38925569331642446be05292e3e1f8a51218827168cdclaireho
38935569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( stl, sl->ScriptCount + 1, HB_UInt ) )
38945569331642446be05292e3e1f8a51218827168cdclaireho    return error;
38955569331642446be05292e3e1f8a51218827168cdclaireho
38965569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < sl->ScriptCount; n++ )
38975569331642446be05292e3e1f8a51218827168cdclaireho    stl[n] = sr[n].ScriptTag;
38985569331642446be05292e3e1f8a51218827168cdclaireho  stl[n] = 0;
38995569331642446be05292e3e1f8a51218827168cdclaireho
39005569331642446be05292e3e1f8a51218827168cdclaireho  *script_tag_list = stl;
39015569331642446be05292e3e1f8a51218827168cdclaireho
39025569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
39035569331642446be05292e3e1f8a51218827168cdclaireho}
39045569331642446be05292e3e1f8a51218827168cdclaireho
39055569331642446be05292e3e1f8a51218827168cdclaireho
39065569331642446be05292e3e1f8a51218827168cdclaireho
39075569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_GSUB_Query_Languages( HB_GSUBHeader*  gsub,
39085569331642446be05292e3e1f8a51218827168cdclaireho				   HB_UShort        script_index,
39095569331642446be05292e3e1f8a51218827168cdclaireho				   HB_UInt**       language_tag_list )
39105569331642446be05292e3e1f8a51218827168cdclaireho{
39115569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort           n;
39125569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error            error;
39135569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt*           ltl;
39145569331642446be05292e3e1f8a51218827168cdclaireho
39155569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptList*     sl;
39165569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptRecord*   sr;
39175569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptTable*    s;
39185569331642446be05292e3e1f8a51218827168cdclaireho  HB_LangSysRecord*  lsr;
39195569331642446be05292e3e1f8a51218827168cdclaireho
39205569331642446be05292e3e1f8a51218827168cdclaireho
39215569331642446be05292e3e1f8a51218827168cdclaireho  if ( !gsub || !language_tag_list )
39225569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
39235569331642446be05292e3e1f8a51218827168cdclaireho
39245569331642446be05292e3e1f8a51218827168cdclaireho  sl = &gsub->ScriptList;
39255569331642446be05292e3e1f8a51218827168cdclaireho  sr = sl->ScriptRecord;
39265569331642446be05292e3e1f8a51218827168cdclaireho
39275569331642446be05292e3e1f8a51218827168cdclaireho  if ( script_index >= sl->ScriptCount )
39285569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
39295569331642446be05292e3e1f8a51218827168cdclaireho
39305569331642446be05292e3e1f8a51218827168cdclaireho  s   = &sr[script_index].Script;
39315569331642446be05292e3e1f8a51218827168cdclaireho  lsr = s->LangSysRecord;
39325569331642446be05292e3e1f8a51218827168cdclaireho
39335569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ltl, s->LangSysCount + 1, HB_UInt ) )
39345569331642446be05292e3e1f8a51218827168cdclaireho    return error;
39355569331642446be05292e3e1f8a51218827168cdclaireho
39365569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < s->LangSysCount; n++ )
39375569331642446be05292e3e1f8a51218827168cdclaireho    ltl[n] = lsr[n].LangSysTag;
39385569331642446be05292e3e1f8a51218827168cdclaireho  ltl[n] = 0;
39395569331642446be05292e3e1f8a51218827168cdclaireho
39405569331642446be05292e3e1f8a51218827168cdclaireho  *language_tag_list = ltl;
39415569331642446be05292e3e1f8a51218827168cdclaireho
39425569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
39435569331642446be05292e3e1f8a51218827168cdclaireho}
39445569331642446be05292e3e1f8a51218827168cdclaireho
39455569331642446be05292e3e1f8a51218827168cdclaireho
39465569331642446be05292e3e1f8a51218827168cdclaireho/* selecting 0xFFFF for language_index asks for the values of the
39475569331642446be05292e3e1f8a51218827168cdclaireho   default language (DefaultLangSys)                              */
39485569331642446be05292e3e1f8a51218827168cdclaireho
39495569331642446be05292e3e1f8a51218827168cdclaireho
39505569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_GSUB_Query_Features( HB_GSUBHeader*  gsub,
39515569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort        script_index,
39525569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort        language_index,
39535569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UInt**       feature_tag_list )
39545569331642446be05292e3e1f8a51218827168cdclaireho{
39555569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort           n;
39565569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error            error;
39575569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt*           ftl;
39585569331642446be05292e3e1f8a51218827168cdclaireho
39595569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptList*     sl;
39605569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptRecord*   sr;
39615569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptTable*    s;
39625569331642446be05292e3e1f8a51218827168cdclaireho  HB_LangSysRecord*  lsr;
39635569331642446be05292e3e1f8a51218827168cdclaireho  HB_LangSys*        ls;
39645569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*          fi;
39655569331642446be05292e3e1f8a51218827168cdclaireho
39665569331642446be05292e3e1f8a51218827168cdclaireho  HB_FeatureList*    fl;
39675569331642446be05292e3e1f8a51218827168cdclaireho  HB_FeatureRecord*  fr;
39685569331642446be05292e3e1f8a51218827168cdclaireho
39695569331642446be05292e3e1f8a51218827168cdclaireho
39705569331642446be05292e3e1f8a51218827168cdclaireho  if ( !gsub || !feature_tag_list )
39715569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
39725569331642446be05292e3e1f8a51218827168cdclaireho
39735569331642446be05292e3e1f8a51218827168cdclaireho  sl = &gsub->ScriptList;
39745569331642446be05292e3e1f8a51218827168cdclaireho  sr = sl->ScriptRecord;
39755569331642446be05292e3e1f8a51218827168cdclaireho
39765569331642446be05292e3e1f8a51218827168cdclaireho  fl = &gsub->FeatureList;
39775569331642446be05292e3e1f8a51218827168cdclaireho  fr = fl->FeatureRecord;
39785569331642446be05292e3e1f8a51218827168cdclaireho
39795569331642446be05292e3e1f8a51218827168cdclaireho  if ( script_index >= sl->ScriptCount )
39805569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
39815569331642446be05292e3e1f8a51218827168cdclaireho
39825569331642446be05292e3e1f8a51218827168cdclaireho  s   = &sr[script_index].Script;
39835569331642446be05292e3e1f8a51218827168cdclaireho  lsr = s->LangSysRecord;
39845569331642446be05292e3e1f8a51218827168cdclaireho
39855569331642446be05292e3e1f8a51218827168cdclaireho  if ( language_index == 0xFFFF )
39865569331642446be05292e3e1f8a51218827168cdclaireho    ls = &s->DefaultLangSys;
39875569331642446be05292e3e1f8a51218827168cdclaireho  else
39885569331642446be05292e3e1f8a51218827168cdclaireho  {
39895569331642446be05292e3e1f8a51218827168cdclaireho    if ( language_index >= s->LangSysCount )
39905569331642446be05292e3e1f8a51218827168cdclaireho      return ERR(HB_Err_Invalid_Argument);
39915569331642446be05292e3e1f8a51218827168cdclaireho
39925569331642446be05292e3e1f8a51218827168cdclaireho    ls = &lsr[language_index].LangSys;
39935569331642446be05292e3e1f8a51218827168cdclaireho  }
39945569331642446be05292e3e1f8a51218827168cdclaireho
39955569331642446be05292e3e1f8a51218827168cdclaireho  fi = ls->FeatureIndex;
39965569331642446be05292e3e1f8a51218827168cdclaireho
39975569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ftl, ls->FeatureCount + 1, HB_UInt ) )
39985569331642446be05292e3e1f8a51218827168cdclaireho    return error;
39995569331642446be05292e3e1f8a51218827168cdclaireho
40005569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < ls->FeatureCount; n++ )
40015569331642446be05292e3e1f8a51218827168cdclaireho  {
40025569331642446be05292e3e1f8a51218827168cdclaireho    if ( fi[n] >= fl->FeatureCount )
40035569331642446be05292e3e1f8a51218827168cdclaireho    {
40045569331642446be05292e3e1f8a51218827168cdclaireho      FREE( ftl );
40055569331642446be05292e3e1f8a51218827168cdclaireho      return ERR(HB_Err_Invalid_SubTable_Format);
40065569331642446be05292e3e1f8a51218827168cdclaireho    }
40075569331642446be05292e3e1f8a51218827168cdclaireho    ftl[n] = fr[fi[n]].FeatureTag;
40085569331642446be05292e3e1f8a51218827168cdclaireho  }
40095569331642446be05292e3e1f8a51218827168cdclaireho  ftl[n] = 0;
40105569331642446be05292e3e1f8a51218827168cdclaireho
40115569331642446be05292e3e1f8a51218827168cdclaireho  *feature_tag_list = ftl;
40125569331642446be05292e3e1f8a51218827168cdclaireho
40135569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
40145569331642446be05292e3e1f8a51218827168cdclaireho}
40155569331642446be05292e3e1f8a51218827168cdclaireho
40165569331642446be05292e3e1f8a51218827168cdclaireho
40175569331642446be05292e3e1f8a51218827168cdclaireho/* Do an individual subtable lookup.  Returns HB_Err_Ok if substitution
40185569331642446be05292e3e1f8a51218827168cdclaireho   has been done, or HB_Err_Not_Covered if not.                        */
40195569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  GSUB_Do_Glyph_Lookup( HB_GSUBHeader* gsub,
40205569331642446be05292e3e1f8a51218827168cdclaireho				       HB_UShort       lookup_index,
40215569331642446be05292e3e1f8a51218827168cdclaireho				       HB_Buffer      buffer,
40225569331642446be05292e3e1f8a51218827168cdclaireho				       HB_UShort       context_length,
40235569331642446be05292e3e1f8a51218827168cdclaireho				       int             nesting_level )
40245569331642446be05292e3e1f8a51218827168cdclaireho{
40255569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error               error = HB_Err_Not_Covered;
40265569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort              i, flags, lookup_count;
40275569331642446be05292e3e1f8a51218827168cdclaireho  HB_Lookup*             lo;
40285569331642446be05292e3e1f8a51218827168cdclaireho  int                    lookup_type;
40295569331642446be05292e3e1f8a51218827168cdclaireho
40305569331642446be05292e3e1f8a51218827168cdclaireho  nesting_level++;
40315569331642446be05292e3e1f8a51218827168cdclaireho
40325569331642446be05292e3e1f8a51218827168cdclaireho  if ( nesting_level > HB_MAX_NESTING_LEVEL )
40335569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Not_Covered); /* ERR() call intended */
40345569331642446be05292e3e1f8a51218827168cdclaireho
40355569331642446be05292e3e1f8a51218827168cdclaireho  lookup_count = gsub->LookupList.LookupCount;
40365569331642446be05292e3e1f8a51218827168cdclaireho  if (lookup_index >= lookup_count)
40375569331642446be05292e3e1f8a51218827168cdclaireho    return error;
40385569331642446be05292e3e1f8a51218827168cdclaireho
40395569331642446be05292e3e1f8a51218827168cdclaireho  lo    = &gsub->LookupList.Lookup[lookup_index];
40405569331642446be05292e3e1f8a51218827168cdclaireho  flags = lo->LookupFlag;
40415569331642446be05292e3e1f8a51218827168cdclaireho  lookup_type = lo->LookupType;
40425569331642446be05292e3e1f8a51218827168cdclaireho
40435569331642446be05292e3e1f8a51218827168cdclaireho  for ( i = 0; i < lo->SubTableCount; i++ )
40445569331642446be05292e3e1f8a51218827168cdclaireho  {
40455569331642446be05292e3e1f8a51218827168cdclaireho    HB_GSUB_SubTable *st = &lo->SubTable[i].st.gsub;
40465569331642446be05292e3e1f8a51218827168cdclaireho
40475569331642446be05292e3e1f8a51218827168cdclaireho    switch (lookup_type) {
40485569331642446be05292e3e1f8a51218827168cdclaireho      case HB_GSUB_LOOKUP_SINGLE:
40495569331642446be05292e3e1f8a51218827168cdclaireho	error = Lookup_SingleSubst		( gsub, st, buffer, flags, context_length, nesting_level ); break;
40505569331642446be05292e3e1f8a51218827168cdclaireho      case HB_GSUB_LOOKUP_MULTIPLE:
40515569331642446be05292e3e1f8a51218827168cdclaireho	error = Lookup_MultipleSubst		( gsub, st, buffer, flags, context_length, nesting_level ); break;
40525569331642446be05292e3e1f8a51218827168cdclaireho      case HB_GSUB_LOOKUP_ALTERNATE:
40535569331642446be05292e3e1f8a51218827168cdclaireho	error = Lookup_AlternateSubst		( gsub, st, buffer, flags, context_length, nesting_level ); break;
40545569331642446be05292e3e1f8a51218827168cdclaireho      case HB_GSUB_LOOKUP_LIGATURE:
40555569331642446be05292e3e1f8a51218827168cdclaireho	error = Lookup_LigatureSubst		( gsub, st, buffer, flags, context_length, nesting_level ); break;
40565569331642446be05292e3e1f8a51218827168cdclaireho      case HB_GSUB_LOOKUP_CONTEXT:
40575569331642446be05292e3e1f8a51218827168cdclaireho	error = Lookup_ContextSubst		( gsub, st, buffer, flags, context_length, nesting_level ); break;
40585569331642446be05292e3e1f8a51218827168cdclaireho      case HB_GSUB_LOOKUP_CHAIN:
40595569331642446be05292e3e1f8a51218827168cdclaireho	error = Lookup_ChainContextSubst	( gsub, st, buffer, flags, context_length, nesting_level ); break;
40605569331642446be05292e3e1f8a51218827168cdclaireho    /*case HB_GSUB_LOOKUP_EXTENSION:
40615569331642446be05292e3e1f8a51218827168cdclaireho	error = Lookup_ExtensionSubst		( gsub, st, buffer, flags, context_length, nesting_level ); break;*/
40625569331642446be05292e3e1f8a51218827168cdclaireho      case HB_GSUB_LOOKUP_REVERSE_CHAIN:
40635569331642446be05292e3e1f8a51218827168cdclaireho	error = Lookup_ReverseChainContextSubst	( gsub, st, buffer, flags, context_length, nesting_level ); break;
40645569331642446be05292e3e1f8a51218827168cdclaireho      default:
40655569331642446be05292e3e1f8a51218827168cdclaireho	error = HB_Err_Not_Covered;
40665569331642446be05292e3e1f8a51218827168cdclaireho    };
40675569331642446be05292e3e1f8a51218827168cdclaireho
40685569331642446be05292e3e1f8a51218827168cdclaireho    /* Check whether we have a successful substitution or an error other
40695569331642446be05292e3e1f8a51218827168cdclaireho       than HB_Err_Not_Covered                                          */
40705569331642446be05292e3e1f8a51218827168cdclaireho    if ( error != HB_Err_Not_Covered )
40715569331642446be05292e3e1f8a51218827168cdclaireho      return error;
40725569331642446be05292e3e1f8a51218827168cdclaireho  }
40735569331642446be05292e3e1f8a51218827168cdclaireho
40745569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Not_Covered;
40755569331642446be05292e3e1f8a51218827168cdclaireho}
40765569331642446be05292e3e1f8a51218827168cdclaireho
40775569331642446be05292e3e1f8a51218827168cdclaireho
40785569331642446be05292e3e1f8a51218827168cdclairehoHB_INTERNAL HB_Error
40795569331642446be05292e3e1f8a51218827168cdclaireho_HB_GSUB_Load_SubTable( HB_GSUB_SubTable* st,
40805569331642446be05292e3e1f8a51218827168cdclaireho			HB_Stream         stream,
40815569331642446be05292e3e1f8a51218827168cdclaireho			HB_UShort         lookup_type )
40825569331642446be05292e3e1f8a51218827168cdclaireho{
40835569331642446be05292e3e1f8a51218827168cdclaireho  switch (lookup_type) {
40845569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GSUB_LOOKUP_SINGLE:		return Load_SingleSubst			( st, stream );
40855569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GSUB_LOOKUP_MULTIPLE:	return Load_MultipleSubst		( st, stream );
40865569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GSUB_LOOKUP_ALTERNATE:	return Load_AlternateSubst		( st, stream );
40875569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GSUB_LOOKUP_LIGATURE:	return Load_LigatureSubst		( st, stream );
40885569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GSUB_LOOKUP_CONTEXT:	return Load_ContextSubst		( st, stream );
40895569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GSUB_LOOKUP_CHAIN:		return Load_ChainContextSubst		( st, stream );
40905569331642446be05292e3e1f8a51218827168cdclaireho  /*case HB_GSUB_LOOKUP_EXTENSION:	return Load_ExtensionSubst		( st, stream );*/
40915569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GSUB_LOOKUP_REVERSE_CHAIN:	return Load_ReverseChainContextSubst	( st, stream );
40925569331642446be05292e3e1f8a51218827168cdclaireho    default:				return ERR(HB_Err_Invalid_SubTable_Format);
40935569331642446be05292e3e1f8a51218827168cdclaireho  };
40945569331642446be05292e3e1f8a51218827168cdclaireho}
40955569331642446be05292e3e1f8a51218827168cdclaireho
40965569331642446be05292e3e1f8a51218827168cdclaireho
40975569331642446be05292e3e1f8a51218827168cdclairehoHB_INTERNAL void
40985569331642446be05292e3e1f8a51218827168cdclaireho_HB_GSUB_Free_SubTable( HB_GSUB_SubTable* st,
40995569331642446be05292e3e1f8a51218827168cdclaireho			HB_UShort         lookup_type )
41005569331642446be05292e3e1f8a51218827168cdclaireho{
41015569331642446be05292e3e1f8a51218827168cdclaireho  switch ( lookup_type ) {
41025569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GSUB_LOOKUP_SINGLE:		Free_SingleSubst		( st ); return;
41035569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GSUB_LOOKUP_MULTIPLE:	Free_MultipleSubst		( st ); return;
41045569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GSUB_LOOKUP_ALTERNATE:	Free_AlternateSubst		( st ); return;
41055569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GSUB_LOOKUP_LIGATURE:	Free_LigatureSubst		( st ); return;
41065569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GSUB_LOOKUP_CONTEXT:	Free_ContextSubst		( st ); return;
41075569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GSUB_LOOKUP_CHAIN:		Free_ChainContextSubst		( st ); return;
41085569331642446be05292e3e1f8a51218827168cdclaireho  /*case HB_GSUB_LOOKUP_EXTENSION:	Free_ExtensionSubst		( st ); return;*/
41095569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GSUB_LOOKUP_REVERSE_CHAIN:	Free_ReverseChainContextSubst	( st ); return;
41105569331642446be05292e3e1f8a51218827168cdclaireho    default:									return;
41115569331642446be05292e3e1f8a51218827168cdclaireho  };
41125569331642446be05292e3e1f8a51218827168cdclaireho}
41135569331642446be05292e3e1f8a51218827168cdclaireho
41145569331642446be05292e3e1f8a51218827168cdclaireho
41155569331642446be05292e3e1f8a51218827168cdclaireho
41165569331642446be05292e3e1f8a51218827168cdclaireho/* apply one lookup to the input string object */
41175569331642446be05292e3e1f8a51218827168cdclaireho
41185569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  GSUB_Do_String_Lookup( HB_GSUBHeader*   gsub,
41195569331642446be05292e3e1f8a51218827168cdclaireho				   HB_UShort         lookup_index,
41205569331642446be05292e3e1f8a51218827168cdclaireho				   HB_Buffer        buffer )
41215569331642446be05292e3e1f8a51218827168cdclaireho{
41225569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error, retError = HB_Err_Not_Covered;
41235569331642446be05292e3e1f8a51218827168cdclaireho
41245569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt*  properties = gsub->LookupList.Properties;
41255569331642446be05292e3e1f8a51218827168cdclaireho  int       lookup_type = gsub->LookupList.Lookup[lookup_index].LookupType;
41265569331642446be05292e3e1f8a51218827168cdclaireho
41275569331642446be05292e3e1f8a51218827168cdclaireho  const int       nesting_level = 0;
41285569331642446be05292e3e1f8a51218827168cdclaireho  /* 0xFFFF indicates that we don't have a context length yet */
41295569331642446be05292e3e1f8a51218827168cdclaireho  const HB_UShort context_length = 0xFFFF;
41305569331642446be05292e3e1f8a51218827168cdclaireho
41315569331642446be05292e3e1f8a51218827168cdclaireho  switch (lookup_type) {
41325569331642446be05292e3e1f8a51218827168cdclaireho
41335569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GSUB_LOOKUP_SINGLE:
41345569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GSUB_LOOKUP_MULTIPLE:
41355569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GSUB_LOOKUP_ALTERNATE:
41365569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GSUB_LOOKUP_LIGATURE:
41375569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GSUB_LOOKUP_CONTEXT:
41385569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GSUB_LOOKUP_CHAIN:
41395569331642446be05292e3e1f8a51218827168cdclaireho      /* in/out forward substitution (implemented lazy) */
41405569331642446be05292e3e1f8a51218827168cdclaireho
41415569331642446be05292e3e1f8a51218827168cdclaireho      _hb_buffer_clear_output ( buffer );
41425569331642446be05292e3e1f8a51218827168cdclaireho      buffer->in_pos = 0;
41435569331642446be05292e3e1f8a51218827168cdclaireho  while ( buffer->in_pos < buffer->in_length )
41445569331642446be05292e3e1f8a51218827168cdclaireho  {
41455569331642446be05292e3e1f8a51218827168cdclaireho    if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
41465569331642446be05292e3e1f8a51218827168cdclaireho    {
41475569331642446be05292e3e1f8a51218827168cdclaireho	  error = GSUB_Do_Glyph_Lookup( gsub, lookup_index, buffer, context_length, nesting_level );
41485569331642446be05292e3e1f8a51218827168cdclaireho      if ( error )
41495569331642446be05292e3e1f8a51218827168cdclaireho      {
41505569331642446be05292e3e1f8a51218827168cdclaireho	if ( error != HB_Err_Not_Covered )
41515569331642446be05292e3e1f8a51218827168cdclaireho	  return error;
41525569331642446be05292e3e1f8a51218827168cdclaireho      }
41535569331642446be05292e3e1f8a51218827168cdclaireho      else
41545569331642446be05292e3e1f8a51218827168cdclaireho	retError = error;
41555569331642446be05292e3e1f8a51218827168cdclaireho    }
41565569331642446be05292e3e1f8a51218827168cdclaireho    else
41575569331642446be05292e3e1f8a51218827168cdclaireho      error = HB_Err_Not_Covered;
41585569331642446be05292e3e1f8a51218827168cdclaireho
41595569331642446be05292e3e1f8a51218827168cdclaireho    if ( error == HB_Err_Not_Covered )
41605569331642446be05292e3e1f8a51218827168cdclaireho	  if ( COPY_Glyph ( buffer ) )
41615569331642446be05292e3e1f8a51218827168cdclaireho	return error;
41625569331642446be05292e3e1f8a51218827168cdclaireho  }
41635569331642446be05292e3e1f8a51218827168cdclaireho      /* we shouldn't swap if error occurred.
41645569331642446be05292e3e1f8a51218827168cdclaireho       *
41655569331642446be05292e3e1f8a51218827168cdclaireho       * also don't swap if nothing changed (ie HB_Err_Not_Covered).
41665569331642446be05292e3e1f8a51218827168cdclaireho       * shouldn't matter in that case though.
41675569331642446be05292e3e1f8a51218827168cdclaireho       */
41685569331642446be05292e3e1f8a51218827168cdclaireho      if ( retError == HB_Err_Ok )
41695569331642446be05292e3e1f8a51218827168cdclaireho	_hb_buffer_swap( buffer );
41705569331642446be05292e3e1f8a51218827168cdclaireho
41715569331642446be05292e3e1f8a51218827168cdclaireho  return retError;
41725569331642446be05292e3e1f8a51218827168cdclaireho
41735569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GSUB_LOOKUP_REVERSE_CHAIN:
41745569331642446be05292e3e1f8a51218827168cdclaireho      /* in-place backward substitution */
41755569331642446be05292e3e1f8a51218827168cdclaireho
41765569331642446be05292e3e1f8a51218827168cdclaireho      buffer->in_pos = buffer->in_length - 1;
41775569331642446be05292e3e1f8a51218827168cdclaireho    do
41785569331642446be05292e3e1f8a51218827168cdclaireho    {
41795569331642446be05292e3e1f8a51218827168cdclaireho      if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
41805569331642446be05292e3e1f8a51218827168cdclaireho	{
41815569331642446be05292e3e1f8a51218827168cdclaireho	  error = GSUB_Do_Glyph_Lookup( gsub, lookup_index, buffer, context_length, nesting_level );
41825569331642446be05292e3e1f8a51218827168cdclaireho	  if ( error )
41835569331642446be05292e3e1f8a51218827168cdclaireho	    {
41845569331642446be05292e3e1f8a51218827168cdclaireho	      if ( error != HB_Err_Not_Covered )
41855569331642446be05292e3e1f8a51218827168cdclaireho		return error;
41865569331642446be05292e3e1f8a51218827168cdclaireho	    }
41875569331642446be05292e3e1f8a51218827168cdclaireho	  else
41885569331642446be05292e3e1f8a51218827168cdclaireho	    retError = error;
41895569331642446be05292e3e1f8a51218827168cdclaireho	}
41905569331642446be05292e3e1f8a51218827168cdclaireho	else
41915569331642446be05292e3e1f8a51218827168cdclaireho	  error = HB_Err_Not_Covered;
41925569331642446be05292e3e1f8a51218827168cdclaireho
41935569331642446be05292e3e1f8a51218827168cdclaireho	if ( error == HB_Err_Not_Covered )
41945569331642446be05292e3e1f8a51218827168cdclaireho	  buffer->in_pos--;
41955569331642446be05292e3e1f8a51218827168cdclaireho      }
41965569331642446be05292e3e1f8a51218827168cdclaireho      while ((HB_Int) buffer->in_pos >= 0);
41975569331642446be05292e3e1f8a51218827168cdclaireho
41985569331642446be05292e3e1f8a51218827168cdclaireho      return retError;
41995569331642446be05292e3e1f8a51218827168cdclaireho
42005569331642446be05292e3e1f8a51218827168cdclaireho  /*case HB_GSUB_LOOKUP_EXTENSION:*/
42015569331642446be05292e3e1f8a51218827168cdclaireho    default:
42025569331642446be05292e3e1f8a51218827168cdclaireho  return retError;
42035569331642446be05292e3e1f8a51218827168cdclaireho  };
42045569331642446be05292e3e1f8a51218827168cdclaireho}
42055569331642446be05292e3e1f8a51218827168cdclaireho
42065569331642446be05292e3e1f8a51218827168cdclaireho
42075569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_GSUB_Add_Feature( HB_GSUBHeader*  gsub,
42085569331642446be05292e3e1f8a51218827168cdclaireho			       HB_UShort        feature_index,
42095569331642446be05292e3e1f8a51218827168cdclaireho			       HB_UInt          property )
42105569331642446be05292e3e1f8a51218827168cdclaireho{
42115569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort    i;
42125569331642446be05292e3e1f8a51218827168cdclaireho
42135569331642446be05292e3e1f8a51218827168cdclaireho  HB_Feature  feature;
42145569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt*     properties;
42155569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*   index;
42165569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort    lookup_count;
42175569331642446be05292e3e1f8a51218827168cdclaireho
42185569331642446be05292e3e1f8a51218827168cdclaireho  /* Each feature can only be added once */
42195569331642446be05292e3e1f8a51218827168cdclaireho
42205569331642446be05292e3e1f8a51218827168cdclaireho  if ( !gsub ||
42215569331642446be05292e3e1f8a51218827168cdclaireho       feature_index >= gsub->FeatureList.FeatureCount ||
42225569331642446be05292e3e1f8a51218827168cdclaireho       gsub->FeatureList.ApplyCount == gsub->FeatureList.FeatureCount )
42235569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
42245569331642446be05292e3e1f8a51218827168cdclaireho
42255569331642446be05292e3e1f8a51218827168cdclaireho  gsub->FeatureList.ApplyOrder[gsub->FeatureList.ApplyCount++] = feature_index;
42265569331642446be05292e3e1f8a51218827168cdclaireho
42275569331642446be05292e3e1f8a51218827168cdclaireho  properties = gsub->LookupList.Properties;
42285569331642446be05292e3e1f8a51218827168cdclaireho
42295569331642446be05292e3e1f8a51218827168cdclaireho  feature = gsub->FeatureList.FeatureRecord[feature_index].Feature;
42305569331642446be05292e3e1f8a51218827168cdclaireho  index   = feature.LookupListIndex;
42315569331642446be05292e3e1f8a51218827168cdclaireho  lookup_count = gsub->LookupList.LookupCount;
42325569331642446be05292e3e1f8a51218827168cdclaireho
42335569331642446be05292e3e1f8a51218827168cdclaireho  for ( i = 0; i < feature.LookupListCount; i++ )
42345569331642446be05292e3e1f8a51218827168cdclaireho  {
42355569331642446be05292e3e1f8a51218827168cdclaireho    HB_UShort lookup_index = index[i];
42365569331642446be05292e3e1f8a51218827168cdclaireho    if (lookup_index < lookup_count)
42375569331642446be05292e3e1f8a51218827168cdclaireho      properties[lookup_index] |= property;
42385569331642446be05292e3e1f8a51218827168cdclaireho  }
42395569331642446be05292e3e1f8a51218827168cdclaireho
42405569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
42415569331642446be05292e3e1f8a51218827168cdclaireho}
42425569331642446be05292e3e1f8a51218827168cdclaireho
42435569331642446be05292e3e1f8a51218827168cdclaireho
42445569331642446be05292e3e1f8a51218827168cdclaireho
42455569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_GSUB_Clear_Features( HB_GSUBHeader*  gsub )
42465569331642446be05292e3e1f8a51218827168cdclaireho{
42475569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort i;
42485569331642446be05292e3e1f8a51218827168cdclaireho
42495569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt*  properties;
42505569331642446be05292e3e1f8a51218827168cdclaireho
42515569331642446be05292e3e1f8a51218827168cdclaireho
42525569331642446be05292e3e1f8a51218827168cdclaireho  if ( !gsub )
42535569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
42545569331642446be05292e3e1f8a51218827168cdclaireho
42555569331642446be05292e3e1f8a51218827168cdclaireho  gsub->FeatureList.ApplyCount = 0;
42565569331642446be05292e3e1f8a51218827168cdclaireho
42575569331642446be05292e3e1f8a51218827168cdclaireho  properties = gsub->LookupList.Properties;
42585569331642446be05292e3e1f8a51218827168cdclaireho
42595569331642446be05292e3e1f8a51218827168cdclaireho  for ( i = 0; i < gsub->LookupList.LookupCount; i++ )
42605569331642446be05292e3e1f8a51218827168cdclaireho    properties[i] = 0;
42615569331642446be05292e3e1f8a51218827168cdclaireho
42625569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
42635569331642446be05292e3e1f8a51218827168cdclaireho}
42645569331642446be05292e3e1f8a51218827168cdclaireho
42655569331642446be05292e3e1f8a51218827168cdclaireho
42665569331642446be05292e3e1f8a51218827168cdclaireho
42675569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_GSUB_Register_Alternate_Function( HB_GSUBHeader*  gsub,
42685569331642446be05292e3e1f8a51218827168cdclaireho					       HB_AltFunction  altfunc,
42695569331642446be05292e3e1f8a51218827168cdclaireho					       void*            data )
42705569331642446be05292e3e1f8a51218827168cdclaireho{
42715569331642446be05292e3e1f8a51218827168cdclaireho  if ( !gsub )
42725569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
42735569331642446be05292e3e1f8a51218827168cdclaireho
42745569331642446be05292e3e1f8a51218827168cdclaireho  gsub->altfunc = altfunc;
42755569331642446be05292e3e1f8a51218827168cdclaireho  gsub->data    = data;
42765569331642446be05292e3e1f8a51218827168cdclaireho
42775569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
42785569331642446be05292e3e1f8a51218827168cdclaireho}
42795569331642446be05292e3e1f8a51218827168cdclaireho
42805569331642446be05292e3e1f8a51218827168cdclaireho/* returns error if one happened, otherwise returns HB_Err_Not_Covered if no
42815569331642446be05292e3e1f8a51218827168cdclaireho * feature were applied, or HB_Err_Ok otherwise.
42825569331642446be05292e3e1f8a51218827168cdclaireho */
42835569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_GSUB_Apply_String( HB_GSUBHeader*   gsub,
42845569331642446be05292e3e1f8a51218827168cdclaireho				HB_Buffer        buffer )
42855569331642446be05292e3e1f8a51218827168cdclaireho{
42865569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error          error, retError = HB_Err_Not_Covered;
42875569331642446be05292e3e1f8a51218827168cdclaireho  int               i, j, lookup_count, num_features;
42885569331642446be05292e3e1f8a51218827168cdclaireho
42895569331642446be05292e3e1f8a51218827168cdclaireho  if ( !gsub ||
42905569331642446be05292e3e1f8a51218827168cdclaireho       !buffer)
42915569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
42925569331642446be05292e3e1f8a51218827168cdclaireho
42935569331642446be05292e3e1f8a51218827168cdclaireho  if ( buffer->in_length == 0 )
42945569331642446be05292e3e1f8a51218827168cdclaireho    return retError;
42955569331642446be05292e3e1f8a51218827168cdclaireho
42965569331642446be05292e3e1f8a51218827168cdclaireho  lookup_count = gsub->LookupList.LookupCount;
42975569331642446be05292e3e1f8a51218827168cdclaireho  num_features = gsub->FeatureList.ApplyCount;
42985569331642446be05292e3e1f8a51218827168cdclaireho
42995569331642446be05292e3e1f8a51218827168cdclaireho  for ( i = 0; i < num_features; i++)
43005569331642446be05292e3e1f8a51218827168cdclaireho  {
43015569331642446be05292e3e1f8a51218827168cdclaireho    HB_UShort  feature_index = gsub->FeatureList.ApplyOrder[i];
43025569331642446be05292e3e1f8a51218827168cdclaireho    HB_Feature feature = gsub->FeatureList.FeatureRecord[feature_index].Feature;
43035569331642446be05292e3e1f8a51218827168cdclaireho
43045569331642446be05292e3e1f8a51218827168cdclaireho    for ( j = 0; j < feature.LookupListCount; j++ )
43055569331642446be05292e3e1f8a51218827168cdclaireho    {
43065569331642446be05292e3e1f8a51218827168cdclaireho      HB_UShort         lookup_index = feature.LookupListIndex[j];
43075569331642446be05292e3e1f8a51218827168cdclaireho
43085569331642446be05292e3e1f8a51218827168cdclaireho      /* Skip nonexistant lookups */
43095569331642446be05292e3e1f8a51218827168cdclaireho      if (lookup_index >= lookup_count)
43105569331642446be05292e3e1f8a51218827168cdclaireho       continue;
43115569331642446be05292e3e1f8a51218827168cdclaireho
43125569331642446be05292e3e1f8a51218827168cdclaireho	error = GSUB_Do_String_Lookup( gsub, lookup_index, buffer );
43135569331642446be05292e3e1f8a51218827168cdclaireho      if ( error )
43145569331642446be05292e3e1f8a51218827168cdclaireho      {
43155569331642446be05292e3e1f8a51218827168cdclaireho	if ( error != HB_Err_Not_Covered )
43165569331642446be05292e3e1f8a51218827168cdclaireho	  return error;
43175569331642446be05292e3e1f8a51218827168cdclaireho      }
43185569331642446be05292e3e1f8a51218827168cdclaireho      else
43195569331642446be05292e3e1f8a51218827168cdclaireho	retError = error;
43205569331642446be05292e3e1f8a51218827168cdclaireho    }
43215569331642446be05292e3e1f8a51218827168cdclaireho  }
43225569331642446be05292e3e1f8a51218827168cdclaireho
43235569331642446be05292e3e1f8a51218827168cdclaireho  error = retError;
43245569331642446be05292e3e1f8a51218827168cdclaireho
43255569331642446be05292e3e1f8a51218827168cdclaireho  return error;
43265569331642446be05292e3e1f8a51218827168cdclaireho}
43275569331642446be05292e3e1f8a51218827168cdclaireho
43285569331642446be05292e3e1f8a51218827168cdclaireho
43295569331642446be05292e3e1f8a51218827168cdclaireho/* END */
4330