15469607a00d84a07dc638eda46a87fc90142d64breed@android.com/*
25469607a00d84a07dc638eda46a87fc90142d64breed@android.com * Copyright (C) 1998-2004  David Turner and Werner Lemberg
35469607a00d84a07dc638eda46a87fc90142d64breed@android.com * Copyright (C) 2006  Behdad Esfahbod
45469607a00d84a07dc638eda46a87fc90142d64breed@android.com * Copyright (C) 2007  Red Hat, Inc.
55469607a00d84a07dc638eda46a87fc90142d64breed@android.com *
65469607a00d84a07dc638eda46a87fc90142d64breed@android.com * This is part of HarfBuzz, an OpenType Layout engine library.
75469607a00d84a07dc638eda46a87fc90142d64breed@android.com *
85469607a00d84a07dc638eda46a87fc90142d64breed@android.com * Permission is hereby granted, without written agreement and without
95469607a00d84a07dc638eda46a87fc90142d64breed@android.com * license or royalty fees, to use, copy, modify, and distribute this
105469607a00d84a07dc638eda46a87fc90142d64breed@android.com * software and its documentation for any purpose, provided that the
115469607a00d84a07dc638eda46a87fc90142d64breed@android.com * above copyright notice and the following two paragraphs appear in
125469607a00d84a07dc638eda46a87fc90142d64breed@android.com * all copies of this software.
135469607a00d84a07dc638eda46a87fc90142d64breed@android.com *
145469607a00d84a07dc638eda46a87fc90142d64breed@android.com * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
155469607a00d84a07dc638eda46a87fc90142d64breed@android.com * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
165469607a00d84a07dc638eda46a87fc90142d64breed@android.com * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
175469607a00d84a07dc638eda46a87fc90142d64breed@android.com * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
185469607a00d84a07dc638eda46a87fc90142d64breed@android.com * DAMAGE.
195469607a00d84a07dc638eda46a87fc90142d64breed@android.com *
205469607a00d84a07dc638eda46a87fc90142d64breed@android.com * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
215469607a00d84a07dc638eda46a87fc90142d64breed@android.com * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
225469607a00d84a07dc638eda46a87fc90142d64breed@android.com * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
235469607a00d84a07dc638eda46a87fc90142d64breed@android.com * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
245469607a00d84a07dc638eda46a87fc90142d64breed@android.com * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
255469607a00d84a07dc638eda46a87fc90142d64breed@android.com *
265469607a00d84a07dc638eda46a87fc90142d64breed@android.com * Red Hat Author(s): Behdad Esfahbod
275469607a00d84a07dc638eda46a87fc90142d64breed@android.com */
285469607a00d84a07dc638eda46a87fc90142d64breed@android.com
295469607a00d84a07dc638eda46a87fc90142d64breed@android.com#include "harfbuzz-impl.h"
305469607a00d84a07dc638eda46a87fc90142d64breed@android.com#include "harfbuzz-gsub-private.h"
315469607a00d84a07dc638eda46a87fc90142d64breed@android.com#include "harfbuzz-open-private.h"
325469607a00d84a07dc638eda46a87fc90142d64breed@android.com#include "harfbuzz-gdef-private.h"
335469607a00d84a07dc638eda46a87fc90142d64breed@android.com
345469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  GSUB_Do_Glyph_Lookup( HB_GSUBHeader*   gsub,
355469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_UShort         lookup_index,
365469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_Buffer        buffer,
375469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_UShort         context_length,
385469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       int               nesting_level );
395469607a00d84a07dc638eda46a87fc90142d64breed@android.com
405469607a00d84a07dc638eda46a87fc90142d64breed@android.com
415469607a00d84a07dc638eda46a87fc90142d64breed@android.com
425469607a00d84a07dc638eda46a87fc90142d64breed@android.com/**********************
435469607a00d84a07dc638eda46a87fc90142d64breed@android.com * Auxiliary functions
445469607a00d84a07dc638eda46a87fc90142d64breed@android.com **********************/
455469607a00d84a07dc638eda46a87fc90142d64breed@android.com
465469607a00d84a07dc638eda46a87fc90142d64breed@android.com
475469607a00d84a07dc638eda46a87fc90142d64breed@android.com
485469607a00d84a07dc638eda46a87fc90142d64breed@android.comHB_Error  HB_Load_GSUB_Table( HB_Stream stream,
495469607a00d84a07dc638eda46a87fc90142d64breed@android.com			      HB_GSUBHeader** retptr,
505469607a00d84a07dc638eda46a87fc90142d64breed@android.com			      HB_GDEFHeader*  gdef,
515469607a00d84a07dc638eda46a87fc90142d64breed@android.com                              HB_Stream       gdefStream )
525469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
535469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error         error;
545469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt         cur_offset, new_offset, base_offset;
555469607a00d84a07dc638eda46a87fc90142d64breed@android.com
565469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_GSUBHeader*  gsub;
575469607a00d84a07dc638eda46a87fc90142d64breed@android.com
585469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( !retptr )
595469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return ERR(HB_Err_Invalid_Argument);
605469607a00d84a07dc638eda46a87fc90142d64breed@android.com
615469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( GOTO_Table( TTAG_GSUB ) )
625469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
635469607a00d84a07dc638eda46a87fc90142d64breed@android.com
645469607a00d84a07dc638eda46a87fc90142d64breed@android.com  base_offset = FILE_Pos();
655469607a00d84a07dc638eda46a87fc90142d64breed@android.com
665469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC ( gsub, sizeof( *gsub ) ) )
675469607a00d84a07dc638eda46a87fc90142d64breed@android.com      return error;
685469607a00d84a07dc638eda46a87fc90142d64breed@android.com
695469607a00d84a07dc638eda46a87fc90142d64breed@android.com
705469607a00d84a07dc638eda46a87fc90142d64breed@android.com  /* skip version */
715469607a00d84a07dc638eda46a87fc90142d64breed@android.com
725469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( FILE_Seek( base_offset + 4L ) ||
735469607a00d84a07dc638eda46a87fc90142d64breed@android.com       ACCESS_Frame( 2L ) )
745469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail4;
755469607a00d84a07dc638eda46a87fc90142d64breed@android.com
765469607a00d84a07dc638eda46a87fc90142d64breed@android.com  new_offset = GET_UShort() + base_offset;
775469607a00d84a07dc638eda46a87fc90142d64breed@android.com
785469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
795469607a00d84a07dc638eda46a87fc90142d64breed@android.com
805469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cur_offset = FILE_Pos();
815469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( FILE_Seek( new_offset ) ||
825469607a00d84a07dc638eda46a87fc90142d64breed@android.com       ( error = _HB_OPEN_Load_ScriptList( &gsub->ScriptList,
835469607a00d84a07dc638eda46a87fc90142d64breed@android.com				  stream ) ) != HB_Err_Ok )
845469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail4;
855469607a00d84a07dc638eda46a87fc90142d64breed@android.com  (void)FILE_Seek( cur_offset );
865469607a00d84a07dc638eda46a87fc90142d64breed@android.com
875469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
885469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail3;
895469607a00d84a07dc638eda46a87fc90142d64breed@android.com
905469607a00d84a07dc638eda46a87fc90142d64breed@android.com  new_offset = GET_UShort() + base_offset;
915469607a00d84a07dc638eda46a87fc90142d64breed@android.com
925469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
935469607a00d84a07dc638eda46a87fc90142d64breed@android.com
945469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cur_offset = FILE_Pos();
955469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( FILE_Seek( new_offset ) ||
965469607a00d84a07dc638eda46a87fc90142d64breed@android.com       ( error = _HB_OPEN_Load_FeatureList( &gsub->FeatureList,
975469607a00d84a07dc638eda46a87fc90142d64breed@android.com				   stream ) ) != HB_Err_Ok )
985469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail3;
995469607a00d84a07dc638eda46a87fc90142d64breed@android.com  (void)FILE_Seek( cur_offset );
1005469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1015469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
1025469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
1035469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1045469607a00d84a07dc638eda46a87fc90142d64breed@android.com  new_offset = GET_UShort() + base_offset;
1055469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1065469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
1075469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1085469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cur_offset = FILE_Pos();
1095469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( FILE_Seek( new_offset ) ||
1105469607a00d84a07dc638eda46a87fc90142d64breed@android.com       ( error = _HB_OPEN_Load_LookupList( &gsub->LookupList,
1115469607a00d84a07dc638eda46a87fc90142d64breed@android.com				  stream, HB_Type_GSUB ) ) != HB_Err_Ok )
1125469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
1135469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1145469607a00d84a07dc638eda46a87fc90142d64breed@android.com  gsub->gdef = gdef;      /* can be NULL */
1155469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1165469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ( error =  _HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( gdef, gdefStream,
1175469607a00d84a07dc638eda46a87fc90142d64breed@android.com								     gsub->LookupList.Lookup,
1185469607a00d84a07dc638eda46a87fc90142d64breed@android.com								     gsub->LookupList.LookupCount ) ) )
1195469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail1;
1205469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1215469607a00d84a07dc638eda46a87fc90142d64breed@android.com  *retptr = gsub;
1225469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1235469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
1245469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1255469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail1:
1265469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_LookupList( &gsub->LookupList, HB_Type_GSUB );
1275469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1285469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail2:
1295469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_FeatureList( &gsub->FeatureList );
1305469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1315469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail3:
1325469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_ScriptList( &gsub->ScriptList );
1335469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1345469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail4:
1355469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE ( gsub );
1365469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1375469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1385469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
1395469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
1405469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1415469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1425469607a00d84a07dc638eda46a87fc90142d64breed@android.comHB_Error   HB_Done_GSUB_Table( HB_GSUBHeader* gsub )
1435469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
1445469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_LookupList( &gsub->LookupList, HB_Type_GSUB );
1455469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_FeatureList( &gsub->FeatureList );
1465469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_ScriptList( &gsub->ScriptList );
1475469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1485469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( gsub );
1495469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1505469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
1515469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
1525469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1535469607a00d84a07dc638eda46a87fc90142d64breed@android.com/*****************************
1545469607a00d84a07dc638eda46a87fc90142d64breed@android.com * SubTable related functions
1555469607a00d84a07dc638eda46a87fc90142d64breed@android.com *****************************/
1565469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1575469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1585469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* LookupType 1 */
1595469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1605469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* SingleSubstFormat1 */
1615469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* SingleSubstFormat2 */
1625469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1635469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_SingleSubst( HB_GSUB_SubTable* st,
1645469607a00d84a07dc638eda46a87fc90142d64breed@android.com				   HB_Stream         stream )
1655469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
1665469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
1675469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_SingleSubst*  ss = &st->single;
1685469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1695469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort n, count;
1705469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt cur_offset, new_offset, base_offset;
1715469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1725469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*  s;
1735469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1745469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1755469607a00d84a07dc638eda46a87fc90142d64breed@android.com  base_offset = FILE_Pos();
1765469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1775469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 4L ) )
1785469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
1795469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1805469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ss->SubstFormat = GET_UShort();
1815469607a00d84a07dc638eda46a87fc90142d64breed@android.com  new_offset      = GET_UShort() + base_offset;
1825469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1835469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
1845469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1855469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cur_offset = FILE_Pos();
1865469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( FILE_Seek( new_offset ) ||
1875469607a00d84a07dc638eda46a87fc90142d64breed@android.com       ( error = _HB_OPEN_Load_Coverage( &ss->Coverage, stream ) ) != HB_Err_Ok )
1885469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
1895469607a00d84a07dc638eda46a87fc90142d64breed@android.com  (void)FILE_Seek( cur_offset );
1905469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1915469607a00d84a07dc638eda46a87fc90142d64breed@android.com  switch ( ss->SubstFormat )
1925469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
1935469607a00d84a07dc638eda46a87fc90142d64breed@android.com  case 1:
1945469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ACCESS_Frame( 2L ) )
1955469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail2;
1965469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1975469607a00d84a07dc638eda46a87fc90142d64breed@android.com    ss->ssf.ssf1.DeltaGlyphID = GET_UShort();
1985469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1995469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FORGET_Frame();
2005469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2015469607a00d84a07dc638eda46a87fc90142d64breed@android.com    break;
2025469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2035469607a00d84a07dc638eda46a87fc90142d64breed@android.com  case 2:
2045469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ACCESS_Frame( 2L ) )
2055469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail2;
2065469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2075469607a00d84a07dc638eda46a87fc90142d64breed@android.com    count = ss->ssf.ssf2.GlyphCount = GET_UShort();
2085469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2095469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FORGET_Frame();
2105469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2115469607a00d84a07dc638eda46a87fc90142d64breed@android.com    ss->ssf.ssf2.Substitute = NULL;
2125469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2135469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ALLOC_ARRAY( ss->ssf.ssf2.Substitute, count, HB_UShort ) )
2145469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail2;
2155469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2165469607a00d84a07dc638eda46a87fc90142d64breed@android.com    s = ss->ssf.ssf2.Substitute;
2175469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2185469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ACCESS_Frame( count * 2L ) )
2195469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail1;
2205469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2215469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( n = 0; n < count; n++ )
2225469607a00d84a07dc638eda46a87fc90142d64breed@android.com      s[n] = GET_UShort();
2235469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2245469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FORGET_Frame();
2255469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2265469607a00d84a07dc638eda46a87fc90142d64breed@android.com    break;
2275469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2285469607a00d84a07dc638eda46a87fc90142d64breed@android.com  default:
2295469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return ERR(HB_Err_Invalid_SubTable_Format);
2305469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
2315469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2325469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
2335469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2345469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail1:
2355469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( s );
2365469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2375469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail2:
2385469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_Coverage( &ss->Coverage );
2395469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
2405469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
2415469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2425469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2435469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_SingleSubst( HB_GSUB_SubTable* st )
2445469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
2455469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_SingleSubst*  ss = &st->single;
2465469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2475469607a00d84a07dc638eda46a87fc90142d64breed@android.com  switch ( ss->SubstFormat )
2485469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
2495469607a00d84a07dc638eda46a87fc90142d64breed@android.com  case 1:
2505469607a00d84a07dc638eda46a87fc90142d64breed@android.com    break;
2515469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2525469607a00d84a07dc638eda46a87fc90142d64breed@android.com  case 2:
2535469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FREE( ss->ssf.ssf2.Substitute );
2545469607a00d84a07dc638eda46a87fc90142d64breed@android.com    break;
2555469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2565469607a00d84a07dc638eda46a87fc90142d64breed@android.com  default:
2575469607a00d84a07dc638eda46a87fc90142d64breed@android.com    break;
2585469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
2595469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2605469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_Coverage( &ss->Coverage );
2615469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
2625469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2635469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2645469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Lookup_SingleSubst( HB_GSUBHeader*   gsub,
2655469607a00d84a07dc638eda46a87fc90142d64breed@android.com				     HB_GSUB_SubTable* st,
2665469607a00d84a07dc638eda46a87fc90142d64breed@android.com				     HB_Buffer        buffer,
2675469607a00d84a07dc638eda46a87fc90142d64breed@android.com				     HB_UShort         flags,
2685469607a00d84a07dc638eda46a87fc90142d64breed@android.com				     HB_UShort         context_length,
2695469607a00d84a07dc638eda46a87fc90142d64breed@android.com				     int               nesting_level )
2705469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
2715469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort index, value, property;
2725469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error  error;
2735469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_SingleSubst*  ss = &st->single;
2745469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_GDEFHeader*   gdef = gsub->gdef;
2755469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2765469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UNUSED(nesting_level);
2775469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2785469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( context_length != 0xFFFF && context_length < 1 )
2795469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return HB_Err_Not_Covered;
2805469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2815469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
2825469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
2835469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2845469607a00d84a07dc638eda46a87fc90142d64breed@android.com  error = _HB_OPEN_Coverage_Index( &ss->Coverage, IN_CURGLYPH(), &index );
2855469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( error )
2865469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
2875469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2885469607a00d84a07dc638eda46a87fc90142d64breed@android.com  switch ( ss->SubstFormat )
2895469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
2905469607a00d84a07dc638eda46a87fc90142d64breed@android.com  case 1:
2915469607a00d84a07dc638eda46a87fc90142d64breed@android.com    value = ( IN_CURGLYPH() + ss->ssf.ssf1.DeltaGlyphID ) & 0xFFFF;
2925469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( REPLACE_Glyph( buffer, value, nesting_level ) )
2935469607a00d84a07dc638eda46a87fc90142d64breed@android.com      return error;
2945469607a00d84a07dc638eda46a87fc90142d64breed@android.com    break;
2955469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2965469607a00d84a07dc638eda46a87fc90142d64breed@android.com  case 2:
2975469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( index >= ss->ssf.ssf2.GlyphCount )
2985469607a00d84a07dc638eda46a87fc90142d64breed@android.com      return ERR(HB_Err_Invalid_SubTable);
2995469607a00d84a07dc638eda46a87fc90142d64breed@android.com    value = ss->ssf.ssf2.Substitute[index];
3005469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( REPLACE_Glyph( buffer, value, nesting_level ) )
3015469607a00d84a07dc638eda46a87fc90142d64breed@android.com      return error;
3025469607a00d84a07dc638eda46a87fc90142d64breed@android.com    break;
3035469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3045469607a00d84a07dc638eda46a87fc90142d64breed@android.com  default:
3055469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return ERR(HB_Err_Invalid_SubTable);
3065469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
3075469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3085469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( gdef && gdef->NewGlyphClasses )
3095469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
3105469607a00d84a07dc638eda46a87fc90142d64breed@android.com    /* we inherit the old glyph class to the substituted glyph */
3115469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3125469607a00d84a07dc638eda46a87fc90142d64breed@android.com    error = _HB_GDEF_Add_Glyph_Property( gdef, value, property );
3135469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( error && error != HB_Err_Not_Covered )
3145469607a00d84a07dc638eda46a87fc90142d64breed@android.com      return error;
3155469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
3165469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3175469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
3185469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
3195469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3205469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3215469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* LookupType 2 */
3225469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3235469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* Sequence */
3245469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3255469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_Sequence( HB_Sequence*  s,
3265469607a00d84a07dc638eda46a87fc90142d64breed@android.com				HB_Stream      stream )
3275469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
3285469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
3295469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3305469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort n, count;
3315469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*  sub;
3325469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3335469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3345469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
3355469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
3365469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3375469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = s->GlyphCount = GET_UShort();
3385469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3395469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
3405469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3415469607a00d84a07dc638eda46a87fc90142d64breed@android.com  s->Substitute = NULL;
3425469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3435469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( count )
3445469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
3455469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ALLOC_ARRAY( s->Substitute, count, HB_UShort ) )
3465469607a00d84a07dc638eda46a87fc90142d64breed@android.com      return error;
3475469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3485469607a00d84a07dc638eda46a87fc90142d64breed@android.com    sub = s->Substitute;
3495469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3505469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ACCESS_Frame( count * 2L ) )
3515469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
3525469607a00d84a07dc638eda46a87fc90142d64breed@android.com      FREE( sub );
3535469607a00d84a07dc638eda46a87fc90142d64breed@android.com      return error;
3545469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
3555469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3565469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( n = 0; n < count; n++ )
3575469607a00d84a07dc638eda46a87fc90142d64breed@android.com      sub[n] = GET_UShort();
3585469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3595469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FORGET_Frame();
3605469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
3615469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3625469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
3635469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
3645469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3655469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3665469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_Sequence( HB_Sequence*  s )
3675469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
3685469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( s->Substitute );
3695469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
3705469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3715469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3725469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* MultipleSubstFormat1 */
3735469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3745469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_MultipleSubst( HB_GSUB_SubTable* st,
3755469607a00d84a07dc638eda46a87fc90142d64breed@android.com				     HB_Stream         stream )
3765469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
3775469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
3785469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_MultipleSubst*  ms = &st->multiple;
3795469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3805469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort      n = 0, m, count;
3815469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt       cur_offset, new_offset, base_offset;
3825469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3835469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Sequence*  s;
3845469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3855469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3865469607a00d84a07dc638eda46a87fc90142d64breed@android.com  base_offset = FILE_Pos();
3875469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3885469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 4L ) )
3895469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
3905469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3915469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ms->SubstFormat = GET_UShort();             /* should be 1 */
3925469607a00d84a07dc638eda46a87fc90142d64breed@android.com  new_offset      = GET_UShort() + base_offset;
3935469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3945469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
3955469607a00d84a07dc638eda46a87fc90142d64breed@android.com
3965469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cur_offset = FILE_Pos();
3975469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( FILE_Seek( new_offset ) ||
3985469607a00d84a07dc638eda46a87fc90142d64breed@android.com       ( error = _HB_OPEN_Load_Coverage( &ms->Coverage, stream ) ) != HB_Err_Ok )
3995469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
4005469607a00d84a07dc638eda46a87fc90142d64breed@android.com  (void)FILE_Seek( cur_offset );
4015469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4025469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
4035469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
4045469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4055469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = ms->SequenceCount = GET_UShort();
4065469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4075469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
4085469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4095469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ms->Sequence = NULL;
4105469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4115469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( ms->Sequence, count, HB_Sequence ) )
4125469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
4135469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4145469607a00d84a07dc638eda46a87fc90142d64breed@android.com  s = ms->Sequence;
4155469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4165469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
4175469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
4185469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ACCESS_Frame( 2L ) )
4195469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail1;
4205469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4215469607a00d84a07dc638eda46a87fc90142d64breed@android.com    new_offset = GET_UShort() + base_offset;
4225469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4235469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FORGET_Frame();
4245469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4255469607a00d84a07dc638eda46a87fc90142d64breed@android.com    cur_offset = FILE_Pos();
4265469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( FILE_Seek( new_offset ) ||
4275469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 ( error = Load_Sequence( &s[n], stream ) ) != HB_Err_Ok )
4285469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail1;
4295469607a00d84a07dc638eda46a87fc90142d64breed@android.com    (void)FILE_Seek( cur_offset );
4305469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
4315469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4325469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
4335469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4345469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail1:
4355469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( m = 0; m < n; m++ )
4365469607a00d84a07dc638eda46a87fc90142d64breed@android.com    Free_Sequence( &s[m] );
4375469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4385469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( s );
4395469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4405469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail2:
4415469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_Coverage( &ms->Coverage );
4425469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
4435469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
4445469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4455469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4465469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_MultipleSubst( HB_GSUB_SubTable* st )
4475469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
4485469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort      n, count;
4495469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_MultipleSubst*  ms = &st->multiple;
4505469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4515469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Sequence*  s;
4525469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4535469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4545469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ms->Sequence )
4555469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
4565469607a00d84a07dc638eda46a87fc90142d64breed@android.com    count = ms->SequenceCount;
4575469607a00d84a07dc638eda46a87fc90142d64breed@android.com    s     = ms->Sequence;
4585469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4595469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( n = 0; n < count; n++ )
4605469607a00d84a07dc638eda46a87fc90142d64breed@android.com      Free_Sequence( &s[n] );
4615469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4625469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FREE( s );
4635469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
4645469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4655469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_Coverage( &ms->Coverage );
4665469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
4675469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4685469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4695469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Lookup_MultipleSubst( HB_GSUBHeader*    gsub,
4705469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_GSUB_SubTable* st,
4715469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_Buffer         buffer,
4725469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_UShort          flags,
4735469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_UShort          context_length,
4745469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       int                nesting_level )
4755469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
4765469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error  error;
4775469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort index, property, n, count;
4785469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*s;
4795469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_MultipleSubst*  ms = &st->multiple;
4805469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_GDEFHeader*     gdef = gsub->gdef;
4815469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4825469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UNUSED(nesting_level);
4835469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4845469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( context_length != 0xFFFF && context_length < 1 )
4855469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return HB_Err_Not_Covered;
4865469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4875469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
4885469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
4895469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4905469607a00d84a07dc638eda46a87fc90142d64breed@android.com  error = _HB_OPEN_Coverage_Index( &ms->Coverage, IN_CURGLYPH(), &index );
4915469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( error )
4925469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
4935469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4945469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( index >= ms->SequenceCount )
4955469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return ERR(HB_Err_Invalid_SubTable);
4965469607a00d84a07dc638eda46a87fc90142d64breed@android.com
4975469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = ms->Sequence[index].GlyphCount;
4985469607a00d84a07dc638eda46a87fc90142d64breed@android.com  s     = ms->Sequence[index].Substitute;
4995469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5005469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ADD_String( buffer, 1, count, s, 0xFFFF, 0xFFFF ) )
5015469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
5025469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5035469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( gdef && gdef->NewGlyphClasses )
5045469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
5055469607a00d84a07dc638eda46a87fc90142d64breed@android.com    /* this is a guess only ... */
5065469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5075469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( property == HB_GDEF_LIGATURE )
5085469607a00d84a07dc638eda46a87fc90142d64breed@android.com      property = HB_GDEF_BASE_GLYPH;
5095469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5105469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( n = 0; n < count; n++ )
5115469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
5125469607a00d84a07dc638eda46a87fc90142d64breed@android.com      error = _HB_GDEF_Add_Glyph_Property( gdef, s[n], property );
5135469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( error && error != HB_Err_Not_Covered )
5145469607a00d84a07dc638eda46a87fc90142d64breed@android.com	return error;
5155469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
5165469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
5175469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5185469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
5195469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
5205469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5215469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5225469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* LookupType 3 */
5235469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5245469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* AlternateSet */
5255469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5265469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_AlternateSet( HB_AlternateSet*  as,
5275469607a00d84a07dc638eda46a87fc90142d64breed@android.com				    HB_Stream          stream )
5285469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
5295469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
5305469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5315469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort n, count;
5325469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*  a;
5335469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5345469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5355469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
5365469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
5375469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5385469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = as->GlyphCount = GET_UShort();
5395469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5405469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
5415469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5425469607a00d84a07dc638eda46a87fc90142d64breed@android.com  as->Alternate = NULL;
5435469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5445469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( as->Alternate, count, HB_UShort ) )
5455469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
5465469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5475469607a00d84a07dc638eda46a87fc90142d64breed@android.com  a = as->Alternate;
5485469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5495469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( count * 2L ) )
5505469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
5515469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FREE( a );
5525469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
5535469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
5545469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5555469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
5565469607a00d84a07dc638eda46a87fc90142d64breed@android.com    a[n] = GET_UShort();
5575469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5585469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
5595469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5605469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
5615469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
5625469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5635469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5645469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_AlternateSet( HB_AlternateSet*  as )
5655469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
5665469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( as->Alternate );
5675469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
5685469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5695469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5705469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* AlternateSubstFormat1 */
5715469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5725469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_AlternateSubst( HB_GSUB_SubTable* st,
5735469607a00d84a07dc638eda46a87fc90142d64breed@android.com				      HB_Stream         stream )
5745469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
5755469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
5765469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_AlternateSubst* as = &st->alternate;
5775469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5785469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort          n = 0, m, count;
5795469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt           cur_offset, new_offset, base_offset;
5805469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5815469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_AlternateSet*  aset;
5825469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5835469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5845469607a00d84a07dc638eda46a87fc90142d64breed@android.com  base_offset = FILE_Pos();
5855469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5865469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 4L ) )
5875469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
5885469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5895469607a00d84a07dc638eda46a87fc90142d64breed@android.com  as->SubstFormat = GET_UShort();             /* should be 1 */
5905469607a00d84a07dc638eda46a87fc90142d64breed@android.com  new_offset      = GET_UShort() + base_offset;
5915469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5925469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
5935469607a00d84a07dc638eda46a87fc90142d64breed@android.com
5945469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cur_offset = FILE_Pos();
5955469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( FILE_Seek( new_offset ) ||
5965469607a00d84a07dc638eda46a87fc90142d64breed@android.com       ( error = _HB_OPEN_Load_Coverage( &as->Coverage, stream ) ) != HB_Err_Ok )
5975469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
5985469607a00d84a07dc638eda46a87fc90142d64breed@android.com  (void)FILE_Seek( cur_offset );
5995469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6005469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
6015469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
6025469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6035469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = as->AlternateSetCount = GET_UShort();
6045469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6055469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
6065469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6075469607a00d84a07dc638eda46a87fc90142d64breed@android.com  as->AlternateSet = NULL;
6085469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6095469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( as->AlternateSet, count, HB_AlternateSet ) )
6105469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
6115469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6125469607a00d84a07dc638eda46a87fc90142d64breed@android.com  aset = as->AlternateSet;
6135469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6145469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
6155469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
6165469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ACCESS_Frame( 2L ) )
6175469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail1;
6185469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6195469607a00d84a07dc638eda46a87fc90142d64breed@android.com    new_offset = GET_UShort() + base_offset;
6205469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6215469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FORGET_Frame();
6225469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6235469607a00d84a07dc638eda46a87fc90142d64breed@android.com    cur_offset = FILE_Pos();
6245469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( FILE_Seek( new_offset ) ||
6255469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 ( error = Load_AlternateSet( &aset[n], stream ) ) != HB_Err_Ok )
6265469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail1;
6275469607a00d84a07dc638eda46a87fc90142d64breed@android.com    (void)FILE_Seek( cur_offset );
6285469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
6295469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6305469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
6315469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6325469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail1:
6335469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( m = 0; m < n; m++ )
6345469607a00d84a07dc638eda46a87fc90142d64breed@android.com    Free_AlternateSet( &aset[m] );
6355469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6365469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( aset );
6375469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6385469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail2:
6395469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_Coverage( &as->Coverage );
6405469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
6415469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
6425469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6435469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6445469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_AlternateSubst( HB_GSUB_SubTable* st )
6455469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
6465469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort          n, count;
6475469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_AlternateSubst* as = &st->alternate;
6485469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6495469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_AlternateSet*  aset;
6505469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6515469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6525469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( as->AlternateSet )
6535469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
6545469607a00d84a07dc638eda46a87fc90142d64breed@android.com    count = as->AlternateSetCount;
6555469607a00d84a07dc638eda46a87fc90142d64breed@android.com    aset  = as->AlternateSet;
6565469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6575469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( n = 0; n < count; n++ )
6585469607a00d84a07dc638eda46a87fc90142d64breed@android.com      Free_AlternateSet( &aset[n] );
6595469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6605469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FREE( aset );
6615469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
6625469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6635469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_Coverage( &as->Coverage );
6645469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
6655469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6665469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6675469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Lookup_AlternateSubst( HB_GSUBHeader*    gsub,
6685469607a00d84a07dc638eda46a87fc90142d64breed@android.com					HB_GSUB_SubTable* st,
6695469607a00d84a07dc638eda46a87fc90142d64breed@android.com					HB_Buffer         buffer,
6705469607a00d84a07dc638eda46a87fc90142d64breed@android.com					HB_UShort          flags,
6715469607a00d84a07dc638eda46a87fc90142d64breed@android.com					HB_UShort          context_length,
6725469607a00d84a07dc638eda46a87fc90142d64breed@android.com					int                nesting_level )
6735469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
6745469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error          error;
6755469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort         index, value, alt_index, property;
6765469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_AlternateSubst* as = &st->alternate;
6775469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_GDEFHeader*     gdef = gsub->gdef;
6785469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_AlternateSet  aset;
6795469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6805469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UNUSED(nesting_level);
6815469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6825469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( context_length != 0xFFFF && context_length < 1 )
6835469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return HB_Err_Not_Covered;
6845469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6855469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
6865469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
6875469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6885469607a00d84a07dc638eda46a87fc90142d64breed@android.com  error = _HB_OPEN_Coverage_Index( &as->Coverage, IN_CURGLYPH(), &index );
6895469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( error )
6905469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
6915469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6925469607a00d84a07dc638eda46a87fc90142d64breed@android.com  aset = as->AlternateSet[index];
6935469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6945469607a00d84a07dc638eda46a87fc90142d64breed@android.com  /* we use a user-defined callback function to get the alternate index */
6955469607a00d84a07dc638eda46a87fc90142d64breed@android.com
6965469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( gsub->altfunc )
6975469607a00d84a07dc638eda46a87fc90142d64breed@android.com    alt_index = (gsub->altfunc)( buffer->out_pos, IN_CURGLYPH(),
6985469607a00d84a07dc638eda46a87fc90142d64breed@android.com				 aset.GlyphCount, aset.Alternate,
6995469607a00d84a07dc638eda46a87fc90142d64breed@android.com				 gsub->data );
7005469607a00d84a07dc638eda46a87fc90142d64breed@android.com  else
7015469607a00d84a07dc638eda46a87fc90142d64breed@android.com    alt_index = 0;
7025469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7035469607a00d84a07dc638eda46a87fc90142d64breed@android.com  value = aset.Alternate[alt_index];
7045469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( REPLACE_Glyph( buffer, value, nesting_level ) )
7055469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
7065469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7075469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( gdef && gdef->NewGlyphClasses )
7085469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
7095469607a00d84a07dc638eda46a87fc90142d64breed@android.com    /* we inherit the old glyph class to the substituted glyph */
7105469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7115469607a00d84a07dc638eda46a87fc90142d64breed@android.com    error = _HB_GDEF_Add_Glyph_Property( gdef, value, property );
7125469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( error && error != HB_Err_Not_Covered )
7135469607a00d84a07dc638eda46a87fc90142d64breed@android.com      return error;
7145469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
7155469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7165469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
7175469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
7185469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7195469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7205469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* LookupType 4 */
7215469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7225469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* Ligature */
7235469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7245469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_Ligature( HB_Ligature*  l,
7255469607a00d84a07dc638eda46a87fc90142d64breed@android.com				HB_Stream      stream )
7265469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
7275469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
7285469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7295469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort n, count;
7305469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*  c;
7315469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7325469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7335469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 4L ) )
7345469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
7355469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7365469607a00d84a07dc638eda46a87fc90142d64breed@android.com  l->LigGlyph       = GET_UShort();
7375469607a00d84a07dc638eda46a87fc90142d64breed@android.com  l->ComponentCount = GET_UShort();
7385469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7395469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
7405469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7415469607a00d84a07dc638eda46a87fc90142d64breed@android.com  l->Component = NULL;
7425469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7435469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = l->ComponentCount - 1;      /* only ComponentCount - 1 elements */
7445469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7455469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( l->Component, count, HB_UShort ) )
7465469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
7475469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7485469607a00d84a07dc638eda46a87fc90142d64breed@android.com  c = l->Component;
7495469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7505469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( count * 2L ) )
7515469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
7525469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FREE( c );
7535469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
7545469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
7555469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7565469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
7575469607a00d84a07dc638eda46a87fc90142d64breed@android.com    c[n] = GET_UShort();
7585469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7595469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
7605469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7615469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
7625469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
7635469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7645469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7655469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_Ligature( HB_Ligature*  l )
7665469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
7675469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( l->Component );
7685469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
7695469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7705469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7715469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* LigatureSet */
7725469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7735469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_LigatureSet( HB_LigatureSet*  ls,
7745469607a00d84a07dc638eda46a87fc90142d64breed@android.com				   HB_Stream         stream )
7755469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
7765469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
7775469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7785469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort      n = 0, m, count;
7795469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt       cur_offset, new_offset, base_offset;
7805469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7815469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Ligature*  l;
7825469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7835469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7845469607a00d84a07dc638eda46a87fc90142d64breed@android.com  base_offset = FILE_Pos();
7855469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7865469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
7875469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
7885469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7895469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = ls->LigatureCount = GET_UShort();
7905469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7915469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
7925469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7935469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ls->Ligature = NULL;
7945469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7955469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( ls->Ligature, count, HB_Ligature ) )
7965469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
7975469607a00d84a07dc638eda46a87fc90142d64breed@android.com
7985469607a00d84a07dc638eda46a87fc90142d64breed@android.com  l = ls->Ligature;
7995469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8005469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
8015469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
8025469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ACCESS_Frame( 2L ) )
8035469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail;
8045469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8055469607a00d84a07dc638eda46a87fc90142d64breed@android.com    new_offset = GET_UShort() + base_offset;
8065469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8075469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FORGET_Frame();
8085469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8095469607a00d84a07dc638eda46a87fc90142d64breed@android.com    cur_offset = FILE_Pos();
8105469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( FILE_Seek( new_offset ) ||
8115469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 ( error = Load_Ligature( &l[n], stream ) ) != HB_Err_Ok )
8125469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail;
8135469607a00d84a07dc638eda46a87fc90142d64breed@android.com    (void)FILE_Seek( cur_offset );
8145469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
8155469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8165469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
8175469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8185469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail:
8195469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( m = 0; m < n; m++ )
8205469607a00d84a07dc638eda46a87fc90142d64breed@android.com    Free_Ligature( &l[m] );
8215469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8225469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( l );
8235469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
8245469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
8255469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8265469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8275469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_LigatureSet( HB_LigatureSet*  ls )
8285469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
8295469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort      n, count;
8305469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8315469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Ligature*  l;
8325469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8335469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8345469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ls->Ligature )
8355469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
8365469607a00d84a07dc638eda46a87fc90142d64breed@android.com    count = ls->LigatureCount;
8375469607a00d84a07dc638eda46a87fc90142d64breed@android.com    l     = ls->Ligature;
8385469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8395469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( n = 0; n < count; n++ )
8405469607a00d84a07dc638eda46a87fc90142d64breed@android.com      Free_Ligature( &l[n] );
8415469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8425469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FREE( l );
8435469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
8445469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
8455469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8465469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8475469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* LigatureSubstFormat1 */
8485469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8495469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_LigatureSubst( HB_GSUB_SubTable* st,
8505469607a00d84a07dc638eda46a87fc90142d64breed@android.com				     HB_Stream         stream )
8515469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
8525469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
8535469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_LigatureSubst*  ls = &st->ligature;
8545469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8555469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort         n = 0, m, count;
8565469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt          cur_offset, new_offset, base_offset;
8575469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8585469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_LigatureSet*  lset;
8595469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8605469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8615469607a00d84a07dc638eda46a87fc90142d64breed@android.com  base_offset = FILE_Pos();
8625469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8635469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 4L ) )
8645469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
8655469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8665469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ls->SubstFormat = GET_UShort();             /* should be 1 */
8675469607a00d84a07dc638eda46a87fc90142d64breed@android.com  new_offset      = GET_UShort() + base_offset;
8685469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8695469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
8705469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8715469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cur_offset = FILE_Pos();
8725469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( FILE_Seek( new_offset ) ||
8735469607a00d84a07dc638eda46a87fc90142d64breed@android.com       ( error = _HB_OPEN_Load_Coverage( &ls->Coverage, stream ) ) != HB_Err_Ok )
8745469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
8755469607a00d84a07dc638eda46a87fc90142d64breed@android.com  (void)FILE_Seek( cur_offset );
8765469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8775469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
8785469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
8795469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8805469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = ls->LigatureSetCount = GET_UShort();
8815469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8825469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
8835469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8845469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ls->LigatureSet = NULL;
8855469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8865469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( ls->LigatureSet, count, HB_LigatureSet ) )
8875469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
8885469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8895469607a00d84a07dc638eda46a87fc90142d64breed@android.com  lset = ls->LigatureSet;
8905469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8915469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
8925469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
8935469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ACCESS_Frame( 2L ) )
8945469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail1;
8955469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8965469607a00d84a07dc638eda46a87fc90142d64breed@android.com    new_offset = GET_UShort() + base_offset;
8975469607a00d84a07dc638eda46a87fc90142d64breed@android.com
8985469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FORGET_Frame();
8995469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9005469607a00d84a07dc638eda46a87fc90142d64breed@android.com    cur_offset = FILE_Pos();
9015469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( FILE_Seek( new_offset ) ||
9025469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 ( error = Load_LigatureSet( &lset[n], stream ) ) != HB_Err_Ok )
9035469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail1;
9045469607a00d84a07dc638eda46a87fc90142d64breed@android.com    (void)FILE_Seek( cur_offset );
9055469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
9065469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9075469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
9085469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9095469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail1:
9105469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( m = 0; m < n; m++ )
9115469607a00d84a07dc638eda46a87fc90142d64breed@android.com    Free_LigatureSet( &lset[m] );
9125469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9135469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( lset );
9145469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9155469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail2:
9165469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_Coverage( &ls->Coverage );
9175469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
9185469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
9195469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9205469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9215469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_LigatureSubst( HB_GSUB_SubTable* st )
9225469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
9235469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort         n, count;
9245469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_LigatureSubst*  ls = &st->ligature;
9255469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9265469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_LigatureSet*  lset;
9275469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9285469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9295469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ls->LigatureSet )
9305469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
9315469607a00d84a07dc638eda46a87fc90142d64breed@android.com    count = ls->LigatureSetCount;
9325469607a00d84a07dc638eda46a87fc90142d64breed@android.com    lset  = ls->LigatureSet;
9335469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9345469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( n = 0; n < count; n++ )
9355469607a00d84a07dc638eda46a87fc90142d64breed@android.com      Free_LigatureSet( &lset[n] );
9365469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9375469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FREE( lset );
9385469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
9395469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9405469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_Coverage( &ls->Coverage );
9415469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
9425469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9435469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9445469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Lookup_LigatureSubst( HB_GSUBHeader*    gsub,
9455469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_GSUB_SubTable* st,
9465469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_Buffer         buffer,
9475469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_UShort          flags,
9485469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_UShort          context_length,
9495469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       int                nesting_level )
9505469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
9515469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort      index, property;
9525469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error       error;
9535469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort      numlig, i, j, is_mark, first_is_mark = FALSE;
9545469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*     c;
9555469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_LigatureSubst*  ls = &st->ligature;
9565469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_GDEFHeader*     gdef = gsub->gdef;
9575469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9585469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Ligature*  lig;
9595469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9605469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UNUSED(nesting_level);
9615469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9625469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
9635469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
9645469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9655469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
9665469607a00d84a07dc638eda46a87fc90142d64breed@android.com    first_is_mark = TRUE;
9675469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9685469607a00d84a07dc638eda46a87fc90142d64breed@android.com  error = _HB_OPEN_Coverage_Index( &ls->Coverage, IN_CURGLYPH(), &index );
9695469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( error )
9705469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
9715469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9725469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( index >= ls->LigatureSetCount )
9735469607a00d84a07dc638eda46a87fc90142d64breed@android.com     return ERR(HB_Err_Invalid_SubTable);
9745469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9755469607a00d84a07dc638eda46a87fc90142d64breed@android.com  lig = ls->LigatureSet[index].Ligature;
9765469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9775469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( numlig = ls->LigatureSet[index].LigatureCount;
9785469607a00d84a07dc638eda46a87fc90142d64breed@android.com	numlig;
9795469607a00d84a07dc638eda46a87fc90142d64breed@android.com	numlig--, lig++ )
9805469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
9815469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( buffer->in_pos + lig->ComponentCount > buffer->in_length )
9825469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto next_ligature;               /* Not enough glyphs in input */
9835469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9845469607a00d84a07dc638eda46a87fc90142d64breed@android.com    c    = lig->Component;
9855469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9865469607a00d84a07dc638eda46a87fc90142d64breed@android.com    is_mark = first_is_mark;
9875469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9885469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( context_length != 0xFFFF && context_length < lig->ComponentCount )
9895469607a00d84a07dc638eda46a87fc90142d64breed@android.com      break;
9905469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9915469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( i = 1, j = buffer->in_pos + 1; i < lig->ComponentCount; i++, j++ )
9925469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
9935469607a00d84a07dc638eda46a87fc90142d64breed@android.com      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
9945469607a00d84a07dc638eda46a87fc90142d64breed@android.com      {
9955469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( error && error != HB_Err_Not_Covered )
9965469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  return error;
9975469607a00d84a07dc638eda46a87fc90142d64breed@android.com
9985469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( j + lig->ComponentCount - i == (HB_Int)buffer->in_length )
9995469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  goto next_ligature;
10005469607a00d84a07dc638eda46a87fc90142d64breed@android.com	j++;
10015469607a00d84a07dc638eda46a87fc90142d64breed@android.com      }
10025469607a00d84a07dc638eda46a87fc90142d64breed@android.com
10035469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
10045469607a00d84a07dc638eda46a87fc90142d64breed@android.com	is_mark = FALSE;
10055469607a00d84a07dc638eda46a87fc90142d64breed@android.com
10065469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( IN_GLYPH( j ) != c[i - 1] )
10075469607a00d84a07dc638eda46a87fc90142d64breed@android.com	goto next_ligature;
10085469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
10095469607a00d84a07dc638eda46a87fc90142d64breed@android.com
10105469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( gdef && gdef->NewGlyphClasses )
10115469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
10125469607a00d84a07dc638eda46a87fc90142d64breed@android.com      /* this is just a guess ... */
10135469607a00d84a07dc638eda46a87fc90142d64breed@android.com
10145469607a00d84a07dc638eda46a87fc90142d64breed@android.com      error = _HB_GDEF_Add_Glyph_Property( gdef, lig->LigGlyph,
10155469607a00d84a07dc638eda46a87fc90142d64breed@android.com				  is_mark ? HB_GDEF_MARK : HB_GDEF_LIGATURE );
10165469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( error && error != HB_Err_Not_Covered )
10175469607a00d84a07dc638eda46a87fc90142d64breed@android.com	return error;
10185469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
10195469607a00d84a07dc638eda46a87fc90142d64breed@android.com
10205469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( j == buffer->in_pos + i ) /* No input glyphs skipped */
10215469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
10225469607a00d84a07dc638eda46a87fc90142d64breed@android.com      /* We don't use a new ligature ID if there are no skipped
10235469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 glyphs and the ligature already has an ID.             */
10245469607a00d84a07dc638eda46a87fc90142d64breed@android.com
10255469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( IN_LIGID( buffer->in_pos ) )
10265469607a00d84a07dc638eda46a87fc90142d64breed@android.com      {
10275469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( ADD_String( buffer, i, 1, &lig->LigGlyph,
10285469607a00d84a07dc638eda46a87fc90142d64breed@android.com			0xFFFF, 0xFFFF ) )
10295469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  return error;
10305469607a00d84a07dc638eda46a87fc90142d64breed@android.com      }
10315469607a00d84a07dc638eda46a87fc90142d64breed@android.com      else
10325469607a00d84a07dc638eda46a87fc90142d64breed@android.com      {
10335469607a00d84a07dc638eda46a87fc90142d64breed@android.com	HB_UShort ligID = _hb_buffer_allocate_ligid( buffer );
10345469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( ADD_String( buffer, i, 1, &lig->LigGlyph,
10355469607a00d84a07dc638eda46a87fc90142d64breed@android.com			0xFFFF, ligID ) )
10365469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  return error;
10375469607a00d84a07dc638eda46a87fc90142d64breed@android.com      }
10385469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
10395469607a00d84a07dc638eda46a87fc90142d64breed@android.com    else
10405469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
10415469607a00d84a07dc638eda46a87fc90142d64breed@android.com      HB_UShort ligID = _hb_buffer_allocate_ligid( buffer );
10425469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( ADD_Glyph( buffer, lig->LigGlyph, 0xFFFF, ligID ) )
10435469607a00d84a07dc638eda46a87fc90142d64breed@android.com	return error;
10445469607a00d84a07dc638eda46a87fc90142d64breed@android.com
10455469607a00d84a07dc638eda46a87fc90142d64breed@android.com      /* Now we must do a second loop to copy the skipped glyphs to
10465469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 `out' and assign component values to it.  We start with the
10475469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 glyph after the first component.  Glyphs between component
10485469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 i and i+1 belong to component i.  Together with the ligID
10495469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 value it is later possible to check whether a specific
10505469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 component value really belongs to a given ligature.         */
10515469607a00d84a07dc638eda46a87fc90142d64breed@android.com
10525469607a00d84a07dc638eda46a87fc90142d64breed@android.com      for ( i = 0; i < lig->ComponentCount - 1; i++ )
10535469607a00d84a07dc638eda46a87fc90142d64breed@android.com      {
10545469607a00d84a07dc638eda46a87fc90142d64breed@android.com	while ( CHECK_Property( gdef, IN_CURITEM(),
10555469607a00d84a07dc638eda46a87fc90142d64breed@android.com				flags, &property ) )
10565469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  if ( ADD_Glyph( buffer, IN_CURGLYPH(), i, ligID ) )
10575469607a00d84a07dc638eda46a87fc90142d64breed@android.com	    return error;
10585469607a00d84a07dc638eda46a87fc90142d64breed@android.com
10595469607a00d84a07dc638eda46a87fc90142d64breed@android.com	(buffer->in_pos)++;
10605469607a00d84a07dc638eda46a87fc90142d64breed@android.com      }
10615469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
10625469607a00d84a07dc638eda46a87fc90142d64breed@android.com
10635469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return HB_Err_Ok;
10645469607a00d84a07dc638eda46a87fc90142d64breed@android.com
10655469607a00d84a07dc638eda46a87fc90142d64breed@android.com  next_ligature:
10665469607a00d84a07dc638eda46a87fc90142d64breed@android.com    ;
10675469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
10685469607a00d84a07dc638eda46a87fc90142d64breed@android.com
10695469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Not_Covered;
10705469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
10715469607a00d84a07dc638eda46a87fc90142d64breed@android.com
10725469607a00d84a07dc638eda46a87fc90142d64breed@android.com
10735469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* Do the actual substitution for a context substitution (either format
10745469607a00d84a07dc638eda46a87fc90142d64breed@android.com   5 or 6).  This is only called after we've determined that the input
10755469607a00d84a07dc638eda46a87fc90142d64breed@android.com   matches the subrule.                                                 */
10765469607a00d84a07dc638eda46a87fc90142d64breed@android.com
10775469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Do_ContextSubst( HB_GSUBHeader*        gsub,
10785469607a00d84a07dc638eda46a87fc90142d64breed@android.com				  HB_UShort              GlyphCount,
10795469607a00d84a07dc638eda46a87fc90142d64breed@android.com				  HB_UShort              SubstCount,
10805469607a00d84a07dc638eda46a87fc90142d64breed@android.com				  HB_SubstLookupRecord* subst,
10815469607a00d84a07dc638eda46a87fc90142d64breed@android.com				  HB_Buffer             buffer,
10825469607a00d84a07dc638eda46a87fc90142d64breed@android.com				  int                    nesting_level )
10835469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
10845469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error  error;
10855469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt   i, old_pos;
10865469607a00d84a07dc638eda46a87fc90142d64breed@android.com
10875469607a00d84a07dc638eda46a87fc90142d64breed@android.com
10885469607a00d84a07dc638eda46a87fc90142d64breed@android.com  i = 0;
10895469607a00d84a07dc638eda46a87fc90142d64breed@android.com
10905469607a00d84a07dc638eda46a87fc90142d64breed@android.com  while ( i < GlyphCount )
10915469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
10925469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( SubstCount && i == subst->SequenceIndex )
10935469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
10945469607a00d84a07dc638eda46a87fc90142d64breed@android.com      old_pos = buffer->in_pos;
10955469607a00d84a07dc638eda46a87fc90142d64breed@android.com
10965469607a00d84a07dc638eda46a87fc90142d64breed@android.com      /* Do a substitution */
10975469607a00d84a07dc638eda46a87fc90142d64breed@android.com
10985469607a00d84a07dc638eda46a87fc90142d64breed@android.com      error = GSUB_Do_Glyph_Lookup( gsub, subst->LookupListIndex, buffer,
10995469607a00d84a07dc638eda46a87fc90142d64breed@android.com				    GlyphCount, nesting_level );
11005469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11015469607a00d84a07dc638eda46a87fc90142d64breed@android.com      subst++;
11025469607a00d84a07dc638eda46a87fc90142d64breed@android.com      SubstCount--;
11035469607a00d84a07dc638eda46a87fc90142d64breed@android.com      i += buffer->in_pos - old_pos;
11045469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11055469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( error == HB_Err_Not_Covered )
11065469607a00d84a07dc638eda46a87fc90142d64breed@android.com      {
11075469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( COPY_Glyph( buffer ) )
11085469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  return error;
11095469607a00d84a07dc638eda46a87fc90142d64breed@android.com	i++;
11105469607a00d84a07dc638eda46a87fc90142d64breed@android.com      }
11115469607a00d84a07dc638eda46a87fc90142d64breed@android.com      else if ( error )
11125469607a00d84a07dc638eda46a87fc90142d64breed@android.com	return error;
11135469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
11145469607a00d84a07dc638eda46a87fc90142d64breed@android.com    else
11155469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
11165469607a00d84a07dc638eda46a87fc90142d64breed@android.com      /* No substitution for this index */
11175469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11185469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( COPY_Glyph( buffer ) )
11195469607a00d84a07dc638eda46a87fc90142d64breed@android.com	return error;
11205469607a00d84a07dc638eda46a87fc90142d64breed@android.com      i++;
11215469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
11225469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
11235469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11245469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
11255469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
11265469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11275469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11285469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* LookupType 5 */
11295469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11305469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* SubRule */
11315469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11325469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_SubRule( HB_SubRule*  sr,
11335469607a00d84a07dc638eda46a87fc90142d64breed@android.com			       HB_Stream     stream )
11345469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
11355469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
11365469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11375469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort               n, count;
11385469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*              i;
11395469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11405469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_SubstLookupRecord*  slr;
11415469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11425469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11435469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 4L ) )
11445469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
11455469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11465469607a00d84a07dc638eda46a87fc90142d64breed@android.com  sr->GlyphCount = GET_UShort();
11475469607a00d84a07dc638eda46a87fc90142d64breed@android.com  sr->SubstCount = GET_UShort();
11485469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11495469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
11505469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11515469607a00d84a07dc638eda46a87fc90142d64breed@android.com  sr->Input = NULL;
11525469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11535469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = sr->GlyphCount - 1;         /* only GlyphCount - 1 elements */
11545469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11555469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( sr->Input, count, HB_UShort ) )
11565469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
11575469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11585469607a00d84a07dc638eda46a87fc90142d64breed@android.com  i = sr->Input;
11595469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11605469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( count * 2L ) )
11615469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
11625469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11635469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
11645469607a00d84a07dc638eda46a87fc90142d64breed@android.com    i[n] = GET_UShort();
11655469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11665469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
11675469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11685469607a00d84a07dc638eda46a87fc90142d64breed@android.com  sr->SubstLookupRecord = NULL;
11695469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11705469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = sr->SubstCount;
11715469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11725469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( sr->SubstLookupRecord, count, HB_SubstLookupRecord ) )
11735469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
11745469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11755469607a00d84a07dc638eda46a87fc90142d64breed@android.com  slr = sr->SubstLookupRecord;
11765469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11775469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( count * 4L ) )
11785469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail1;
11795469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11805469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
11815469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
11825469607a00d84a07dc638eda46a87fc90142d64breed@android.com    slr[n].SequenceIndex   = GET_UShort();
11835469607a00d84a07dc638eda46a87fc90142d64breed@android.com    slr[n].LookupListIndex = GET_UShort();
11845469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
11855469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11865469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
11875469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11885469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
11895469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11905469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail1:
11915469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( slr );
11925469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11935469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail2:
11945469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( i );
11955469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
11965469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
11975469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11985469607a00d84a07dc638eda46a87fc90142d64breed@android.com
11995469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_SubRule( HB_SubRule*  sr )
12005469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
12015469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( sr->SubstLookupRecord );
12025469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( sr->Input );
12035469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
12045469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12055469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12065469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* SubRuleSet */
12075469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12085469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_SubRuleSet( HB_SubRuleSet*  srs,
12095469607a00d84a07dc638eda46a87fc90142d64breed@android.com				  HB_Stream        stream )
12105469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
12115469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
12125469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12135469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort     n = 0, m, count;
12145469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt      cur_offset, new_offset, base_offset;
12155469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12165469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_SubRule*  sr;
12175469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12185469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12195469607a00d84a07dc638eda46a87fc90142d64breed@android.com  base_offset = FILE_Pos();
12205469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12215469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
12225469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
12235469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12245469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = srs->SubRuleCount = GET_UShort();
12255469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12265469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
12275469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12285469607a00d84a07dc638eda46a87fc90142d64breed@android.com  srs->SubRule = NULL;
12295469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12305469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( srs->SubRule, count, HB_SubRule ) )
12315469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
12325469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12335469607a00d84a07dc638eda46a87fc90142d64breed@android.com  sr = srs->SubRule;
12345469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12355469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
12365469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
12375469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ACCESS_Frame( 2L ) )
12385469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail;
12395469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12405469607a00d84a07dc638eda46a87fc90142d64breed@android.com    new_offset = GET_UShort() + base_offset;
12415469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12425469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FORGET_Frame();
12435469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12445469607a00d84a07dc638eda46a87fc90142d64breed@android.com    cur_offset = FILE_Pos();
12455469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( FILE_Seek( new_offset ) ||
12465469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 ( error = Load_SubRule( &sr[n], stream ) ) != HB_Err_Ok )
12475469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail;
12485469607a00d84a07dc638eda46a87fc90142d64breed@android.com    (void)FILE_Seek( cur_offset );
12495469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
12505469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12515469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
12525469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12535469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail:
12545469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( m = 0; m < n; m++ )
12555469607a00d84a07dc638eda46a87fc90142d64breed@android.com    Free_SubRule( &sr[m] );
12565469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12575469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( sr );
12585469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
12595469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
12605469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12615469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12625469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_SubRuleSet( HB_SubRuleSet*  srs )
12635469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
12645469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort     n, count;
12655469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12665469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_SubRule*  sr;
12675469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12685469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12695469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( srs->SubRule )
12705469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
12715469607a00d84a07dc638eda46a87fc90142d64breed@android.com    count = srs->SubRuleCount;
12725469607a00d84a07dc638eda46a87fc90142d64breed@android.com    sr    = srs->SubRule;
12735469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12745469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( n = 0; n < count; n++ )
12755469607a00d84a07dc638eda46a87fc90142d64breed@android.com      Free_SubRule( &sr[n] );
12765469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12775469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FREE( sr );
12785469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
12795469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
12805469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12815469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12825469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* ContextSubstFormat1 */
12835469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12845469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_ContextSubst1( HB_ContextSubstFormat1*  csf1,
12855469607a00d84a07dc638eda46a87fc90142d64breed@android.com				     HB_Stream                 stream )
12865469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
12875469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
12885469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12895469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort        n = 0, m, count;
12905469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt         cur_offset, new_offset, base_offset;
12915469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12925469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_SubRuleSet*  srs;
12935469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12945469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12955469607a00d84a07dc638eda46a87fc90142d64breed@android.com  base_offset = FILE_Pos() - 2L;
12965469607a00d84a07dc638eda46a87fc90142d64breed@android.com
12975469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
12985469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
12995469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13005469607a00d84a07dc638eda46a87fc90142d64breed@android.com  new_offset = GET_UShort() + base_offset;
13015469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13025469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
13035469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13045469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cur_offset = FILE_Pos();
13055469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( FILE_Seek( new_offset ) ||
13065469607a00d84a07dc638eda46a87fc90142d64breed@android.com       ( error = _HB_OPEN_Load_Coverage( &csf1->Coverage, stream ) ) != HB_Err_Ok )
13075469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
13085469607a00d84a07dc638eda46a87fc90142d64breed@android.com  (void)FILE_Seek( cur_offset );
13095469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13105469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
13115469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
13125469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13135469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = csf1->SubRuleSetCount = GET_UShort();
13145469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13155469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
13165469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13175469607a00d84a07dc638eda46a87fc90142d64breed@android.com  csf1->SubRuleSet = NULL;
13185469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13195469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( csf1->SubRuleSet, count, HB_SubRuleSet ) )
13205469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
13215469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13225469607a00d84a07dc638eda46a87fc90142d64breed@android.com  srs = csf1->SubRuleSet;
13235469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13245469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
13255469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
13265469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ACCESS_Frame( 2L ) )
13275469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail1;
13285469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13295469607a00d84a07dc638eda46a87fc90142d64breed@android.com    new_offset = GET_UShort() + base_offset;
13305469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13315469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FORGET_Frame();
13325469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13335469607a00d84a07dc638eda46a87fc90142d64breed@android.com    cur_offset = FILE_Pos();
13345469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( FILE_Seek( new_offset ) ||
13355469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 ( error = Load_SubRuleSet( &srs[n], stream ) ) != HB_Err_Ok )
13365469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail1;
13375469607a00d84a07dc638eda46a87fc90142d64breed@android.com    (void)FILE_Seek( cur_offset );
13385469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
13395469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13405469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
13415469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13425469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail1:
13435469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( m = 0; m < n; m++ )
13445469607a00d84a07dc638eda46a87fc90142d64breed@android.com    Free_SubRuleSet( &srs[m] );
13455469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13465469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( srs );
13475469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13485469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail2:
13495469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_Coverage( &csf1->Coverage );
13505469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
13515469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
13525469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13535469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13545469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_ContextSubst1( HB_ContextSubstFormat1* csf1 )
13555469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
13565469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort        n, count;
13575469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13585469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_SubRuleSet*  srs;
13595469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13605469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13615469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( csf1->SubRuleSet )
13625469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
13635469607a00d84a07dc638eda46a87fc90142d64breed@android.com    count = csf1->SubRuleSetCount;
13645469607a00d84a07dc638eda46a87fc90142d64breed@android.com    srs   = csf1->SubRuleSet;
13655469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13665469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( n = 0; n < count; n++ )
13675469607a00d84a07dc638eda46a87fc90142d64breed@android.com      Free_SubRuleSet( &srs[n] );
13685469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13695469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FREE( srs );
13705469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
13715469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13725469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_Coverage( &csf1->Coverage );
13735469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
13745469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13755469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13765469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* SubClassRule */
13775469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13785469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_SubClassRule( HB_ContextSubstFormat2*  csf2,
13795469607a00d84a07dc638eda46a87fc90142d64breed@android.com				    HB_SubClassRule*         scr,
13805469607a00d84a07dc638eda46a87fc90142d64breed@android.com				    HB_Stream                 stream )
13815469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
13825469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
13835469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13845469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort               n, count;
13855469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13865469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*              c;
13875469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_SubstLookupRecord*  slr;
13885469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13895469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13905469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 4L ) )
13915469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
13925469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13935469607a00d84a07dc638eda46a87fc90142d64breed@android.com  scr->GlyphCount = GET_UShort();
13945469607a00d84a07dc638eda46a87fc90142d64breed@android.com  scr->SubstCount = GET_UShort();
13955469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13965469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( scr->GlyphCount > csf2->MaxContextLength )
13975469607a00d84a07dc638eda46a87fc90142d64breed@android.com    csf2->MaxContextLength = scr->GlyphCount;
13985469607a00d84a07dc638eda46a87fc90142d64breed@android.com
13995469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
14005469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14015469607a00d84a07dc638eda46a87fc90142d64breed@android.com  scr->Class = NULL;
14025469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14035469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = scr->GlyphCount - 1;        /* only GlyphCount - 1 elements */
14045469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14055469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( scr->Class, count, HB_UShort ) )
14065469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
14075469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14085469607a00d84a07dc638eda46a87fc90142d64breed@android.com  c = scr->Class;
14095469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14105469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( count * 2L ) )
14115469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
14125469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14135469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
14145469607a00d84a07dc638eda46a87fc90142d64breed@android.com    c[n] = GET_UShort();
14155469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14165469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
14175469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14185469607a00d84a07dc638eda46a87fc90142d64breed@android.com  scr->SubstLookupRecord = NULL;
14195469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14205469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = scr->SubstCount;
14215469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14225469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( scr->SubstLookupRecord, count, HB_SubstLookupRecord ) )
14235469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
14245469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14255469607a00d84a07dc638eda46a87fc90142d64breed@android.com  slr = scr->SubstLookupRecord;
14265469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14275469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( count * 4L ) )
14285469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail1;
14295469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14305469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
14315469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
14325469607a00d84a07dc638eda46a87fc90142d64breed@android.com    slr[n].SequenceIndex   = GET_UShort();
14335469607a00d84a07dc638eda46a87fc90142d64breed@android.com    slr[n].LookupListIndex = GET_UShort();
14345469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
14355469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14365469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
14375469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14385469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
14395469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14405469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail1:
14415469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( slr );
14425469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14435469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail2:
14445469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( c );
14455469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
14465469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
14475469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14485469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14495469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_SubClassRule( HB_SubClassRule*  scr )
14505469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
14515469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( scr->SubstLookupRecord );
14525469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( scr->Class );
14535469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
14545469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14555469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14565469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* SubClassSet */
14575469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14585469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_SubClassSet( HB_ContextSubstFormat2*  csf2,
14595469607a00d84a07dc638eda46a87fc90142d64breed@android.com				   HB_SubClassSet*          scs,
14605469607a00d84a07dc638eda46a87fc90142d64breed@android.com				   HB_Stream                 stream )
14615469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
14625469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
14635469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14645469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort          n = 0, m, count;
14655469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt           cur_offset, new_offset, base_offset;
14665469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14675469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_SubClassRule*  scr;
14685469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14695469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14705469607a00d84a07dc638eda46a87fc90142d64breed@android.com  base_offset = FILE_Pos();
14715469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14725469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
14735469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
14745469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14755469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = scs->SubClassRuleCount = GET_UShort();
14765469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14775469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
14785469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14795469607a00d84a07dc638eda46a87fc90142d64breed@android.com  scs->SubClassRule = NULL;
14805469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14815469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( scs->SubClassRule, count, HB_SubClassRule ) )
14825469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
14835469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14845469607a00d84a07dc638eda46a87fc90142d64breed@android.com  scr = scs->SubClassRule;
14855469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14865469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
14875469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
14885469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ACCESS_Frame( 2L ) )
14895469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail;
14905469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14915469607a00d84a07dc638eda46a87fc90142d64breed@android.com    new_offset = GET_UShort() + base_offset;
14925469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14935469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FORGET_Frame();
14945469607a00d84a07dc638eda46a87fc90142d64breed@android.com
14955469607a00d84a07dc638eda46a87fc90142d64breed@android.com    cur_offset = FILE_Pos();
14965469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( FILE_Seek( new_offset ) ||
14975469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 ( error = Load_SubClassRule( csf2, &scr[n],
14985469607a00d84a07dc638eda46a87fc90142d64breed@android.com				      stream ) ) != HB_Err_Ok )
14995469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail;
15005469607a00d84a07dc638eda46a87fc90142d64breed@android.com    (void)FILE_Seek( cur_offset );
15015469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
15025469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15035469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
15045469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15055469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail:
15065469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( m = 0; m < n; m++ )
15075469607a00d84a07dc638eda46a87fc90142d64breed@android.com    Free_SubClassRule( &scr[m] );
15085469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15095469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( scr );
15105469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
15115469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
15125469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15135469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15145469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_SubClassSet( HB_SubClassSet*  scs )
15155469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
15165469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort          n, count;
15175469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15185469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_SubClassRule*  scr;
15195469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15205469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15215469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( scs->SubClassRule )
15225469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
15235469607a00d84a07dc638eda46a87fc90142d64breed@android.com    count = scs->SubClassRuleCount;
15245469607a00d84a07dc638eda46a87fc90142d64breed@android.com    scr   = scs->SubClassRule;
15255469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15265469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( n = 0; n < count; n++ )
15275469607a00d84a07dc638eda46a87fc90142d64breed@android.com      Free_SubClassRule( &scr[n] );
15285469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15295469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FREE( scr );
15305469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
15315469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
15325469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15335469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15345469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* ContextSubstFormat2 */
15355469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15365469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_ContextSubst2( HB_ContextSubstFormat2*  csf2,
15375469607a00d84a07dc638eda46a87fc90142d64breed@android.com				     HB_Stream                 stream )
15385469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
15395469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
15405469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15415469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort         n = 0, m, count;
15425469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt          cur_offset, new_offset, base_offset;
15435469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15445469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_SubClassSet*  scs;
15455469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15465469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15475469607a00d84a07dc638eda46a87fc90142d64breed@android.com  base_offset = FILE_Pos() - 2;
15485469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15495469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
15505469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
15515469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15525469607a00d84a07dc638eda46a87fc90142d64breed@android.com  new_offset = GET_UShort() + base_offset;
15535469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15545469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
15555469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15565469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cur_offset = FILE_Pos();
15575469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( FILE_Seek( new_offset ) ||
15585469607a00d84a07dc638eda46a87fc90142d64breed@android.com       ( error = _HB_OPEN_Load_Coverage( &csf2->Coverage, stream ) ) != HB_Err_Ok )
15595469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
15605469607a00d84a07dc638eda46a87fc90142d64breed@android.com  (void)FILE_Seek( cur_offset );
15615469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15625469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 4L ) )
15635469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail3;
15645469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15655469607a00d84a07dc638eda46a87fc90142d64breed@android.com  new_offset = GET_UShort() + base_offset;
15665469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15675469607a00d84a07dc638eda46a87fc90142d64breed@android.com  /* `SubClassSetCount' is the upper limit for class values, thus we
15685469607a00d84a07dc638eda46a87fc90142d64breed@android.com     read it now to make an additional safety check.                 */
15695469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15705469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = csf2->SubClassSetCount = GET_UShort();
15715469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15725469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
15735469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15745469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cur_offset = FILE_Pos();
15755469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( FILE_Seek( new_offset ) ||
15765469607a00d84a07dc638eda46a87fc90142d64breed@android.com       ( error = _HB_OPEN_Load_ClassDefinition( &csf2->ClassDef, count,
15775469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       stream ) ) != HB_Err_Ok )
15785469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail3;
15795469607a00d84a07dc638eda46a87fc90142d64breed@android.com  (void)FILE_Seek( cur_offset );
15805469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15815469607a00d84a07dc638eda46a87fc90142d64breed@android.com  csf2->SubClassSet      = NULL;
15825469607a00d84a07dc638eda46a87fc90142d64breed@android.com  csf2->MaxContextLength = 0;
15835469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15845469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( csf2->SubClassSet, count, HB_SubClassSet ) )
15855469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
15865469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15875469607a00d84a07dc638eda46a87fc90142d64breed@android.com  scs = csf2->SubClassSet;
15885469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15895469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
15905469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
15915469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ACCESS_Frame( 2L ) )
15925469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail1;
15935469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15945469607a00d84a07dc638eda46a87fc90142d64breed@android.com    new_offset = GET_UShort() + base_offset;
15955469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15965469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FORGET_Frame();
15975469607a00d84a07dc638eda46a87fc90142d64breed@android.com
15985469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( new_offset != base_offset )      /* not a NULL offset */
15995469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
16005469607a00d84a07dc638eda46a87fc90142d64breed@android.com      cur_offset = FILE_Pos();
16015469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( FILE_Seek( new_offset ) ||
16025469607a00d84a07dc638eda46a87fc90142d64breed@android.com	   ( error = Load_SubClassSet( csf2, &scs[n],
16035469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       stream ) ) != HB_Err_Ok )
16045469607a00d84a07dc638eda46a87fc90142d64breed@android.com	goto Fail1;
16055469607a00d84a07dc638eda46a87fc90142d64breed@android.com      (void)FILE_Seek( cur_offset );
16065469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
16075469607a00d84a07dc638eda46a87fc90142d64breed@android.com    else
16085469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
16095469607a00d84a07dc638eda46a87fc90142d64breed@android.com      /* we create a SubClassSet table with no entries */
16105469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16115469607a00d84a07dc638eda46a87fc90142d64breed@android.com      csf2->SubClassSet[n].SubClassRuleCount = 0;
16125469607a00d84a07dc638eda46a87fc90142d64breed@android.com      csf2->SubClassSet[n].SubClassRule      = NULL;
16135469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
16145469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
16155469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16165469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
16175469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16185469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail1:
16195469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( m = 0; m < n; m++ )
16205469607a00d84a07dc638eda46a87fc90142d64breed@android.com    Free_SubClassSet( &scs[m] );
16215469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16225469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( scs );
16235469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16245469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail2:
16255469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_ClassDefinition( &csf2->ClassDef );
16265469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16275469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail3:
16285469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_Coverage( &csf2->Coverage );
16295469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
16305469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
16315469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16325469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16335469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_ContextSubst2( HB_ContextSubstFormat2*  csf2 )
16345469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
16355469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort         n, count;
16365469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16375469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_SubClassSet*  scs;
16385469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16395469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16405469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( csf2->SubClassSet )
16415469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
16425469607a00d84a07dc638eda46a87fc90142d64breed@android.com    count = csf2->SubClassSetCount;
16435469607a00d84a07dc638eda46a87fc90142d64breed@android.com    scs   = csf2->SubClassSet;
16445469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16455469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( n = 0; n < count; n++ )
16465469607a00d84a07dc638eda46a87fc90142d64breed@android.com      Free_SubClassSet( &scs[n] );
16475469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16485469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FREE( scs );
16495469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
16505469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16515469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_ClassDefinition( &csf2->ClassDef );
16525469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_Coverage( &csf2->Coverage );
16535469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
16545469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16555469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16565469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* ContextSubstFormat3 */
16575469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16585469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_ContextSubst3( HB_ContextSubstFormat3*  csf3,
16595469607a00d84a07dc638eda46a87fc90142d64breed@android.com				     HB_Stream                 stream )
16605469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
16615469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
16625469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16635469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort               n = 0, m, count;
16645469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt                cur_offset, new_offset, base_offset;
16655469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16665469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Coverage*           c;
16675469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_SubstLookupRecord*  slr;
16685469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16695469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16705469607a00d84a07dc638eda46a87fc90142d64breed@android.com  base_offset = FILE_Pos() - 2L;
16715469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16725469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 4L ) )
16735469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
16745469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16755469607a00d84a07dc638eda46a87fc90142d64breed@android.com  csf3->GlyphCount = GET_UShort();
16765469607a00d84a07dc638eda46a87fc90142d64breed@android.com  csf3->SubstCount = GET_UShort();
16775469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16785469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
16795469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16805469607a00d84a07dc638eda46a87fc90142d64breed@android.com  csf3->Coverage = NULL;
16815469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16825469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = csf3->GlyphCount;
16835469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16845469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( csf3->Coverage, count, HB_Coverage ) )
16855469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
16865469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16875469607a00d84a07dc638eda46a87fc90142d64breed@android.com  c = csf3->Coverage;
16885469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16895469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
16905469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
16915469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ACCESS_Frame( 2L ) )
16925469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail2;
16935469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16945469607a00d84a07dc638eda46a87fc90142d64breed@android.com    new_offset = GET_UShort() + base_offset;
16955469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16965469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FORGET_Frame();
16975469607a00d84a07dc638eda46a87fc90142d64breed@android.com
16985469607a00d84a07dc638eda46a87fc90142d64breed@android.com    cur_offset = FILE_Pos();
16995469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( FILE_Seek( new_offset ) ||
17005469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 ( error = _HB_OPEN_Load_Coverage( &c[n], stream ) ) != HB_Err_Ok )
17015469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail2;
17025469607a00d84a07dc638eda46a87fc90142d64breed@android.com    (void)FILE_Seek( cur_offset );
17035469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
17045469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17055469607a00d84a07dc638eda46a87fc90142d64breed@android.com  csf3->SubstLookupRecord = NULL;
17065469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17075469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = csf3->SubstCount;
17085469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17095469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( csf3->SubstLookupRecord, count,
17105469607a00d84a07dc638eda46a87fc90142d64breed@android.com		    HB_SubstLookupRecord ) )
17115469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
17125469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17135469607a00d84a07dc638eda46a87fc90142d64breed@android.com  slr = csf3->SubstLookupRecord;
17145469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17155469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( count * 4L ) )
17165469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail1;
17175469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17185469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
17195469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
17205469607a00d84a07dc638eda46a87fc90142d64breed@android.com    slr[n].SequenceIndex   = GET_UShort();
17215469607a00d84a07dc638eda46a87fc90142d64breed@android.com    slr[n].LookupListIndex = GET_UShort();
17225469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
17235469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17245469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
17255469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17265469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
17275469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17285469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail1:
17295469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( slr );
17305469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17315469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail2:
17325469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( m = 0; m < n; m++ )
17335469607a00d84a07dc638eda46a87fc90142d64breed@android.com    _HB_OPEN_Free_Coverage( &c[m] );
17345469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17355469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( c );
17365469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
17375469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
17385469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17395469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17405469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_ContextSubst3( HB_ContextSubstFormat3*  csf3 )
17415469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
17425469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort      n, count;
17435469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17445469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Coverage*  c;
17455469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17465469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17475469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( csf3->SubstLookupRecord );
17485469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17495469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( csf3->Coverage )
17505469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
17515469607a00d84a07dc638eda46a87fc90142d64breed@android.com    count = csf3->GlyphCount;
17525469607a00d84a07dc638eda46a87fc90142d64breed@android.com    c     = csf3->Coverage;
17535469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17545469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( n = 0; n < count; n++ )
17555469607a00d84a07dc638eda46a87fc90142d64breed@android.com      _HB_OPEN_Free_Coverage( &c[n] );
17565469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17575469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FREE( c );
17585469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
17595469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
17605469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17615469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17625469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* ContextSubst */
17635469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17645469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_ContextSubst( HB_GSUB_SubTable* st,
17655469607a00d84a07dc638eda46a87fc90142d64breed@android.com				    HB_Stream         stream )
17665469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
17675469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
17685469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ContextSubst*  cs = &st->context;
17695469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17705469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17715469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
17725469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
17735469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17745469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cs->SubstFormat = GET_UShort();
17755469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17765469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
17775469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17785469607a00d84a07dc638eda46a87fc90142d64breed@android.com  switch ( cs->SubstFormat )
17795469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
17805469607a00d84a07dc638eda46a87fc90142d64breed@android.com  case 1:  return Load_ContextSubst1( &cs->csf.csf1, stream );
17815469607a00d84a07dc638eda46a87fc90142d64breed@android.com  case 2:  return Load_ContextSubst2( &cs->csf.csf2, stream );
17825469607a00d84a07dc638eda46a87fc90142d64breed@android.com  case 3:  return Load_ContextSubst3( &cs->csf.csf3, stream );
17835469607a00d84a07dc638eda46a87fc90142d64breed@android.com  default: return ERR(HB_Err_Invalid_SubTable_Format);
17845469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
17855469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17865469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;               /* never reached */
17875469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
17885469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17895469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17905469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_ContextSubst( HB_GSUB_SubTable* st )
17915469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
17925469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ContextSubst*  cs = &st->context;
17935469607a00d84a07dc638eda46a87fc90142d64breed@android.com
17945469607a00d84a07dc638eda46a87fc90142d64breed@android.com  switch ( cs->SubstFormat )
17955469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
17965469607a00d84a07dc638eda46a87fc90142d64breed@android.com  case 1:  Free_ContextSubst1( &cs->csf.csf1 ); break;
17975469607a00d84a07dc638eda46a87fc90142d64breed@android.com  case 2:  Free_ContextSubst2( &cs->csf.csf2 ); break;
17985469607a00d84a07dc638eda46a87fc90142d64breed@android.com  case 3:  Free_ContextSubst3( &cs->csf.csf3 ); break;
17995469607a00d84a07dc638eda46a87fc90142d64breed@android.com  default:						break;
18005469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
18015469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
18025469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18035469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18045469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Lookup_ContextSubst1( HB_GSUBHeader*          gsub,
18055469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_ContextSubstFormat1* csf1,
18065469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_Buffer               buffer,
18075469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_UShort                flags,
18085469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_UShort                context_length,
18095469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       int                      nesting_level )
18105469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
18115469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort        index, property;
18125469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort        i, j, k, numsr;
18135469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error         error;
18145469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18155469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_SubRule*     sr;
18165469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_GDEFHeader*  gdef;
18175469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18185469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18195469607a00d84a07dc638eda46a87fc90142d64breed@android.com  gdef = gsub->gdef;
18205469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18215469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
18225469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
18235469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18245469607a00d84a07dc638eda46a87fc90142d64breed@android.com  error = _HB_OPEN_Coverage_Index( &csf1->Coverage, IN_CURGLYPH(), &index );
18255469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( error )
18265469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
18275469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18285469607a00d84a07dc638eda46a87fc90142d64breed@android.com  sr    = csf1->SubRuleSet[index].SubRule;
18295469607a00d84a07dc638eda46a87fc90142d64breed@android.com  numsr = csf1->SubRuleSet[index].SubRuleCount;
18305469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18315469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( k = 0; k < numsr; k++ )
18325469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
18335469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( context_length != 0xFFFF && context_length < sr[k].GlyphCount )
18345469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto next_subrule;
18355469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18365469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( buffer->in_pos + sr[k].GlyphCount > buffer->in_length )
18375469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto next_subrule;                        /* context is too long */
18385469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18395469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( i = 1, j = buffer->in_pos + 1; i < sr[k].GlyphCount; i++, j++ )
18405469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
18415469607a00d84a07dc638eda46a87fc90142d64breed@android.com      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
18425469607a00d84a07dc638eda46a87fc90142d64breed@android.com      {
18435469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( error && error != HB_Err_Not_Covered )
18445469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  return error;
18455469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18465469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( j + sr[k].GlyphCount - i == (HB_Int)buffer->in_length )
18475469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  goto next_subrule;
18485469607a00d84a07dc638eda46a87fc90142d64breed@android.com	j++;
18495469607a00d84a07dc638eda46a87fc90142d64breed@android.com      }
18505469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18515469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( IN_GLYPH( j ) != sr[k].Input[i - 1] )
18525469607a00d84a07dc638eda46a87fc90142d64breed@android.com	goto next_subrule;
18535469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
18545469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18555469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return Do_ContextSubst( gsub, sr[k].GlyphCount,
18565469607a00d84a07dc638eda46a87fc90142d64breed@android.com			    sr[k].SubstCount, sr[k].SubstLookupRecord,
18575469607a00d84a07dc638eda46a87fc90142d64breed@android.com			    buffer,
18585469607a00d84a07dc638eda46a87fc90142d64breed@android.com			    nesting_level );
18595469607a00d84a07dc638eda46a87fc90142d64breed@android.com  next_subrule:
18605469607a00d84a07dc638eda46a87fc90142d64breed@android.com    ;
18615469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
18625469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18635469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Not_Covered;
18645469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
18655469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18665469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18675469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Lookup_ContextSubst2( HB_GSUBHeader*          gsub,
18685469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_ContextSubstFormat2* csf2,
18695469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_Buffer               buffer,
18705469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_UShort                flags,
18715469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_UShort                context_length,
18725469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       int                      nesting_level )
18735469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
18745469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort          index, property;
18755469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error           error;
18765469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort          i, j, k, known_classes;
18775469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18785469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*         classes;
18795469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*         cl;
18805469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18815469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_SubClassSet*   scs;
18825469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_SubClassRule*  sr;
18835469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_GDEFHeader*    gdef;
18845469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18855469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18865469607a00d84a07dc638eda46a87fc90142d64breed@android.com  gdef = gsub->gdef;
18875469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18885469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
18895469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
18905469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18915469607a00d84a07dc638eda46a87fc90142d64breed@android.com  /* Note: The coverage table in format 2 doesn't give an index into
18925469607a00d84a07dc638eda46a87fc90142d64breed@android.com	   anything.  It just lets us know whether or not we need to
18935469607a00d84a07dc638eda46a87fc90142d64breed@android.com	   do any lookup at all.                                     */
18945469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18955469607a00d84a07dc638eda46a87fc90142d64breed@android.com  error = _HB_OPEN_Coverage_Index( &csf2->Coverage, IN_CURGLYPH(), &index );
18965469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( error )
18975469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
18985469607a00d84a07dc638eda46a87fc90142d64breed@android.com
18995469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if (csf2->MaxContextLength < 1)
19005469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return HB_Err_Not_Covered;
19015469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19025469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( classes, csf2->MaxContextLength, HB_UShort ) )
19035469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
19045469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19055469607a00d84a07dc638eda46a87fc90142d64breed@android.com  error = _HB_OPEN_Get_Class( &csf2->ClassDef, IN_CURGLYPH(),
19065469607a00d84a07dc638eda46a87fc90142d64breed@android.com		     &classes[0], NULL );
19075469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( error && error != HB_Err_Not_Covered )
19085469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto End;
19095469607a00d84a07dc638eda46a87fc90142d64breed@android.com  known_classes = 0;
19105469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19115469607a00d84a07dc638eda46a87fc90142d64breed@android.com  scs = &csf2->SubClassSet[classes[0]];
19125469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( !scs )
19135469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
19145469607a00d84a07dc638eda46a87fc90142d64breed@android.com    error = ERR(HB_Err_Invalid_SubTable);
19155469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto End;
19165469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
19175469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19185469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( k = 0; k < scs->SubClassRuleCount; k++ )
19195469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
19205469607a00d84a07dc638eda46a87fc90142d64breed@android.com    sr  = &scs->SubClassRule[k];
19215469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19225469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( context_length != 0xFFFF && context_length < sr->GlyphCount )
19235469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto next_subclassrule;
19245469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19255469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( buffer->in_pos + sr->GlyphCount > buffer->in_length )
19265469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto next_subclassrule;                      /* context is too long */
19275469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19285469607a00d84a07dc638eda46a87fc90142d64breed@android.com    cl   = sr->Class;
19295469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19305469607a00d84a07dc638eda46a87fc90142d64breed@android.com    /* Start at 1 because [0] is implied */
19315469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19325469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( i = 1, j = buffer->in_pos + 1; i < sr->GlyphCount; i++, j++ )
19335469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
19345469607a00d84a07dc638eda46a87fc90142d64breed@android.com      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
19355469607a00d84a07dc638eda46a87fc90142d64breed@android.com      {
19365469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( error && error != HB_Err_Not_Covered )
19375469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  goto End;
19385469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19395469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( j + sr->GlyphCount - i < (HB_Int)buffer->in_length )
19405469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  goto next_subclassrule;
19415469607a00d84a07dc638eda46a87fc90142d64breed@android.com	j++;
19425469607a00d84a07dc638eda46a87fc90142d64breed@android.com      }
19435469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19445469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( i > known_classes )
19455469607a00d84a07dc638eda46a87fc90142d64breed@android.com      {
19465469607a00d84a07dc638eda46a87fc90142d64breed@android.com	/* Keeps us from having to do this for each rule */
19475469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19485469607a00d84a07dc638eda46a87fc90142d64breed@android.com	error = _HB_OPEN_Get_Class( &csf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL );
19495469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( error && error != HB_Err_Not_Covered )
19505469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  goto End;
19515469607a00d84a07dc638eda46a87fc90142d64breed@android.com	known_classes = i;
19525469607a00d84a07dc638eda46a87fc90142d64breed@android.com      }
19535469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19545469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( cl[i - 1] != classes[i] )
19555469607a00d84a07dc638eda46a87fc90142d64breed@android.com	goto next_subclassrule;
19565469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
19575469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19585469607a00d84a07dc638eda46a87fc90142d64breed@android.com    error = Do_ContextSubst( gsub, sr->GlyphCount,
19595469607a00d84a07dc638eda46a87fc90142d64breed@android.com			     sr->SubstCount, sr->SubstLookupRecord,
19605469607a00d84a07dc638eda46a87fc90142d64breed@android.com			     buffer,
19615469607a00d84a07dc638eda46a87fc90142d64breed@android.com			     nesting_level );
19625469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto End;
19635469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19645469607a00d84a07dc638eda46a87fc90142d64breed@android.com  next_subclassrule:
19655469607a00d84a07dc638eda46a87fc90142d64breed@android.com    ;
19665469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
19675469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19685469607a00d84a07dc638eda46a87fc90142d64breed@android.com  error = HB_Err_Not_Covered;
19695469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19705469607a00d84a07dc638eda46a87fc90142d64breed@android.comEnd:
19715469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( classes );
19725469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
19735469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
19745469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19755469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19765469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Lookup_ContextSubst3( HB_GSUBHeader*          gsub,
19775469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_ContextSubstFormat3* csf3,
19785469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_Buffer               buffer,
19795469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_UShort                flags,
19805469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_UShort                context_length,
19815469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       int                      nesting_level )
19825469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
19835469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error         error;
19845469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort        index, i, j, property;
19855469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19865469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Coverage*    c;
19875469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_GDEFHeader*  gdef;
19885469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19895469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19905469607a00d84a07dc638eda46a87fc90142d64breed@android.com  gdef = gsub->gdef;
19915469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19925469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
19935469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
19945469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19955469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( context_length != 0xFFFF && context_length < csf3->GlyphCount )
19965469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return HB_Err_Not_Covered;
19975469607a00d84a07dc638eda46a87fc90142d64breed@android.com
19985469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( buffer->in_pos + csf3->GlyphCount > buffer->in_length )
19995469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return HB_Err_Not_Covered;         /* context is too long */
20005469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20015469607a00d84a07dc638eda46a87fc90142d64breed@android.com  c    = csf3->Coverage;
20025469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20035469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( i = 1, j = buffer->in_pos + 1; i < csf3->GlyphCount; i++, j++ )
20045469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
20055469607a00d84a07dc638eda46a87fc90142d64breed@android.com    while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
20065469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
20075469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( error && error != HB_Err_Not_Covered )
20085469607a00d84a07dc638eda46a87fc90142d64breed@android.com	return error;
20095469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20105469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( j + csf3->GlyphCount - i == (HB_Int)buffer->in_length )
20115469607a00d84a07dc638eda46a87fc90142d64breed@android.com	return HB_Err_Not_Covered;
20125469607a00d84a07dc638eda46a87fc90142d64breed@android.com      j++;
20135469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
20145469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20155469607a00d84a07dc638eda46a87fc90142d64breed@android.com    error = _HB_OPEN_Coverage_Index( &c[i], IN_GLYPH( j ), &index );
20165469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( error )
20175469607a00d84a07dc638eda46a87fc90142d64breed@android.com      return error;
20185469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
20195469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20205469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return Do_ContextSubst( gsub, csf3->GlyphCount,
20215469607a00d84a07dc638eda46a87fc90142d64breed@android.com			  csf3->SubstCount, csf3->SubstLookupRecord,
20225469607a00d84a07dc638eda46a87fc90142d64breed@android.com			  buffer,
20235469607a00d84a07dc638eda46a87fc90142d64breed@android.com			  nesting_level );
20245469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
20255469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20265469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20275469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Lookup_ContextSubst( HB_GSUBHeader*    gsub,
20285469607a00d84a07dc638eda46a87fc90142d64breed@android.com				      HB_GSUB_SubTable* st,
20295469607a00d84a07dc638eda46a87fc90142d64breed@android.com				      HB_Buffer         buffer,
20305469607a00d84a07dc638eda46a87fc90142d64breed@android.com				      HB_UShort          flags,
20315469607a00d84a07dc638eda46a87fc90142d64breed@android.com				      HB_UShort          context_length,
20325469607a00d84a07dc638eda46a87fc90142d64breed@android.com				      int                nesting_level )
20335469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
20345469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ContextSubst*  cs = &st->context;
20355469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20365469607a00d84a07dc638eda46a87fc90142d64breed@android.com  switch ( cs->SubstFormat )
20375469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
20385469607a00d84a07dc638eda46a87fc90142d64breed@android.com  case 1:  return Lookup_ContextSubst1( gsub, &cs->csf.csf1, buffer, flags, context_length, nesting_level );
20395469607a00d84a07dc638eda46a87fc90142d64breed@android.com  case 2:  return Lookup_ContextSubst2( gsub, &cs->csf.csf2, buffer, flags, context_length, nesting_level );
20405469607a00d84a07dc638eda46a87fc90142d64breed@android.com  case 3:  return Lookup_ContextSubst3( gsub, &cs->csf.csf3, buffer, flags, context_length, nesting_level );
20415469607a00d84a07dc638eda46a87fc90142d64breed@android.com  default: return ERR(HB_Err_Invalid_SubTable_Format);
20425469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
20435469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20445469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;               /* never reached */
20455469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
20465469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20475469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20485469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* LookupType 6 */
20495469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20505469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* ChainSubRule */
20515469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20525469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_ChainSubRule( HB_ChainSubRule*  csr,
20535469607a00d84a07dc638eda46a87fc90142d64breed@android.com				    HB_Stream          stream )
20545469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
20555469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
20565469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20575469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort               n, count;
20585469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*              b;
20595469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*              i;
20605469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*              l;
20615469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20625469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_SubstLookupRecord*  slr;
20635469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20645469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20655469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
20665469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
20675469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20685469607a00d84a07dc638eda46a87fc90142d64breed@android.com  csr->BacktrackGlyphCount = GET_UShort();
20695469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20705469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
20715469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20725469607a00d84a07dc638eda46a87fc90142d64breed@android.com  csr->Backtrack = NULL;
20735469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20745469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = csr->BacktrackGlyphCount;
20755469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20765469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( csr->Backtrack, count, HB_UShort ) )
20775469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
20785469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20795469607a00d84a07dc638eda46a87fc90142d64breed@android.com  b = csr->Backtrack;
20805469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20815469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( count * 2L ) )
20825469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail4;
20835469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20845469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
20855469607a00d84a07dc638eda46a87fc90142d64breed@android.com    b[n] = GET_UShort();
20865469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20875469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
20885469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20895469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
20905469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail4;
20915469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20925469607a00d84a07dc638eda46a87fc90142d64breed@android.com  csr->InputGlyphCount = GET_UShort();
20935469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20945469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
20955469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20965469607a00d84a07dc638eda46a87fc90142d64breed@android.com  csr->Input = NULL;
20975469607a00d84a07dc638eda46a87fc90142d64breed@android.com
20985469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = csr->InputGlyphCount - 1;  /* only InputGlyphCount - 1 elements */
20995469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21005469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( csr->Input, count, HB_UShort ) )
21015469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail4;
21025469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21035469607a00d84a07dc638eda46a87fc90142d64breed@android.com  i = csr->Input;
21045469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21055469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( count * 2L ) )
21065469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail3;
21075469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21085469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
21095469607a00d84a07dc638eda46a87fc90142d64breed@android.com    i[n] = GET_UShort();
21105469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21115469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
21125469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21135469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
21145469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail3;
21155469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21165469607a00d84a07dc638eda46a87fc90142d64breed@android.com  csr->LookaheadGlyphCount = GET_UShort();
21175469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21185469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
21195469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21205469607a00d84a07dc638eda46a87fc90142d64breed@android.com  csr->Lookahead = NULL;
21215469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21225469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = csr->LookaheadGlyphCount;
21235469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21245469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( csr->Lookahead, count, HB_UShort ) )
21255469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail3;
21265469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21275469607a00d84a07dc638eda46a87fc90142d64breed@android.com  l = csr->Lookahead;
21285469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21295469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( count * 2L ) )
21305469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
21315469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21325469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
21335469607a00d84a07dc638eda46a87fc90142d64breed@android.com    l[n] = GET_UShort();
21345469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21355469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
21365469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21375469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
21385469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
21395469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21405469607a00d84a07dc638eda46a87fc90142d64breed@android.com  csr->SubstCount = GET_UShort();
21415469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21425469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
21435469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21445469607a00d84a07dc638eda46a87fc90142d64breed@android.com  csr->SubstLookupRecord = NULL;
21455469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21465469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = csr->SubstCount;
21475469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21485469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( csr->SubstLookupRecord, count, HB_SubstLookupRecord ) )
21495469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
21505469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21515469607a00d84a07dc638eda46a87fc90142d64breed@android.com  slr = csr->SubstLookupRecord;
21525469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21535469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( count * 4L ) )
21545469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail1;
21555469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21565469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
21575469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
21585469607a00d84a07dc638eda46a87fc90142d64breed@android.com    slr[n].SequenceIndex   = GET_UShort();
21595469607a00d84a07dc638eda46a87fc90142d64breed@android.com    slr[n].LookupListIndex = GET_UShort();
21605469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
21615469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21625469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
21635469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21645469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
21655469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21665469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail1:
21675469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( slr );
21685469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21695469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail2:
21705469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( l );
21715469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21725469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail3:
21735469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( i );
21745469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21755469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail4:
21765469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( b );
21775469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
21785469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
21795469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21805469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21815469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_ChainSubRule( HB_ChainSubRule*  csr )
21825469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
21835469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( csr->SubstLookupRecord );
21845469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( csr->Lookahead );
21855469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( csr->Input );
21865469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( csr->Backtrack );
21875469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
21885469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21895469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21905469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* ChainSubRuleSet */
21915469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21925469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_ChainSubRuleSet( HB_ChainSubRuleSet*  csrs,
21935469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_Stream             stream )
21945469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
21955469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
21965469607a00d84a07dc638eda46a87fc90142d64breed@android.com
21975469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort          n = 0, m, count;
21985469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt           cur_offset, new_offset, base_offset;
21995469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22005469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ChainSubRule*  csr;
22015469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22025469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22035469607a00d84a07dc638eda46a87fc90142d64breed@android.com  base_offset = FILE_Pos();
22045469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22055469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
22065469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
22075469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22085469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = csrs->ChainSubRuleCount = GET_UShort();
22095469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22105469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
22115469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22125469607a00d84a07dc638eda46a87fc90142d64breed@android.com  csrs->ChainSubRule = NULL;
22135469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22145469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( csrs->ChainSubRule, count, HB_ChainSubRule ) )
22155469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
22165469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22175469607a00d84a07dc638eda46a87fc90142d64breed@android.com  csr = csrs->ChainSubRule;
22185469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22195469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
22205469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
22215469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ACCESS_Frame( 2L ) )
22225469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail;
22235469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22245469607a00d84a07dc638eda46a87fc90142d64breed@android.com    new_offset = GET_UShort() + base_offset;
22255469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22265469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FORGET_Frame();
22275469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22285469607a00d84a07dc638eda46a87fc90142d64breed@android.com    cur_offset = FILE_Pos();
22295469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( FILE_Seek( new_offset ) ||
22305469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 ( error = Load_ChainSubRule( &csr[n], stream ) ) != HB_Err_Ok )
22315469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail;
22325469607a00d84a07dc638eda46a87fc90142d64breed@android.com    (void)FILE_Seek( cur_offset );
22335469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
22345469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22355469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
22365469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22375469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail:
22385469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( m = 0; m < n; m++ )
22395469607a00d84a07dc638eda46a87fc90142d64breed@android.com    Free_ChainSubRule( &csr[m] );
22405469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22415469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( csr );
22425469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
22435469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
22445469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22455469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22465469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_ChainSubRuleSet( HB_ChainSubRuleSet*  csrs )
22475469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
22485469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort          n, count;
22495469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22505469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ChainSubRule*  csr;
22515469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22525469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22535469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( csrs->ChainSubRule )
22545469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
22555469607a00d84a07dc638eda46a87fc90142d64breed@android.com    count = csrs->ChainSubRuleCount;
22565469607a00d84a07dc638eda46a87fc90142d64breed@android.com    csr   = csrs->ChainSubRule;
22575469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22585469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( n = 0; n < count; n++ )
22595469607a00d84a07dc638eda46a87fc90142d64breed@android.com      Free_ChainSubRule( &csr[n] );
22605469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22615469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FREE( csr );
22625469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
22635469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
22645469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22655469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22665469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* ChainContextSubstFormat1 */
22675469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22685469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_ChainContextSubst1(
22695469607a00d84a07dc638eda46a87fc90142d64breed@android.com		   HB_ChainContextSubstFormat1*  ccsf1,
22705469607a00d84a07dc638eda46a87fc90142d64breed@android.com		   HB_Stream                      stream )
22715469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
22725469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
22735469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22745469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort             n = 0, m, count;
22755469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt              cur_offset, new_offset, base_offset;
22765469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22775469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ChainSubRuleSet*  csrs;
22785469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22795469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22805469607a00d84a07dc638eda46a87fc90142d64breed@android.com  base_offset = FILE_Pos() - 2L;
22815469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22825469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
22835469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
22845469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22855469607a00d84a07dc638eda46a87fc90142d64breed@android.com  new_offset = GET_UShort() + base_offset;
22865469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22875469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
22885469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22895469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cur_offset = FILE_Pos();
22905469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( FILE_Seek( new_offset ) ||
22915469607a00d84a07dc638eda46a87fc90142d64breed@android.com       ( error = _HB_OPEN_Load_Coverage( &ccsf1->Coverage, stream ) ) != HB_Err_Ok )
22925469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
22935469607a00d84a07dc638eda46a87fc90142d64breed@android.com  (void)FILE_Seek( cur_offset );
22945469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22955469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
22965469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
22975469607a00d84a07dc638eda46a87fc90142d64breed@android.com
22985469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = ccsf1->ChainSubRuleSetCount = GET_UShort();
22995469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23005469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
23015469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23025469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ccsf1->ChainSubRuleSet = NULL;
23035469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23045469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( ccsf1->ChainSubRuleSet, count, HB_ChainSubRuleSet ) )
23055469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
23065469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23075469607a00d84a07dc638eda46a87fc90142d64breed@android.com  csrs = ccsf1->ChainSubRuleSet;
23085469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23095469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
23105469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
23115469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ACCESS_Frame( 2L ) )
23125469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail1;
23135469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23145469607a00d84a07dc638eda46a87fc90142d64breed@android.com    new_offset = GET_UShort() + base_offset;
23155469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23165469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FORGET_Frame();
23175469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23185469607a00d84a07dc638eda46a87fc90142d64breed@android.com    cur_offset = FILE_Pos();
23195469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( FILE_Seek( new_offset ) ||
23205469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 ( error = Load_ChainSubRuleSet( &csrs[n], stream ) ) != HB_Err_Ok )
23215469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail1;
23225469607a00d84a07dc638eda46a87fc90142d64breed@android.com    (void)FILE_Seek( cur_offset );
23235469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
23245469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23255469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
23265469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23275469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail1:
23285469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( m = 0; m < n; m++ )
23295469607a00d84a07dc638eda46a87fc90142d64breed@android.com    Free_ChainSubRuleSet( &csrs[m] );
23305469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23315469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( csrs );
23325469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23335469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail2:
23345469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_Coverage( &ccsf1->Coverage );
23355469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
23365469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
23375469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23385469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23395469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_ChainContextSubst1( HB_ChainContextSubstFormat1*  ccsf1 )
23405469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
23415469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort             n, count;
23425469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23435469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ChainSubRuleSet*  csrs;
23445469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23455469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23465469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ccsf1->ChainSubRuleSet )
23475469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
23485469607a00d84a07dc638eda46a87fc90142d64breed@android.com    count = ccsf1->ChainSubRuleSetCount;
23495469607a00d84a07dc638eda46a87fc90142d64breed@android.com    csrs  = ccsf1->ChainSubRuleSet;
23505469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23515469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( n = 0; n < count; n++ )
23525469607a00d84a07dc638eda46a87fc90142d64breed@android.com      Free_ChainSubRuleSet( &csrs[n] );
23535469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23545469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FREE( csrs );
23555469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
23565469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23575469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_Coverage( &ccsf1->Coverage );
23585469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
23595469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23605469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23615469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* ChainSubClassRule */
23625469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23635469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_ChainSubClassRule(
23645469607a00d84a07dc638eda46a87fc90142d64breed@android.com		   HB_ChainContextSubstFormat2*  ccsf2,
23655469607a00d84a07dc638eda46a87fc90142d64breed@android.com		   HB_ChainSubClassRule*         cscr,
23665469607a00d84a07dc638eda46a87fc90142d64breed@android.com		   HB_Stream                      stream )
23675469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
23685469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
23695469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23705469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort               n, count;
23715469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23725469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*              b;
23735469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*              i;
23745469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*              l;
23755469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_SubstLookupRecord*  slr;
23765469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23775469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23785469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
23795469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
23805469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23815469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cscr->BacktrackGlyphCount = GET_UShort();
23825469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23835469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
23845469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23855469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( cscr->BacktrackGlyphCount > ccsf2->MaxBacktrackLength )
23865469607a00d84a07dc638eda46a87fc90142d64breed@android.com    ccsf2->MaxBacktrackLength = cscr->BacktrackGlyphCount;
23875469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23885469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cscr->Backtrack = NULL;
23895469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23905469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = cscr->BacktrackGlyphCount;
23915469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23925469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( cscr->Backtrack, count, HB_UShort ) )
23935469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
23945469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23955469607a00d84a07dc638eda46a87fc90142d64breed@android.com  b = cscr->Backtrack;
23965469607a00d84a07dc638eda46a87fc90142d64breed@android.com
23975469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( count * 2L ) )
23985469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail4;
23995469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24005469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
24015469607a00d84a07dc638eda46a87fc90142d64breed@android.com    b[n] = GET_UShort();
24025469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24035469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
24045469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24055469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
24065469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail4;
24075469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24085469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cscr->InputGlyphCount = GET_UShort();
24095469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24105469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
24115469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24125469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( cscr->InputGlyphCount > ccsf2->MaxInputLength )
24135469607a00d84a07dc638eda46a87fc90142d64breed@android.com    ccsf2->MaxInputLength = cscr->InputGlyphCount;
24145469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24155469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cscr->Input = NULL;
24165469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24175469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = cscr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
24185469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24195469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( cscr->Input, count, HB_UShort ) )
24205469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail4;
24215469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24225469607a00d84a07dc638eda46a87fc90142d64breed@android.com  i = cscr->Input;
24235469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24245469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( count * 2L ) )
24255469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail3;
24265469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24275469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
24285469607a00d84a07dc638eda46a87fc90142d64breed@android.com    i[n] = GET_UShort();
24295469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24305469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
24315469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24325469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
24335469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail3;
24345469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24355469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cscr->LookaheadGlyphCount = GET_UShort();
24365469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24375469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
24385469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24395469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( cscr->LookaheadGlyphCount > ccsf2->MaxLookaheadLength )
24405469607a00d84a07dc638eda46a87fc90142d64breed@android.com    ccsf2->MaxLookaheadLength = cscr->LookaheadGlyphCount;
24415469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24425469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cscr->Lookahead = NULL;
24435469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24445469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = cscr->LookaheadGlyphCount;
24455469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24465469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( cscr->Lookahead, count, HB_UShort ) )
24475469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail3;
24485469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24495469607a00d84a07dc638eda46a87fc90142d64breed@android.com  l = cscr->Lookahead;
24505469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24515469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( count * 2L ) )
24525469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
24535469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24545469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
24555469607a00d84a07dc638eda46a87fc90142d64breed@android.com    l[n] = GET_UShort();
24565469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24575469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
24585469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24595469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
24605469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
24615469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24625469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cscr->SubstCount = GET_UShort();
24635469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24645469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
24655469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24665469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cscr->SubstLookupRecord = NULL;
24675469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24685469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = cscr->SubstCount;
24695469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24705469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( cscr->SubstLookupRecord, count,
24715469607a00d84a07dc638eda46a87fc90142d64breed@android.com		    HB_SubstLookupRecord ) )
24725469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
24735469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24745469607a00d84a07dc638eda46a87fc90142d64breed@android.com  slr = cscr->SubstLookupRecord;
24755469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24765469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( count * 4L ) )
24775469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail1;
24785469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24795469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
24805469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
24815469607a00d84a07dc638eda46a87fc90142d64breed@android.com    slr[n].SequenceIndex   = GET_UShort();
24825469607a00d84a07dc638eda46a87fc90142d64breed@android.com    slr[n].LookupListIndex = GET_UShort();
24835469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
24845469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24855469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
24865469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24875469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
24885469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24895469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail1:
24905469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( slr );
24915469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24925469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail2:
24935469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( l );
24945469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24955469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail3:
24965469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( i );
24975469607a00d84a07dc638eda46a87fc90142d64breed@android.com
24985469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail4:
24995469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( b );
25005469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
25015469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
25025469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25035469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25045469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_ChainSubClassRule( HB_ChainSubClassRule*  cscr )
25055469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
25065469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( cscr->SubstLookupRecord );
25075469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( cscr->Lookahead );
25085469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( cscr->Input );
25095469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( cscr->Backtrack );
25105469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
25115469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25125469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25135469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* SubClassSet */
25145469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25155469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_ChainSubClassSet(
25165469607a00d84a07dc638eda46a87fc90142d64breed@android.com		   HB_ChainContextSubstFormat2*  ccsf2,
25175469607a00d84a07dc638eda46a87fc90142d64breed@android.com		   HB_ChainSubClassSet*          cscs,
25185469607a00d84a07dc638eda46a87fc90142d64breed@android.com		   HB_Stream                      stream )
25195469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
25205469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
25215469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25225469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort               n = 0, m, count;
25235469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt                cur_offset, new_offset, base_offset;
25245469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25255469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ChainSubClassRule*  cscr;
25265469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25275469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25285469607a00d84a07dc638eda46a87fc90142d64breed@android.com  base_offset = FILE_Pos();
25295469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25305469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
25315469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
25325469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25335469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = cscs->ChainSubClassRuleCount = GET_UShort();
25345469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25355469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
25365469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25375469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cscs->ChainSubClassRule = NULL;
25385469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25395469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( cscs->ChainSubClassRule, count,
25405469607a00d84a07dc638eda46a87fc90142d64breed@android.com		    HB_ChainSubClassRule ) )
25415469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
25425469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25435469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cscr = cscs->ChainSubClassRule;
25445469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25455469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
25465469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
25475469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ACCESS_Frame( 2L ) )
25485469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail;
25495469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25505469607a00d84a07dc638eda46a87fc90142d64breed@android.com    new_offset = GET_UShort() + base_offset;
25515469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25525469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FORGET_Frame();
25535469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25545469607a00d84a07dc638eda46a87fc90142d64breed@android.com    cur_offset = FILE_Pos();
25555469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( FILE_Seek( new_offset ) ||
25565469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 ( error = Load_ChainSubClassRule( ccsf2, &cscr[n],
25575469607a00d84a07dc638eda46a87fc90142d64breed@android.com					   stream ) ) != HB_Err_Ok )
25585469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail;
25595469607a00d84a07dc638eda46a87fc90142d64breed@android.com    (void)FILE_Seek( cur_offset );
25605469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
25615469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25625469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
25635469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25645469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail:
25655469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( m = 0; m < n; m++ )
25665469607a00d84a07dc638eda46a87fc90142d64breed@android.com    Free_ChainSubClassRule( &cscr[m] );
25675469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25685469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( cscr );
25695469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
25705469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
25715469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25725469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25735469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_ChainSubClassSet( HB_ChainSubClassSet*  cscs )
25745469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
25755469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort               n, count;
25765469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25775469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ChainSubClassRule*  cscr;
25785469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25795469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25805469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( cscs->ChainSubClassRule )
25815469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
25825469607a00d84a07dc638eda46a87fc90142d64breed@android.com    count = cscs->ChainSubClassRuleCount;
25835469607a00d84a07dc638eda46a87fc90142d64breed@android.com    cscr  = cscs->ChainSubClassRule;
25845469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25855469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( n = 0; n < count; n++ )
25865469607a00d84a07dc638eda46a87fc90142d64breed@android.com      Free_ChainSubClassRule( &cscr[n] );
25875469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25885469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FREE( cscr );
25895469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
25905469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
25915469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25925469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25935469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* ChainContextSubstFormat2 */
25945469607a00d84a07dc638eda46a87fc90142d64breed@android.com
25955469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_ChainContextSubst2(
25965469607a00d84a07dc638eda46a87fc90142d64breed@android.com		   HB_ChainContextSubstFormat2*  ccsf2,
25975469607a00d84a07dc638eda46a87fc90142d64breed@android.com		   HB_Stream                      stream )
25985469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
25995469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
26005469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26015469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort              n = 0, m, count;
26025469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt               cur_offset, new_offset, base_offset;
26035469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt               backtrack_offset, input_offset, lookahead_offset;
26045469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26055469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ChainSubClassSet*  cscs;
26065469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26075469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26085469607a00d84a07dc638eda46a87fc90142d64breed@android.com  base_offset = FILE_Pos() - 2;
26095469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26105469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
26115469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
26125469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26135469607a00d84a07dc638eda46a87fc90142d64breed@android.com  new_offset = GET_UShort() + base_offset;
26145469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26155469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
26165469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26175469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cur_offset = FILE_Pos();
26185469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( FILE_Seek( new_offset ) ||
26195469607a00d84a07dc638eda46a87fc90142d64breed@android.com       ( error = _HB_OPEN_Load_Coverage( &ccsf2->Coverage, stream ) ) != HB_Err_Ok )
26205469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
26215469607a00d84a07dc638eda46a87fc90142d64breed@android.com  (void)FILE_Seek( cur_offset );
26225469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26235469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 8L ) )
26245469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail5;
26255469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26265469607a00d84a07dc638eda46a87fc90142d64breed@android.com  backtrack_offset = GET_UShort();
26275469607a00d84a07dc638eda46a87fc90142d64breed@android.com  input_offset     = GET_UShort();
26285469607a00d84a07dc638eda46a87fc90142d64breed@android.com  lookahead_offset = GET_UShort();
26295469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26305469607a00d84a07dc638eda46a87fc90142d64breed@android.com  /* `ChainSubClassSetCount' is the upper limit for input class values,
26315469607a00d84a07dc638eda46a87fc90142d64breed@android.com     thus we read it now to make an additional safety check. No limit
26325469607a00d84a07dc638eda46a87fc90142d64breed@android.com     is known or needed for the other two class definitions          */
26335469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26345469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = ccsf2->ChainSubClassSetCount = GET_UShort();
26355469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26365469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
26375469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26385469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->BacktrackClassDef, 65535,
26395469607a00d84a07dc638eda46a87fc90142d64breed@android.com						       backtrack_offset, base_offset,
26405469607a00d84a07dc638eda46a87fc90142d64breed@android.com						       stream ) ) != HB_Err_Ok )
26415469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail5;
26425469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26435469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->InputClassDef, count,
26445469607a00d84a07dc638eda46a87fc90142d64breed@android.com						       input_offset, base_offset,
26455469607a00d84a07dc638eda46a87fc90142d64breed@android.com						       stream ) ) != HB_Err_Ok )
26465469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail4;
26475469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccsf2->LookaheadClassDef, 65535,
26485469607a00d84a07dc638eda46a87fc90142d64breed@android.com						       lookahead_offset, base_offset,
26495469607a00d84a07dc638eda46a87fc90142d64breed@android.com						       stream ) ) != HB_Err_Ok )
26505469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail3;
26515469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26525469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ccsf2->ChainSubClassSet   = NULL;
26535469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ccsf2->MaxBacktrackLength = 0;
26545469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ccsf2->MaxInputLength     = 0;
26555469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ccsf2->MaxLookaheadLength = 0;
26565469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26575469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( ccsf2->ChainSubClassSet, count, HB_ChainSubClassSet ) )
26585469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
26595469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26605469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cscs = ccsf2->ChainSubClassSet;
26615469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26625469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
26635469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
26645469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ACCESS_Frame( 2L ) )
26655469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail1;
26665469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26675469607a00d84a07dc638eda46a87fc90142d64breed@android.com    new_offset = GET_UShort() + base_offset;
26685469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26695469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FORGET_Frame();
26705469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26715469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( new_offset != base_offset )      /* not a NULL offset */
26725469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
26735469607a00d84a07dc638eda46a87fc90142d64breed@android.com      cur_offset = FILE_Pos();
26745469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( FILE_Seek( new_offset ) ||
26755469607a00d84a07dc638eda46a87fc90142d64breed@android.com	   ( error = Load_ChainSubClassSet( ccsf2, &cscs[n],
26765469607a00d84a07dc638eda46a87fc90142d64breed@android.com					    stream ) ) != HB_Err_Ok )
26775469607a00d84a07dc638eda46a87fc90142d64breed@android.com	goto Fail1;
26785469607a00d84a07dc638eda46a87fc90142d64breed@android.com      (void)FILE_Seek( cur_offset );
26795469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
26805469607a00d84a07dc638eda46a87fc90142d64breed@android.com    else
26815469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
26825469607a00d84a07dc638eda46a87fc90142d64breed@android.com      /* we create a ChainSubClassSet table with no entries */
26835469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26845469607a00d84a07dc638eda46a87fc90142d64breed@android.com      ccsf2->ChainSubClassSet[n].ChainSubClassRuleCount = 0;
26855469607a00d84a07dc638eda46a87fc90142d64breed@android.com      ccsf2->ChainSubClassSet[n].ChainSubClassRule      = NULL;
26865469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
26875469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
26885469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26895469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
26905469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26915469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail1:
26925469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( m = 0; m < n; m++ )
26935469607a00d84a07dc638eda46a87fc90142d64breed@android.com    Free_ChainSubClassSet( &cscs[m] );
26945469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26955469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( cscs );
26965469607a00d84a07dc638eda46a87fc90142d64breed@android.com
26975469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail2:
26985469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_ClassDefinition( &ccsf2->LookaheadClassDef );
26995469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27005469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail3:
27015469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_ClassDefinition( &ccsf2->InputClassDef );
27025469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27035469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail4:
27045469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_ClassDefinition( &ccsf2->BacktrackClassDef );
27055469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27065469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail5:
27075469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_Coverage( &ccsf2->Coverage );
27085469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
27095469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
27105469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27115469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27125469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_ChainContextSubst2( HB_ChainContextSubstFormat2*  ccsf2 )
27135469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
27145469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort              n, count;
27155469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27165469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ChainSubClassSet*  cscs;
27175469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27185469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27195469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ccsf2->ChainSubClassSet )
27205469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
27215469607a00d84a07dc638eda46a87fc90142d64breed@android.com    count = ccsf2->ChainSubClassSetCount;
27225469607a00d84a07dc638eda46a87fc90142d64breed@android.com    cscs  = ccsf2->ChainSubClassSet;
27235469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27245469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( n = 0; n < count; n++ )
27255469607a00d84a07dc638eda46a87fc90142d64breed@android.com      Free_ChainSubClassSet( &cscs[n] );
27265469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27275469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FREE( cscs );
27285469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
27295469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27305469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_ClassDefinition( &ccsf2->LookaheadClassDef );
27315469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_ClassDefinition( &ccsf2->InputClassDef );
27325469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_ClassDefinition( &ccsf2->BacktrackClassDef );
27335469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27345469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_Coverage( &ccsf2->Coverage );
27355469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
27365469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27375469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27385469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* ChainContextSubstFormat3 */
27395469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27405469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_ChainContextSubst3(
27415469607a00d84a07dc638eda46a87fc90142d64breed@android.com		   HB_ChainContextSubstFormat3*  ccsf3,
27425469607a00d84a07dc638eda46a87fc90142d64breed@android.com		   HB_Stream                      stream )
27435469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
27445469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
27455469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27465469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort               n, nb = 0, ni =0, nl = 0, m, count;
27475469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort               backtrack_count, input_count, lookahead_count;
27485469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt                cur_offset, new_offset, base_offset;
27495469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27505469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Coverage*           b;
27515469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Coverage*           i;
27525469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Coverage*           l;
27535469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_SubstLookupRecord*  slr;
27545469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27555469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27565469607a00d84a07dc638eda46a87fc90142d64breed@android.com  base_offset = FILE_Pos() - 2L;
27575469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27585469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
27595469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
27605469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27615469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ccsf3->BacktrackGlyphCount = GET_UShort();
27625469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27635469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
27645469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27655469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ccsf3->BacktrackCoverage = NULL;
27665469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27675469607a00d84a07dc638eda46a87fc90142d64breed@android.com  backtrack_count = ccsf3->BacktrackGlyphCount;
27685469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27695469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( ccsf3->BacktrackCoverage, backtrack_count,
27705469607a00d84a07dc638eda46a87fc90142d64breed@android.com		    HB_Coverage ) )
27715469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
27725469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27735469607a00d84a07dc638eda46a87fc90142d64breed@android.com  b = ccsf3->BacktrackCoverage;
27745469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27755469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( nb = 0; nb < backtrack_count; nb++ )
27765469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
27775469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ACCESS_Frame( 2L ) )
27785469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail4;
27795469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27805469607a00d84a07dc638eda46a87fc90142d64breed@android.com    new_offset = GET_UShort() + base_offset;
27815469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27825469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FORGET_Frame();
27835469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27845469607a00d84a07dc638eda46a87fc90142d64breed@android.com    cur_offset = FILE_Pos();
27855469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( FILE_Seek( new_offset ) ||
27865469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != HB_Err_Ok )
27875469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail4;
27885469607a00d84a07dc638eda46a87fc90142d64breed@android.com    (void)FILE_Seek( cur_offset );
27895469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
27905469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27915469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
27925469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail4;
27935469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27945469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ccsf3->InputGlyphCount = GET_UShort();
27955469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27965469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
27975469607a00d84a07dc638eda46a87fc90142d64breed@android.com
27985469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ccsf3->InputCoverage = NULL;
27995469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28005469607a00d84a07dc638eda46a87fc90142d64breed@android.com  input_count = ccsf3->InputGlyphCount;
28015469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28025469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( ccsf3->InputCoverage, input_count, HB_Coverage ) )
28035469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail4;
28045469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28055469607a00d84a07dc638eda46a87fc90142d64breed@android.com  i = ccsf3->InputCoverage;
28065469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28075469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( ni = 0; ni < input_count; ni++ )
28085469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
28095469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ACCESS_Frame( 2L ) )
28105469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail3;
28115469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28125469607a00d84a07dc638eda46a87fc90142d64breed@android.com    new_offset = GET_UShort() + base_offset;
28135469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28145469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FORGET_Frame();
28155469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28165469607a00d84a07dc638eda46a87fc90142d64breed@android.com    cur_offset = FILE_Pos();
28175469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( FILE_Seek( new_offset ) ||
28185469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 ( error = _HB_OPEN_Load_Coverage( &i[ni], stream ) ) != HB_Err_Ok )
28195469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail3;
28205469607a00d84a07dc638eda46a87fc90142d64breed@android.com    (void)FILE_Seek( cur_offset );
28215469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
28225469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28235469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
28245469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail3;
28255469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28265469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ccsf3->LookaheadGlyphCount = GET_UShort();
28275469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28285469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
28295469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28305469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ccsf3->LookaheadCoverage = NULL;
28315469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28325469607a00d84a07dc638eda46a87fc90142d64breed@android.com  lookahead_count = ccsf3->LookaheadGlyphCount;
28335469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28345469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( ccsf3->LookaheadCoverage, lookahead_count,
28355469607a00d84a07dc638eda46a87fc90142d64breed@android.com		    HB_Coverage ) )
28365469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail3;
28375469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28385469607a00d84a07dc638eda46a87fc90142d64breed@android.com  l = ccsf3->LookaheadCoverage;
28395469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28405469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( nl = 0; nl < lookahead_count; nl++ )
28415469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
28425469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ACCESS_Frame( 2L ) )
28435469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail2;
28445469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28455469607a00d84a07dc638eda46a87fc90142d64breed@android.com    new_offset = GET_UShort() + base_offset;
28465469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28475469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FORGET_Frame();
28485469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28495469607a00d84a07dc638eda46a87fc90142d64breed@android.com    cur_offset = FILE_Pos();
28505469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( FILE_Seek( new_offset ) ||
28515469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != HB_Err_Ok )
28525469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail2;
28535469607a00d84a07dc638eda46a87fc90142d64breed@android.com    (void)FILE_Seek( cur_offset );
28545469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
28555469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28565469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
28575469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
28585469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28595469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ccsf3->SubstCount = GET_UShort();
28605469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28615469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
28625469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28635469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ccsf3->SubstLookupRecord = NULL;
28645469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28655469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = ccsf3->SubstCount;
28665469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28675469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( ccsf3->SubstLookupRecord, count,
28685469607a00d84a07dc638eda46a87fc90142d64breed@android.com		    HB_SubstLookupRecord ) )
28695469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
28705469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28715469607a00d84a07dc638eda46a87fc90142d64breed@android.com  slr = ccsf3->SubstLookupRecord;
28725469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28735469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( count * 4L ) )
28745469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail1;
28755469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28765469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
28775469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
28785469607a00d84a07dc638eda46a87fc90142d64breed@android.com    slr[n].SequenceIndex   = GET_UShort();
28795469607a00d84a07dc638eda46a87fc90142d64breed@android.com    slr[n].LookupListIndex = GET_UShort();
28805469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
28815469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28825469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
28835469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28845469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
28855469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28865469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail1:
28875469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( slr );
28885469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28895469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail2:
28905469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( m = 0; m < nl; m++ )
28915469607a00d84a07dc638eda46a87fc90142d64breed@android.com    _HB_OPEN_Free_Coverage( &l[m] );
28925469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28935469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( l );
28945469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28955469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail3:
28965469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( m = 0; m < ni; m++ )
28975469607a00d84a07dc638eda46a87fc90142d64breed@android.com    _HB_OPEN_Free_Coverage( &i[m] );
28985469607a00d84a07dc638eda46a87fc90142d64breed@android.com
28995469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( i );
29005469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29015469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail4:
29025469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( m = 0; m < nb; m++ )
29035469607a00d84a07dc638eda46a87fc90142d64breed@android.com    _HB_OPEN_Free_Coverage( &b[m] );
29045469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29055469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( b );
29065469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
29075469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
29085469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29095469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29105469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_ChainContextSubst3( HB_ChainContextSubstFormat3*  ccsf3 )
29115469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
29125469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort      n, count;
29135469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29145469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Coverage*  c;
29155469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29165469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29175469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( ccsf3->SubstLookupRecord );
29185469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29195469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ccsf3->LookaheadCoverage )
29205469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
29215469607a00d84a07dc638eda46a87fc90142d64breed@android.com    count = ccsf3->LookaheadGlyphCount;
29225469607a00d84a07dc638eda46a87fc90142d64breed@android.com    c     = ccsf3->LookaheadCoverage;
29235469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29245469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( n = 0; n < count; n++ )
29255469607a00d84a07dc638eda46a87fc90142d64breed@android.com      _HB_OPEN_Free_Coverage( &c[n] );
29265469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29275469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FREE( c );
29285469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
29295469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29305469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ccsf3->InputCoverage )
29315469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
29325469607a00d84a07dc638eda46a87fc90142d64breed@android.com    count = ccsf3->InputGlyphCount;
29335469607a00d84a07dc638eda46a87fc90142d64breed@android.com    c     = ccsf3->InputCoverage;
29345469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29355469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( n = 0; n < count; n++ )
29365469607a00d84a07dc638eda46a87fc90142d64breed@android.com      _HB_OPEN_Free_Coverage( &c[n] );
29375469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29385469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FREE( c );
29395469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
29405469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29415469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ccsf3->BacktrackCoverage )
29425469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
29435469607a00d84a07dc638eda46a87fc90142d64breed@android.com    count = ccsf3->BacktrackGlyphCount;
29445469607a00d84a07dc638eda46a87fc90142d64breed@android.com    c     = ccsf3->BacktrackCoverage;
29455469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29465469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( n = 0; n < count; n++ )
29475469607a00d84a07dc638eda46a87fc90142d64breed@android.com      _HB_OPEN_Free_Coverage( &c[n] );
29485469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29495469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FREE( c );
29505469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
29515469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
29525469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29535469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29545469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* ChainContextSubst */
29555469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29565469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_ChainContextSubst( HB_GSUB_SubTable* st,
29575469607a00d84a07dc638eda46a87fc90142d64breed@android.com					 HB_Stream         stream )
29585469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
29595469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
29605469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ChainContextSubst*  ccs = &st->chain;
29615469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29625469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
29635469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
29645469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29655469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ccs->SubstFormat = GET_UShort();
29665469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29675469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
29685469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29695469607a00d84a07dc638eda46a87fc90142d64breed@android.com  switch ( ccs->SubstFormat ) {
29705469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case 1:  return Load_ChainContextSubst1( &ccs->ccsf.ccsf1, stream );
29715469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case 2:  return Load_ChainContextSubst2( &ccs->ccsf.ccsf2, stream );
29725469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case 3:  return Load_ChainContextSubst3( &ccs->ccsf.ccsf3, stream );
29735469607a00d84a07dc638eda46a87fc90142d64breed@android.com    default: return ERR(HB_Err_Invalid_SubTable_Format);
29745469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
29755469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29765469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;               /* never reached */
29775469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
29785469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29795469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29805469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_ChainContextSubst( HB_GSUB_SubTable* st )
29815469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
29825469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ChainContextSubst*  ccs = &st->chain;
29835469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29845469607a00d84a07dc638eda46a87fc90142d64breed@android.com  switch ( ccs->SubstFormat ) {
29855469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case 1:  Free_ChainContextSubst1( &ccs->ccsf.ccsf1 ); break;
29865469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case 2:  Free_ChainContextSubst2( &ccs->ccsf.ccsf2 ); break;
29875469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case 3:  Free_ChainContextSubst3( &ccs->ccsf.ccsf3 ); break;
29885469607a00d84a07dc638eda46a87fc90142d64breed@android.com    default:							  break;
29895469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
29905469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
29915469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29925469607a00d84a07dc638eda46a87fc90142d64breed@android.com
29935469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Lookup_ChainContextSubst1( HB_GSUBHeader*               gsub,
29945469607a00d84a07dc638eda46a87fc90142d64breed@android.com					    HB_ChainContextSubstFormat1* ccsf1,
29955469607a00d84a07dc638eda46a87fc90142d64breed@android.com					    HB_Buffer                    buffer,
29965469607a00d84a07dc638eda46a87fc90142d64breed@android.com					    HB_UShort                     flags,
29975469607a00d84a07dc638eda46a87fc90142d64breed@android.com					    HB_UShort                     context_length,
29985469607a00d84a07dc638eda46a87fc90142d64breed@android.com					    int                           nesting_level )
29995469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
30005469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort          index, property;
30015469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort          i, j, k, num_csr;
30025469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort          bgc, igc, lgc;
30035469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error           error;
30045469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30055469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ChainSubRule*  csr;
30065469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ChainSubRule   curr_csr;
30075469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_GDEFHeader*    gdef;
30085469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30095469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30105469607a00d84a07dc638eda46a87fc90142d64breed@android.com  gdef = gsub->gdef;
30115469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30125469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
30135469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
30145469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30155469607a00d84a07dc638eda46a87fc90142d64breed@android.com  error = _HB_OPEN_Coverage_Index( &ccsf1->Coverage, IN_CURGLYPH(), &index );
30165469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( error )
30175469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
30185469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30195469607a00d84a07dc638eda46a87fc90142d64breed@android.com  csr     = ccsf1->ChainSubRuleSet[index].ChainSubRule;
30205469607a00d84a07dc638eda46a87fc90142d64breed@android.com  num_csr = ccsf1->ChainSubRuleSet[index].ChainSubRuleCount;
30215469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30225469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( k = 0; k < num_csr; k++ )
30235469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
30245469607a00d84a07dc638eda46a87fc90142d64breed@android.com    curr_csr = csr[k];
30255469607a00d84a07dc638eda46a87fc90142d64breed@android.com    bgc      = curr_csr.BacktrackGlyphCount;
30265469607a00d84a07dc638eda46a87fc90142d64breed@android.com    igc      = curr_csr.InputGlyphCount;
30275469607a00d84a07dc638eda46a87fc90142d64breed@android.com    lgc      = curr_csr.LookaheadGlyphCount;
30285469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30295469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( context_length != 0xFFFF && context_length < igc )
30305469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto next_chainsubrule;
30315469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30325469607a00d84a07dc638eda46a87fc90142d64breed@android.com    /* check whether context is too long; it is a first guess only */
30335469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30345469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length )
30355469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto next_chainsubrule;
30365469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30375469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( bgc )
30385469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
30395469607a00d84a07dc638eda46a87fc90142d64breed@android.com      /* since we don't know in advance the number of glyphs to inspect,
30405469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 we search backwards for matches in the backtrack glyph array    */
30415469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30425469607a00d84a07dc638eda46a87fc90142d64breed@android.com      for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
30435469607a00d84a07dc638eda46a87fc90142d64breed@android.com      {
30445469607a00d84a07dc638eda46a87fc90142d64breed@android.com	while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )
30455469607a00d84a07dc638eda46a87fc90142d64breed@android.com	{
30465469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  if ( error && error != HB_Err_Not_Covered )
30475469607a00d84a07dc638eda46a87fc90142d64breed@android.com	    return error;
30485469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30495469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  if ( j + 1 == bgc - i )
30505469607a00d84a07dc638eda46a87fc90142d64breed@android.com	    goto next_chainsubrule;
30515469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  j--;
30525469607a00d84a07dc638eda46a87fc90142d64breed@android.com	}
30535469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30545469607a00d84a07dc638eda46a87fc90142d64breed@android.com	/* In OpenType 1.3, it is undefined whether the offsets of
30555469607a00d84a07dc638eda46a87fc90142d64breed@android.com	   backtrack glyphs is in logical order or not.  Version 1.4
30565469607a00d84a07dc638eda46a87fc90142d64breed@android.com	   will clarify this:
30575469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30585469607a00d84a07dc638eda46a87fc90142d64breed@android.com	     Logical order -      a  b  c  d  e  f  g  h  i  j
30595469607a00d84a07dc638eda46a87fc90142d64breed@android.com					      i
30605469607a00d84a07dc638eda46a87fc90142d64breed@android.com	     Input offsets -                  0  1
30615469607a00d84a07dc638eda46a87fc90142d64breed@android.com	     Backtrack offsets -  3  2  1  0
30625469607a00d84a07dc638eda46a87fc90142d64breed@android.com	     Lookahead offsets -                    0  1  2  3           */
30635469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30645469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( OUT_GLYPH( j ) != curr_csr.Backtrack[i] )
30655469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  goto next_chainsubrule;
30665469607a00d84a07dc638eda46a87fc90142d64breed@android.com      }
30675469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
30685469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30695469607a00d84a07dc638eda46a87fc90142d64breed@android.com    /* Start at 1 because [0] is implied */
30705469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30715469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
30725469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
30735469607a00d84a07dc638eda46a87fc90142d64breed@android.com      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
30745469607a00d84a07dc638eda46a87fc90142d64breed@android.com      {
30755469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( error && error != HB_Err_Not_Covered )
30765469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  return error;
30775469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30785469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( j + igc - i + lgc == (HB_Int)buffer->in_length )
30795469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  goto next_chainsubrule;
30805469607a00d84a07dc638eda46a87fc90142d64breed@android.com	j++;
30815469607a00d84a07dc638eda46a87fc90142d64breed@android.com      }
30825469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30835469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( IN_GLYPH( j ) != curr_csr.Input[i - 1] )
30845469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  goto next_chainsubrule;
30855469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
30865469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30875469607a00d84a07dc638eda46a87fc90142d64breed@android.com    /* we are starting to check for lookahead glyphs right after the
30885469607a00d84a07dc638eda46a87fc90142d64breed@android.com       last context glyph                                            */
30895469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30905469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( i = 0; i < lgc; i++, j++ )
30915469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
30925469607a00d84a07dc638eda46a87fc90142d64breed@android.com      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
30935469607a00d84a07dc638eda46a87fc90142d64breed@android.com      {
30945469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( error && error != HB_Err_Not_Covered )
30955469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  return error;
30965469607a00d84a07dc638eda46a87fc90142d64breed@android.com
30975469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( j + lgc - i == (HB_Int)buffer->in_length )
30985469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  goto next_chainsubrule;
30995469607a00d84a07dc638eda46a87fc90142d64breed@android.com	j++;
31005469607a00d84a07dc638eda46a87fc90142d64breed@android.com      }
31015469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31025469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( IN_GLYPH( j ) != curr_csr.Lookahead[i] )
31035469607a00d84a07dc638eda46a87fc90142d64breed@android.com	goto next_chainsubrule;
31045469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
31055469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31065469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return Do_ContextSubst( gsub, igc,
31075469607a00d84a07dc638eda46a87fc90142d64breed@android.com			    curr_csr.SubstCount,
31085469607a00d84a07dc638eda46a87fc90142d64breed@android.com			    curr_csr.SubstLookupRecord,
31095469607a00d84a07dc638eda46a87fc90142d64breed@android.com			    buffer,
31105469607a00d84a07dc638eda46a87fc90142d64breed@android.com			    nesting_level );
31115469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31125469607a00d84a07dc638eda46a87fc90142d64breed@android.com  next_chainsubrule:
31135469607a00d84a07dc638eda46a87fc90142d64breed@android.com    ;
31145469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
31155469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31165469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Not_Covered;
31175469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
31185469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31195469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31205469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Lookup_ChainContextSubst2( HB_GSUBHeader*               gsub,
31215469607a00d84a07dc638eda46a87fc90142d64breed@android.com					    HB_ChainContextSubstFormat2* ccsf2,
31225469607a00d84a07dc638eda46a87fc90142d64breed@android.com					    HB_Buffer                    buffer,
31235469607a00d84a07dc638eda46a87fc90142d64breed@android.com					    HB_UShort                     flags,
31245469607a00d84a07dc638eda46a87fc90142d64breed@android.com					    HB_UShort                     context_length,
31255469607a00d84a07dc638eda46a87fc90142d64breed@android.com					    int                           nesting_level )
31265469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
31275469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort              index, property;
31285469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error               error;
31295469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort              i, j, k;
31305469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort              bgc, igc, lgc;
31315469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort              known_backtrack_classes,
31325469607a00d84a07dc638eda46a87fc90142d64breed@android.com			 known_input_classes,
31335469607a00d84a07dc638eda46a87fc90142d64breed@android.com			 known_lookahead_classes;
31345469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31355469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*             backtrack_classes;
31365469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*             input_classes;
31375469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*             lookahead_classes;
31385469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31395469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*             bc;
31405469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*             ic;
31415469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*             lc;
31425469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31435469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ChainSubClassSet*  cscs;
31445469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ChainSubClassRule  ccsr;
31455469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_GDEFHeader*        gdef;
31465469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31475469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31485469607a00d84a07dc638eda46a87fc90142d64breed@android.com  gdef = gsub->gdef;
31495469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31505469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
31515469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
31525469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31535469607a00d84a07dc638eda46a87fc90142d64breed@android.com  /* Note: The coverage table in format 2 doesn't give an index into
31545469607a00d84a07dc638eda46a87fc90142d64breed@android.com	   anything.  It just lets us know whether or not we need to
31555469607a00d84a07dc638eda46a87fc90142d64breed@android.com	   do any lookup at all.                                     */
31565469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31575469607a00d84a07dc638eda46a87fc90142d64breed@android.com  error = _HB_OPEN_Coverage_Index( &ccsf2->Coverage, IN_CURGLYPH(), &index );
31585469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( error )
31595469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
31605469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31615469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( backtrack_classes, ccsf2->MaxBacktrackLength, HB_UShort ) )
31625469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
31635469607a00d84a07dc638eda46a87fc90142d64breed@android.com  known_backtrack_classes = 0;
31645469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31655469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if (ccsf2->MaxInputLength < 1)
31665469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return HB_Err_Not_Covered;
31675469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31685469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( input_classes, ccsf2->MaxInputLength, HB_UShort ) )
31695469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto End3;
31705469607a00d84a07dc638eda46a87fc90142d64breed@android.com  known_input_classes = 1;
31715469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31725469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( lookahead_classes, ccsf2->MaxLookaheadLength, HB_UShort ) )
31735469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto End2;
31745469607a00d84a07dc638eda46a87fc90142d64breed@android.com  known_lookahead_classes = 0;
31755469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31765469607a00d84a07dc638eda46a87fc90142d64breed@android.com  error = _HB_OPEN_Get_Class( &ccsf2->InputClassDef, IN_CURGLYPH(),
31775469607a00d84a07dc638eda46a87fc90142d64breed@android.com		     &input_classes[0], NULL );
31785469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( error && error != HB_Err_Not_Covered )
31795469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto End1;
31805469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31815469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cscs = &ccsf2->ChainSubClassSet[input_classes[0]];
31825469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( !cscs )
31835469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
31845469607a00d84a07dc638eda46a87fc90142d64breed@android.com    error = ERR(HB_Err_Invalid_SubTable);
31855469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto End1;
31865469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
31875469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31885469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( k = 0; k < cscs->ChainSubClassRuleCount; k++ )
31895469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
31905469607a00d84a07dc638eda46a87fc90142d64breed@android.com    ccsr = cscs->ChainSubClassRule[k];
31915469607a00d84a07dc638eda46a87fc90142d64breed@android.com    bgc  = ccsr.BacktrackGlyphCount;
31925469607a00d84a07dc638eda46a87fc90142d64breed@android.com    igc  = ccsr.InputGlyphCount;
31935469607a00d84a07dc638eda46a87fc90142d64breed@android.com    lgc  = ccsr.LookaheadGlyphCount;
31945469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31955469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( context_length != 0xFFFF && context_length < igc )
31965469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto next_chainsubclassrule;
31975469607a00d84a07dc638eda46a87fc90142d64breed@android.com
31985469607a00d84a07dc638eda46a87fc90142d64breed@android.com    /* check whether context is too long; it is a first guess only */
31995469607a00d84a07dc638eda46a87fc90142d64breed@android.com
32005469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length )
32015469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto next_chainsubclassrule;
32025469607a00d84a07dc638eda46a87fc90142d64breed@android.com
32035469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( bgc )
32045469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
32055469607a00d84a07dc638eda46a87fc90142d64breed@android.com      /* Since we don't know in advance the number of glyphs to inspect,
32065469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 we search backwards for matches in the backtrack glyph array.
32075469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 Note that `known_backtrack_classes' starts at index 0.         */
32085469607a00d84a07dc638eda46a87fc90142d64breed@android.com
32095469607a00d84a07dc638eda46a87fc90142d64breed@android.com      bc       = ccsr.Backtrack;
32105469607a00d84a07dc638eda46a87fc90142d64breed@android.com
32115469607a00d84a07dc638eda46a87fc90142d64breed@android.com      for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
32125469607a00d84a07dc638eda46a87fc90142d64breed@android.com      {
32135469607a00d84a07dc638eda46a87fc90142d64breed@android.com	while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )
32145469607a00d84a07dc638eda46a87fc90142d64breed@android.com	{
32155469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  if ( error && error != HB_Err_Not_Covered )
32165469607a00d84a07dc638eda46a87fc90142d64breed@android.com	    goto End1;
32175469607a00d84a07dc638eda46a87fc90142d64breed@android.com
32185469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  if ( j + 1 == bgc - i )
32195469607a00d84a07dc638eda46a87fc90142d64breed@android.com	    goto next_chainsubclassrule;
32205469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  j--;
32215469607a00d84a07dc638eda46a87fc90142d64breed@android.com	}
32225469607a00d84a07dc638eda46a87fc90142d64breed@android.com
32235469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( i >= known_backtrack_classes )
32245469607a00d84a07dc638eda46a87fc90142d64breed@android.com	{
32255469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  /* Keeps us from having to do this for each rule */
32265469607a00d84a07dc638eda46a87fc90142d64breed@android.com
32275469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  error = _HB_OPEN_Get_Class( &ccsf2->BacktrackClassDef, OUT_GLYPH( j ),
32285469607a00d84a07dc638eda46a87fc90142d64breed@android.com			     &backtrack_classes[i], NULL );
32295469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  if ( error && error != HB_Err_Not_Covered )
32305469607a00d84a07dc638eda46a87fc90142d64breed@android.com	    goto End1;
32315469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  known_backtrack_classes = i;
32325469607a00d84a07dc638eda46a87fc90142d64breed@android.com	}
32335469607a00d84a07dc638eda46a87fc90142d64breed@android.com
32345469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( bc[i] != backtrack_classes[i] )
32355469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  goto next_chainsubclassrule;
32365469607a00d84a07dc638eda46a87fc90142d64breed@android.com      }
32375469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
32385469607a00d84a07dc638eda46a87fc90142d64breed@android.com
32395469607a00d84a07dc638eda46a87fc90142d64breed@android.com    ic       = ccsr.Input;
32405469607a00d84a07dc638eda46a87fc90142d64breed@android.com
32415469607a00d84a07dc638eda46a87fc90142d64breed@android.com    /* Start at 1 because [0] is implied */
32425469607a00d84a07dc638eda46a87fc90142d64breed@android.com
32435469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
32445469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
32455469607a00d84a07dc638eda46a87fc90142d64breed@android.com      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
32465469607a00d84a07dc638eda46a87fc90142d64breed@android.com      {
32475469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( error && error != HB_Err_Not_Covered )
32485469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  goto End1;
32495469607a00d84a07dc638eda46a87fc90142d64breed@android.com
32505469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( j + igc - i + lgc == (HB_Int)buffer->in_length )
32515469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  goto next_chainsubclassrule;
32525469607a00d84a07dc638eda46a87fc90142d64breed@android.com	j++;
32535469607a00d84a07dc638eda46a87fc90142d64breed@android.com      }
32545469607a00d84a07dc638eda46a87fc90142d64breed@android.com
32555469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( i >= known_input_classes )
32565469607a00d84a07dc638eda46a87fc90142d64breed@android.com      {
32575469607a00d84a07dc638eda46a87fc90142d64breed@android.com	error = _HB_OPEN_Get_Class( &ccsf2->InputClassDef, IN_GLYPH( j ),
32585469607a00d84a07dc638eda46a87fc90142d64breed@android.com			   &input_classes[i], NULL );
32595469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( error && error != HB_Err_Not_Covered )
32605469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  goto End1;
32615469607a00d84a07dc638eda46a87fc90142d64breed@android.com	known_input_classes = i;
32625469607a00d84a07dc638eda46a87fc90142d64breed@android.com      }
32635469607a00d84a07dc638eda46a87fc90142d64breed@android.com
32645469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( ic[i - 1] != input_classes[i] )
32655469607a00d84a07dc638eda46a87fc90142d64breed@android.com	goto next_chainsubclassrule;
32665469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
32675469607a00d84a07dc638eda46a87fc90142d64breed@android.com
32685469607a00d84a07dc638eda46a87fc90142d64breed@android.com    /* we are starting to check for lookahead glyphs right after the
32695469607a00d84a07dc638eda46a87fc90142d64breed@android.com       last context glyph                                            */
32705469607a00d84a07dc638eda46a87fc90142d64breed@android.com
32715469607a00d84a07dc638eda46a87fc90142d64breed@android.com    lc       = ccsr.Lookahead;
32725469607a00d84a07dc638eda46a87fc90142d64breed@android.com
32735469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( i = 0; i < lgc; i++, j++ )
32745469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
32755469607a00d84a07dc638eda46a87fc90142d64breed@android.com      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
32765469607a00d84a07dc638eda46a87fc90142d64breed@android.com      {
32775469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( error && error != HB_Err_Not_Covered )
32785469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  goto End1;
32795469607a00d84a07dc638eda46a87fc90142d64breed@android.com
32805469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( j + lgc - i == (HB_Int)buffer->in_length )
32815469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  goto next_chainsubclassrule;
32825469607a00d84a07dc638eda46a87fc90142d64breed@android.com	j++;
32835469607a00d84a07dc638eda46a87fc90142d64breed@android.com      }
32845469607a00d84a07dc638eda46a87fc90142d64breed@android.com
32855469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( i >= known_lookahead_classes )
32865469607a00d84a07dc638eda46a87fc90142d64breed@android.com      {
32875469607a00d84a07dc638eda46a87fc90142d64breed@android.com	error = _HB_OPEN_Get_Class( &ccsf2->LookaheadClassDef, IN_GLYPH( j ),
32885469607a00d84a07dc638eda46a87fc90142d64breed@android.com			   &lookahead_classes[i], NULL );
32895469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( error && error != HB_Err_Not_Covered )
32905469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  goto End1;
32915469607a00d84a07dc638eda46a87fc90142d64breed@android.com	known_lookahead_classes = i;
32925469607a00d84a07dc638eda46a87fc90142d64breed@android.com      }
32935469607a00d84a07dc638eda46a87fc90142d64breed@android.com
32945469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( lc[i] != lookahead_classes[i] )
32955469607a00d84a07dc638eda46a87fc90142d64breed@android.com	goto next_chainsubclassrule;
32965469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
32975469607a00d84a07dc638eda46a87fc90142d64breed@android.com
32985469607a00d84a07dc638eda46a87fc90142d64breed@android.com    error = Do_ContextSubst( gsub, igc,
32995469607a00d84a07dc638eda46a87fc90142d64breed@android.com			     ccsr.SubstCount,
33005469607a00d84a07dc638eda46a87fc90142d64breed@android.com			     ccsr.SubstLookupRecord,
33015469607a00d84a07dc638eda46a87fc90142d64breed@android.com			     buffer,
33025469607a00d84a07dc638eda46a87fc90142d64breed@android.com			     nesting_level );
33035469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto End1;
33045469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33055469607a00d84a07dc638eda46a87fc90142d64breed@android.com  next_chainsubclassrule:
33065469607a00d84a07dc638eda46a87fc90142d64breed@android.com    ;
33075469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
33085469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33095469607a00d84a07dc638eda46a87fc90142d64breed@android.com  error = HB_Err_Not_Covered;
33105469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33115469607a00d84a07dc638eda46a87fc90142d64breed@android.comEnd1:
33125469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( lookahead_classes );
33135469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33145469607a00d84a07dc638eda46a87fc90142d64breed@android.comEnd2:
33155469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( input_classes );
33165469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33175469607a00d84a07dc638eda46a87fc90142d64breed@android.comEnd3:
33185469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( backtrack_classes );
33195469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
33205469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
33215469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33225469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33235469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Lookup_ChainContextSubst3( HB_GSUBHeader*               gsub,
33245469607a00d84a07dc638eda46a87fc90142d64breed@android.com					    HB_ChainContextSubstFormat3* ccsf3,
33255469607a00d84a07dc638eda46a87fc90142d64breed@android.com					    HB_Buffer                    buffer,
33265469607a00d84a07dc638eda46a87fc90142d64breed@android.com					    HB_UShort                     flags,
33275469607a00d84a07dc638eda46a87fc90142d64breed@android.com					    HB_UShort                     context_length,
33285469607a00d84a07dc638eda46a87fc90142d64breed@android.com					    int                           nesting_level )
33295469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
33305469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort        index, i, j, property;
33315469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort        bgc, igc, lgc;
33325469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error         error;
33335469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33345469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Coverage*    bc;
33355469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Coverage*    ic;
33365469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Coverage*    lc;
33375469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_GDEFHeader*  gdef;
33385469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33395469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33405469607a00d84a07dc638eda46a87fc90142d64breed@android.com  gdef = gsub->gdef;
33415469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33425469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
33435469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
33445469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33455469607a00d84a07dc638eda46a87fc90142d64breed@android.com  bgc = ccsf3->BacktrackGlyphCount;
33465469607a00d84a07dc638eda46a87fc90142d64breed@android.com  igc = ccsf3->InputGlyphCount;
33475469607a00d84a07dc638eda46a87fc90142d64breed@android.com  lgc = ccsf3->LookaheadGlyphCount;
33485469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33495469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( context_length != 0xFFFF && context_length < igc )
33505469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return HB_Err_Not_Covered;
33515469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33525469607a00d84a07dc638eda46a87fc90142d64breed@android.com  /* check whether context is too long; it is a first guess only */
33535469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33545469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( bgc > buffer->out_pos || buffer->in_pos + igc + lgc > buffer->in_length )
33555469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return HB_Err_Not_Covered;
33565469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33575469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( bgc )
33585469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
33595469607a00d84a07dc638eda46a87fc90142d64breed@android.com    /* Since we don't know in advance the number of glyphs to inspect,
33605469607a00d84a07dc638eda46a87fc90142d64breed@android.com       we search backwards for matches in the backtrack glyph array    */
33615469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33625469607a00d84a07dc638eda46a87fc90142d64breed@android.com    bc       = ccsf3->BacktrackCoverage;
33635469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33645469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
33655469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
33665469607a00d84a07dc638eda46a87fc90142d64breed@android.com      while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )
33675469607a00d84a07dc638eda46a87fc90142d64breed@android.com      {
33685469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( error && error != HB_Err_Not_Covered )
33695469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  return error;
33705469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33715469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( j + 1 == bgc - i )
33725469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  return HB_Err_Not_Covered;
33735469607a00d84a07dc638eda46a87fc90142d64breed@android.com	j--;
33745469607a00d84a07dc638eda46a87fc90142d64breed@android.com      }
33755469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33765469607a00d84a07dc638eda46a87fc90142d64breed@android.com      error = _HB_OPEN_Coverage_Index( &bc[i], OUT_GLYPH( j ), &index );
33775469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( error )
33785469607a00d84a07dc638eda46a87fc90142d64breed@android.com	return error;
33795469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
33805469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
33815469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33825469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ic       = ccsf3->InputCoverage;
33835469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33845469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ )
33855469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
33865469607a00d84a07dc638eda46a87fc90142d64breed@android.com    /* We already called CHECK_Property for IN_GLYPH( buffer->in_pos ) */
33875469607a00d84a07dc638eda46a87fc90142d64breed@android.com    while ( j > buffer->in_pos && CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
33885469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
33895469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( error && error != HB_Err_Not_Covered )
33905469607a00d84a07dc638eda46a87fc90142d64breed@android.com	return error;
33915469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33925469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( j + igc - i + lgc == (HB_Int)buffer->in_length )
33935469607a00d84a07dc638eda46a87fc90142d64breed@android.com	return HB_Err_Not_Covered;
33945469607a00d84a07dc638eda46a87fc90142d64breed@android.com      j++;
33955469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
33965469607a00d84a07dc638eda46a87fc90142d64breed@android.com
33975469607a00d84a07dc638eda46a87fc90142d64breed@android.com    error = _HB_OPEN_Coverage_Index( &ic[i], IN_GLYPH( j ), &index );
33985469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( error )
33995469607a00d84a07dc638eda46a87fc90142d64breed@android.com      return error;
34005469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
34015469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34025469607a00d84a07dc638eda46a87fc90142d64breed@android.com  /* we are starting for lookahead glyphs right after the last context
34035469607a00d84a07dc638eda46a87fc90142d64breed@android.com     glyph                                                             */
34045469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34055469607a00d84a07dc638eda46a87fc90142d64breed@android.com  lc       = ccsf3->LookaheadCoverage;
34065469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34075469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( i = 0; i < lgc; i++, j++ )
34085469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
34095469607a00d84a07dc638eda46a87fc90142d64breed@android.com    while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
34105469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
34115469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( error && error != HB_Err_Not_Covered )
34125469607a00d84a07dc638eda46a87fc90142d64breed@android.com	return error;
34135469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34145469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( j + lgc - i == (HB_Int)buffer->in_length )
34155469607a00d84a07dc638eda46a87fc90142d64breed@android.com	return HB_Err_Not_Covered;
34165469607a00d84a07dc638eda46a87fc90142d64breed@android.com      j++;
34175469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
34185469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34195469607a00d84a07dc638eda46a87fc90142d64breed@android.com    error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index );
34205469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( error )
34215469607a00d84a07dc638eda46a87fc90142d64breed@android.com      return error;
34225469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
34235469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34245469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return Do_ContextSubst( gsub, igc,
34255469607a00d84a07dc638eda46a87fc90142d64breed@android.com			  ccsf3->SubstCount,
34265469607a00d84a07dc638eda46a87fc90142d64breed@android.com			  ccsf3->SubstLookupRecord,
34275469607a00d84a07dc638eda46a87fc90142d64breed@android.com			  buffer,
34285469607a00d84a07dc638eda46a87fc90142d64breed@android.com			  nesting_level );
34295469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
34305469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34315469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34325469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Lookup_ChainContextSubst( HB_GSUBHeader*    gsub,
34335469607a00d84a07dc638eda46a87fc90142d64breed@android.com					   HB_GSUB_SubTable* st,
34345469607a00d84a07dc638eda46a87fc90142d64breed@android.com					   HB_Buffer         buffer,
34355469607a00d84a07dc638eda46a87fc90142d64breed@android.com					   HB_UShort          flags,
34365469607a00d84a07dc638eda46a87fc90142d64breed@android.com					   HB_UShort          context_length,
34375469607a00d84a07dc638eda46a87fc90142d64breed@android.com					   int                nesting_level )
34385469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
34395469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ChainContextSubst*  ccs = &st->chain;
34405469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34415469607a00d84a07dc638eda46a87fc90142d64breed@android.com  switch ( ccs->SubstFormat ) {
34425469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case 1:  return Lookup_ChainContextSubst1( gsub, &ccs->ccsf.ccsf1, buffer, flags, context_length, nesting_level );
34435469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case 2:  return Lookup_ChainContextSubst2( gsub, &ccs->ccsf.ccsf2, buffer, flags, context_length, nesting_level );
34445469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case 3:  return Lookup_ChainContextSubst3( gsub, &ccs->ccsf.ccsf3, buffer, flags, context_length, nesting_level );
34455469607a00d84a07dc638eda46a87fc90142d64breed@android.com    default: return ERR(HB_Err_Invalid_SubTable_Format);
34465469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
34475469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
34485469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34495469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34505469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Load_ReverseChainContextSubst( HB_GSUB_SubTable* st,
34515469607a00d84a07dc638eda46a87fc90142d64breed@android.com					        HB_Stream         stream )
34525469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
34535469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error error;
34545469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ReverseChainContextSubst*  rccs = &st->reverse;
34555469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34565469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort               m, count;
34575469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34585469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort               nb = 0, nl = 0, n;
34595469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort               backtrack_count, lookahead_count;
34605469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt                cur_offset, new_offset, base_offset;
34615469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34625469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Coverage*           b;
34635469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Coverage*           l;
34645469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*              sub;
34655469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34665469607a00d84a07dc638eda46a87fc90142d64breed@android.com  base_offset = FILE_Pos();
34675469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34685469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
34695469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
34705469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34715469607a00d84a07dc638eda46a87fc90142d64breed@android.com  rccs->SubstFormat = GET_UShort();
34725469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34735469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( rccs->SubstFormat != 1 )
34745469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return ERR(HB_Err_Invalid_SubTable_Format);
34755469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34765469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
34775469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34785469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
34795469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
34805469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34815469607a00d84a07dc638eda46a87fc90142d64breed@android.com  new_offset = GET_UShort() + base_offset;
34825469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34835469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
34845469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34855469607a00d84a07dc638eda46a87fc90142d64breed@android.com  cur_offset = FILE_Pos();
34865469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( FILE_Seek( new_offset ) ||
34875469607a00d84a07dc638eda46a87fc90142d64breed@android.com       ( error = _HB_OPEN_Load_Coverage( &rccs->Coverage, stream ) ) != HB_Err_Ok )
34885469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
34895469607a00d84a07dc638eda46a87fc90142d64breed@android.com  (void)FILE_Seek( cur_offset );
34905469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34915469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34925469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
34935469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail4;
34945469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34955469607a00d84a07dc638eda46a87fc90142d64breed@android.com  rccs->BacktrackGlyphCount = GET_UShort();
34965469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34975469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
34985469607a00d84a07dc638eda46a87fc90142d64breed@android.com
34995469607a00d84a07dc638eda46a87fc90142d64breed@android.com  rccs->BacktrackCoverage = NULL;
35005469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35015469607a00d84a07dc638eda46a87fc90142d64breed@android.com  backtrack_count = rccs->BacktrackGlyphCount;
35025469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35035469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( rccs->BacktrackCoverage, backtrack_count,
35045469607a00d84a07dc638eda46a87fc90142d64breed@android.com		    HB_Coverage ) )
35055469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail4;
35065469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35075469607a00d84a07dc638eda46a87fc90142d64breed@android.com  b = rccs->BacktrackCoverage;
35085469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35095469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( nb = 0; nb < backtrack_count; nb++ )
35105469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
35115469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ACCESS_Frame( 2L ) )
35125469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail3;
35135469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35145469607a00d84a07dc638eda46a87fc90142d64breed@android.com    new_offset = GET_UShort() + base_offset;
35155469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35165469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FORGET_Frame();
35175469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35185469607a00d84a07dc638eda46a87fc90142d64breed@android.com    cur_offset = FILE_Pos();
35195469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( FILE_Seek( new_offset ) ||
35205469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != HB_Err_Ok )
35215469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail3;
35225469607a00d84a07dc638eda46a87fc90142d64breed@android.com    (void)FILE_Seek( cur_offset );
35235469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
35245469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35255469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35265469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
35275469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail3;
35285469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35295469607a00d84a07dc638eda46a87fc90142d64breed@android.com  rccs->LookaheadGlyphCount = GET_UShort();
35305469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35315469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
35325469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35335469607a00d84a07dc638eda46a87fc90142d64breed@android.com  rccs->LookaheadCoverage = NULL;
35345469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35355469607a00d84a07dc638eda46a87fc90142d64breed@android.com  lookahead_count = rccs->LookaheadGlyphCount;
35365469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35375469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( rccs->LookaheadCoverage, lookahead_count,
35385469607a00d84a07dc638eda46a87fc90142d64breed@android.com		    HB_Coverage ) )
35395469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail3;
35405469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35415469607a00d84a07dc638eda46a87fc90142d64breed@android.com  l = rccs->LookaheadCoverage;
35425469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35435469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( nl = 0; nl < lookahead_count; nl++ )
35445469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
35455469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ACCESS_Frame( 2L ) )
35465469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail2;
35475469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35485469607a00d84a07dc638eda46a87fc90142d64breed@android.com    new_offset = GET_UShort() + base_offset;
35495469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35505469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FORGET_Frame();
35515469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35525469607a00d84a07dc638eda46a87fc90142d64breed@android.com    cur_offset = FILE_Pos();
35535469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( FILE_Seek( new_offset ) ||
35545469607a00d84a07dc638eda46a87fc90142d64breed@android.com	 ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != HB_Err_Ok )
35555469607a00d84a07dc638eda46a87fc90142d64breed@android.com      goto Fail2;
35565469607a00d84a07dc638eda46a87fc90142d64breed@android.com    (void)FILE_Seek( cur_offset );
35575469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
35585469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35595469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( 2L ) )
35605469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
35615469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35625469607a00d84a07dc638eda46a87fc90142d64breed@android.com  rccs->GlyphCount = GET_UShort();
35635469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35645469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
35655469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35665469607a00d84a07dc638eda46a87fc90142d64breed@android.com  rccs->Substitute = NULL;
35675469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35685469607a00d84a07dc638eda46a87fc90142d64breed@android.com  count = rccs->GlyphCount;
35695469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35705469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( rccs->Substitute, count,
35715469607a00d84a07dc638eda46a87fc90142d64breed@android.com		    HB_UShort ) )
35725469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail2;
35735469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35745469607a00d84a07dc638eda46a87fc90142d64breed@android.com  sub = rccs->Substitute;
35755469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35765469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ACCESS_Frame( count * 2L ) )
35775469607a00d84a07dc638eda46a87fc90142d64breed@android.com    goto Fail1;
35785469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35795469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < count; n++ )
35805469607a00d84a07dc638eda46a87fc90142d64breed@android.com    sub[n] = GET_UShort();
35815469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35825469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FORGET_Frame();
35835469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35845469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
35855469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35865469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail1:
35875469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( sub );
35885469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35895469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail2:
35905469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( m = 0; m < nl; m++ )
35915469607a00d84a07dc638eda46a87fc90142d64breed@android.com    _HB_OPEN_Free_Coverage( &l[m] );
35925469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35935469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( l );
35945469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35955469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail3:
35965469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( m = 0; m < nb; m++ )
35975469607a00d84a07dc638eda46a87fc90142d64breed@android.com    _HB_OPEN_Free_Coverage( &b[m] );
35985469607a00d84a07dc638eda46a87fc90142d64breed@android.com
35995469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE( b );
36005469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36015469607a00d84a07dc638eda46a87fc90142d64breed@android.comFail4:
36025469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_Coverage( &rccs->Coverage );
36035469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
36045469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
36055469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36065469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36075469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic void  Free_ReverseChainContextSubst( HB_GSUB_SubTable* st )
36085469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
36095469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort      n, count;
36105469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ReverseChainContextSubst*  rccs = &st->reverse;
36115469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36125469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Coverage*  c;
36135469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36145469607a00d84a07dc638eda46a87fc90142d64breed@android.com  _HB_OPEN_Free_Coverage( &rccs->Coverage );
36155469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36165469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( rccs->LookaheadCoverage )
36175469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
36185469607a00d84a07dc638eda46a87fc90142d64breed@android.com    count = rccs->LookaheadGlyphCount;
36195469607a00d84a07dc638eda46a87fc90142d64breed@android.com    c     = rccs->LookaheadCoverage;
36205469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36215469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( n = 0; n < count; n++ )
36225469607a00d84a07dc638eda46a87fc90142d64breed@android.com      _HB_OPEN_Free_Coverage( &c[n] );
36235469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36245469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FREE( c );
36255469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
36265469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36275469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( rccs->BacktrackCoverage )
36285469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
36295469607a00d84a07dc638eda46a87fc90142d64breed@android.com    count = rccs->BacktrackGlyphCount;
36305469607a00d84a07dc638eda46a87fc90142d64breed@android.com    c     = rccs->BacktrackCoverage;
36315469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36325469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( n = 0; n < count; n++ )
36335469607a00d84a07dc638eda46a87fc90142d64breed@android.com      _HB_OPEN_Free_Coverage( &c[n] );
36345469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36355469607a00d84a07dc638eda46a87fc90142d64breed@android.com    FREE( c );
36365469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
36375469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36385469607a00d84a07dc638eda46a87fc90142d64breed@android.com  FREE ( rccs->Substitute );
36395469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
36405469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36415469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36425469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  Lookup_ReverseChainContextSubst( HB_GSUBHeader*    gsub,
36435469607a00d84a07dc638eda46a87fc90142d64breed@android.com						  HB_GSUB_SubTable* st,
36445469607a00d84a07dc638eda46a87fc90142d64breed@android.com						  HB_Buffer         buffer,
36455469607a00d84a07dc638eda46a87fc90142d64breed@android.com						  HB_UShort          flags,
36465469607a00d84a07dc638eda46a87fc90142d64breed@android.com						  HB_UShort         context_length,
36475469607a00d84a07dc638eda46a87fc90142d64breed@android.com						  int               nesting_level )
36485469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
36495469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort        index, input_index, i, j, property;
36505469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort        bgc, lgc;
36515469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error         error;
36525469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36535469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ReverseChainContextSubst*  rccs = &st->reverse;
36545469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Coverage*    bc;
36555469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Coverage*    lc;
36565469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_GDEFHeader*  gdef;
36575469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36585469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( nesting_level != 1 || context_length != 0xFFFF )
36595469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return HB_Err_Not_Covered;
36605469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36615469607a00d84a07dc638eda46a87fc90142d64breed@android.com  gdef = gsub->gdef;
36625469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36635469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
36645469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
36655469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36665469607a00d84a07dc638eda46a87fc90142d64breed@android.com  bgc = rccs->BacktrackGlyphCount;
36675469607a00d84a07dc638eda46a87fc90142d64breed@android.com  lgc = rccs->LookaheadGlyphCount;
36685469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36695469607a00d84a07dc638eda46a87fc90142d64breed@android.com  /* check whether context is too long; it is a first guess only */
36705469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36715469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( bgc > buffer->in_pos || buffer->in_pos + 1 + lgc > buffer->in_length )
36725469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return HB_Err_Not_Covered;
36735469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36745469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( bgc )
36755469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
36765469607a00d84a07dc638eda46a87fc90142d64breed@android.com    /* Since we don't know in advance the number of glyphs to inspect,
36775469607a00d84a07dc638eda46a87fc90142d64breed@android.com       we search backwards for matches in the backtrack glyph array    */
36785469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36795469607a00d84a07dc638eda46a87fc90142d64breed@android.com    bc       = rccs->BacktrackCoverage;
36805469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36815469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
36825469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
36835469607a00d84a07dc638eda46a87fc90142d64breed@android.com      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
36845469607a00d84a07dc638eda46a87fc90142d64breed@android.com      {
36855469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( error && error != HB_Err_Not_Covered )
36865469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  return error;
36875469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36885469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( j + 1 == bgc - i )
36895469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  return HB_Err_Not_Covered;
36905469607a00d84a07dc638eda46a87fc90142d64breed@android.com	j--;
36915469607a00d84a07dc638eda46a87fc90142d64breed@android.com      }
36925469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36935469607a00d84a07dc638eda46a87fc90142d64breed@android.com      error = _HB_OPEN_Coverage_Index( &bc[i], IN_GLYPH( j ), &index );
36945469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( error )
36955469607a00d84a07dc638eda46a87fc90142d64breed@android.com	return error;
36965469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
36975469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
36985469607a00d84a07dc638eda46a87fc90142d64breed@android.com
36995469607a00d84a07dc638eda46a87fc90142d64breed@android.com  j = buffer->in_pos;
37005469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37015469607a00d84a07dc638eda46a87fc90142d64breed@android.com  error = _HB_OPEN_Coverage_Index( &rccs->Coverage, IN_GLYPH( j ), &input_index );
37025469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( error )
37035469607a00d84a07dc638eda46a87fc90142d64breed@android.com      return error;
37045469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37055469607a00d84a07dc638eda46a87fc90142d64breed@android.com  lc       = rccs->LookaheadCoverage;
37065469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37075469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( i = 0, j = buffer->in_pos + 1; i < lgc; i++, j++ )
37085469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
37095469607a00d84a07dc638eda46a87fc90142d64breed@android.com    while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
37105469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
37115469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( error && error != HB_Err_Not_Covered )
37125469607a00d84a07dc638eda46a87fc90142d64breed@android.com	return error;
37135469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37145469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( j + lgc - i == (HB_Int)buffer->in_length )
37155469607a00d84a07dc638eda46a87fc90142d64breed@android.com	return HB_Err_Not_Covered;
37165469607a00d84a07dc638eda46a87fc90142d64breed@android.com      j++;
37175469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
37185469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37195469607a00d84a07dc638eda46a87fc90142d64breed@android.com    error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index );
37205469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( error )
37215469607a00d84a07dc638eda46a87fc90142d64breed@android.com      return error;
37225469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
37235469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37245469607a00d84a07dc638eda46a87fc90142d64breed@android.com  IN_CURGLYPH() = rccs->Substitute[input_index];
37255469607a00d84a07dc638eda46a87fc90142d64breed@android.com  buffer->in_pos--; /* Reverse! */
37265469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37275469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
37285469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
37295469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37305469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37315469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37325469607a00d84a07dc638eda46a87fc90142d64breed@android.com/***********
37335469607a00d84a07dc638eda46a87fc90142d64breed@android.com * GSUB API
37345469607a00d84a07dc638eda46a87fc90142d64breed@android.com ***********/
37355469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37365469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37375469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37385469607a00d84a07dc638eda46a87fc90142d64breed@android.comHB_Error  HB_GSUB_Select_Script( HB_GSUBHeader*  gsub,
37395469607a00d84a07dc638eda46a87fc90142d64breed@android.com				 HB_UInt         script_tag,
37405469607a00d84a07dc638eda46a87fc90142d64breed@android.com				 HB_UShort*       script_index )
37415469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
37425469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort          n;
37435469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37445469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ScriptList*    sl;
37455469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ScriptRecord*  sr;
37465469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37475469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37485469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( !gsub || !script_index )
37495469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return ERR(HB_Err_Invalid_Argument);
37505469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37515469607a00d84a07dc638eda46a87fc90142d64breed@android.com  sl = &gsub->ScriptList;
37525469607a00d84a07dc638eda46a87fc90142d64breed@android.com  sr = sl->ScriptRecord;
37535469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37545469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < sl->ScriptCount; n++ )
37555469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( script_tag == sr[n].ScriptTag )
37565469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
37575469607a00d84a07dc638eda46a87fc90142d64breed@android.com      *script_index = n;
37585469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37595469607a00d84a07dc638eda46a87fc90142d64breed@android.com      return HB_Err_Ok;
37605469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
37615469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37625469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Not_Covered;
37635469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
37645469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37655469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37665469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37675469607a00d84a07dc638eda46a87fc90142d64breed@android.comHB_Error  HB_GSUB_Select_Language( HB_GSUBHeader*  gsub,
37685469607a00d84a07dc638eda46a87fc90142d64breed@android.com				   HB_UInt         language_tag,
37695469607a00d84a07dc638eda46a87fc90142d64breed@android.com				   HB_UShort        script_index,
37705469607a00d84a07dc638eda46a87fc90142d64breed@android.com				   HB_UShort*       language_index,
37715469607a00d84a07dc638eda46a87fc90142d64breed@android.com				   HB_UShort*       req_feature_index )
37725469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
37735469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort           n;
37745469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37755469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ScriptList*     sl;
37765469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ScriptRecord*   sr;
37775469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ScriptTable*    s;
37785469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_LangSysRecord*  lsr;
37795469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37805469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37815469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( !gsub || !language_index || !req_feature_index )
37825469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return ERR(HB_Err_Invalid_Argument);
37835469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37845469607a00d84a07dc638eda46a87fc90142d64breed@android.com  sl = &gsub->ScriptList;
37855469607a00d84a07dc638eda46a87fc90142d64breed@android.com  sr = sl->ScriptRecord;
37865469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37875469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( script_index >= sl->ScriptCount )
37885469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return ERR(HB_Err_Invalid_Argument);
37895469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37905469607a00d84a07dc638eda46a87fc90142d64breed@android.com  s   = &sr[script_index].Script;
37915469607a00d84a07dc638eda46a87fc90142d64breed@android.com  lsr = s->LangSysRecord;
37925469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37935469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < s->LangSysCount; n++ )
37945469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( language_tag == lsr[n].LangSysTag )
37955469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
37965469607a00d84a07dc638eda46a87fc90142d64breed@android.com      *language_index = n;
37975469607a00d84a07dc638eda46a87fc90142d64breed@android.com      *req_feature_index = lsr[n].LangSys.ReqFeatureIndex;
37985469607a00d84a07dc638eda46a87fc90142d64breed@android.com
37995469607a00d84a07dc638eda46a87fc90142d64breed@android.com      return HB_Err_Ok;
38005469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
38015469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38025469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Not_Covered;
38035469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
38045469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38055469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38065469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* selecting 0xFFFF for language_index asks for the values of the
38075469607a00d84a07dc638eda46a87fc90142d64breed@android.com   default language (DefaultLangSys)                              */
38085469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38095469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38105469607a00d84a07dc638eda46a87fc90142d64breed@android.comHB_Error  HB_GSUB_Select_Feature( HB_GSUBHeader*  gsub,
38115469607a00d84a07dc638eda46a87fc90142d64breed@android.com				  HB_UInt         feature_tag,
38125469607a00d84a07dc638eda46a87fc90142d64breed@android.com				  HB_UShort        script_index,
38135469607a00d84a07dc638eda46a87fc90142d64breed@android.com				  HB_UShort        language_index,
38145469607a00d84a07dc638eda46a87fc90142d64breed@android.com				  HB_UShort*       feature_index )
38155469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
38165469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort           n;
38175469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38185469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ScriptList*     sl;
38195469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ScriptRecord*   sr;
38205469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ScriptTable*    s;
38215469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_LangSysRecord*  lsr;
38225469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_LangSys*        ls;
38235469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*          fi;
38245469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38255469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_FeatureList*    fl;
38265469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_FeatureRecord*  fr;
38275469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38285469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38295469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( !gsub || !feature_index )
38305469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return ERR(HB_Err_Invalid_Argument);
38315469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38325469607a00d84a07dc638eda46a87fc90142d64breed@android.com  sl = &gsub->ScriptList;
38335469607a00d84a07dc638eda46a87fc90142d64breed@android.com  sr = sl->ScriptRecord;
38345469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38355469607a00d84a07dc638eda46a87fc90142d64breed@android.com  fl = &gsub->FeatureList;
38365469607a00d84a07dc638eda46a87fc90142d64breed@android.com  fr = fl->FeatureRecord;
38375469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38385469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( script_index >= sl->ScriptCount )
38395469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return ERR(HB_Err_Invalid_Argument);
38405469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38415469607a00d84a07dc638eda46a87fc90142d64breed@android.com  s   = &sr[script_index].Script;
38425469607a00d84a07dc638eda46a87fc90142d64breed@android.com  lsr = s->LangSysRecord;
38435469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38445469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( language_index == 0xFFFF )
38455469607a00d84a07dc638eda46a87fc90142d64breed@android.com    ls = &s->DefaultLangSys;
38465469607a00d84a07dc638eda46a87fc90142d64breed@android.com  else
38475469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
38485469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( language_index >= s->LangSysCount )
38495469607a00d84a07dc638eda46a87fc90142d64breed@android.com      return ERR(HB_Err_Invalid_Argument);
38505469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38515469607a00d84a07dc638eda46a87fc90142d64breed@android.com    ls = &lsr[language_index].LangSys;
38525469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
38535469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38545469607a00d84a07dc638eda46a87fc90142d64breed@android.com  fi = ls->FeatureIndex;
38555469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38565469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < ls->FeatureCount; n++ )
38575469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
38585469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( fi[n] >= fl->FeatureCount )
38595469607a00d84a07dc638eda46a87fc90142d64breed@android.com      return ERR(HB_Err_Invalid_SubTable_Format);
38605469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38615469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( feature_tag == fr[fi[n]].FeatureTag )
38625469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
38635469607a00d84a07dc638eda46a87fc90142d64breed@android.com      *feature_index = fi[n];
38645469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38655469607a00d84a07dc638eda46a87fc90142d64breed@android.com      return HB_Err_Ok;
38665469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
38675469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
38685469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38695469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Not_Covered;
38705469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
38715469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38725469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38735469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* The next three functions return a null-terminated list */
38745469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38755469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38765469607a00d84a07dc638eda46a87fc90142d64breed@android.comHB_Error  HB_GSUB_Query_Scripts( HB_GSUBHeader*  gsub,
38775469607a00d84a07dc638eda46a87fc90142d64breed@android.com				 HB_UInt**       script_tag_list )
38785469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
38795469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort          n;
38805469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error           error;
38815469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt*          stl;
38825469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38835469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ScriptList*    sl;
38845469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ScriptRecord*  sr;
38855469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38865469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38875469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( !gsub || !script_tag_list )
38885469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return ERR(HB_Err_Invalid_Argument);
38895469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38905469607a00d84a07dc638eda46a87fc90142d64breed@android.com  sl = &gsub->ScriptList;
38915469607a00d84a07dc638eda46a87fc90142d64breed@android.com  sr = sl->ScriptRecord;
38925469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38935469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( stl, sl->ScriptCount + 1, HB_UInt ) )
38945469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
38955469607a00d84a07dc638eda46a87fc90142d64breed@android.com
38965469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < sl->ScriptCount; n++ )
38975469607a00d84a07dc638eda46a87fc90142d64breed@android.com    stl[n] = sr[n].ScriptTag;
38985469607a00d84a07dc638eda46a87fc90142d64breed@android.com  stl[n] = 0;
38995469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39005469607a00d84a07dc638eda46a87fc90142d64breed@android.com  *script_tag_list = stl;
39015469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39025469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
39035469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
39045469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39055469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39065469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39075469607a00d84a07dc638eda46a87fc90142d64breed@android.comHB_Error  HB_GSUB_Query_Languages( HB_GSUBHeader*  gsub,
39085469607a00d84a07dc638eda46a87fc90142d64breed@android.com				   HB_UShort        script_index,
39095469607a00d84a07dc638eda46a87fc90142d64breed@android.com				   HB_UInt**       language_tag_list )
39105469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
39115469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort           n;
39125469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error            error;
39135469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt*           ltl;
39145469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39155469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ScriptList*     sl;
39165469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ScriptRecord*   sr;
39175469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ScriptTable*    s;
39185469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_LangSysRecord*  lsr;
39195469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39205469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39215469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( !gsub || !language_tag_list )
39225469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return ERR(HB_Err_Invalid_Argument);
39235469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39245469607a00d84a07dc638eda46a87fc90142d64breed@android.com  sl = &gsub->ScriptList;
39255469607a00d84a07dc638eda46a87fc90142d64breed@android.com  sr = sl->ScriptRecord;
39265469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39275469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( script_index >= sl->ScriptCount )
39285469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return ERR(HB_Err_Invalid_Argument);
39295469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39305469607a00d84a07dc638eda46a87fc90142d64breed@android.com  s   = &sr[script_index].Script;
39315469607a00d84a07dc638eda46a87fc90142d64breed@android.com  lsr = s->LangSysRecord;
39325469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39335469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( ltl, s->LangSysCount + 1, HB_UInt ) )
39345469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
39355469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39365469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < s->LangSysCount; n++ )
39375469607a00d84a07dc638eda46a87fc90142d64breed@android.com    ltl[n] = lsr[n].LangSysTag;
39385469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ltl[n] = 0;
39395469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39405469607a00d84a07dc638eda46a87fc90142d64breed@android.com  *language_tag_list = ltl;
39415469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39425469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
39435469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
39445469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39455469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39465469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* selecting 0xFFFF for language_index asks for the values of the
39475469607a00d84a07dc638eda46a87fc90142d64breed@android.com   default language (DefaultLangSys)                              */
39485469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39495469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39505469607a00d84a07dc638eda46a87fc90142d64breed@android.comHB_Error  HB_GSUB_Query_Features( HB_GSUBHeader*  gsub,
39515469607a00d84a07dc638eda46a87fc90142d64breed@android.com				  HB_UShort        script_index,
39525469607a00d84a07dc638eda46a87fc90142d64breed@android.com				  HB_UShort        language_index,
39535469607a00d84a07dc638eda46a87fc90142d64breed@android.com				  HB_UInt**       feature_tag_list )
39545469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
39555469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort           n;
39565469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error            error;
39575469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt*           ftl;
39585469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39595469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ScriptList*     sl;
39605469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ScriptRecord*   sr;
39615469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_ScriptTable*    s;
39625469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_LangSysRecord*  lsr;
39635469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_LangSys*        ls;
39645469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*          fi;
39655469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39665469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_FeatureList*    fl;
39675469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_FeatureRecord*  fr;
39685469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39695469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39705469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( !gsub || !feature_tag_list )
39715469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return ERR(HB_Err_Invalid_Argument);
39725469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39735469607a00d84a07dc638eda46a87fc90142d64breed@android.com  sl = &gsub->ScriptList;
39745469607a00d84a07dc638eda46a87fc90142d64breed@android.com  sr = sl->ScriptRecord;
39755469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39765469607a00d84a07dc638eda46a87fc90142d64breed@android.com  fl = &gsub->FeatureList;
39775469607a00d84a07dc638eda46a87fc90142d64breed@android.com  fr = fl->FeatureRecord;
39785469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39795469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( script_index >= sl->ScriptCount )
39805469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return ERR(HB_Err_Invalid_Argument);
39815469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39825469607a00d84a07dc638eda46a87fc90142d64breed@android.com  s   = &sr[script_index].Script;
39835469607a00d84a07dc638eda46a87fc90142d64breed@android.com  lsr = s->LangSysRecord;
39845469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39855469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( language_index == 0xFFFF )
39865469607a00d84a07dc638eda46a87fc90142d64breed@android.com    ls = &s->DefaultLangSys;
39875469607a00d84a07dc638eda46a87fc90142d64breed@android.com  else
39885469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
39895469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( language_index >= s->LangSysCount )
39905469607a00d84a07dc638eda46a87fc90142d64breed@android.com      return ERR(HB_Err_Invalid_Argument);
39915469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39925469607a00d84a07dc638eda46a87fc90142d64breed@android.com    ls = &lsr[language_index].LangSys;
39935469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
39945469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39955469607a00d84a07dc638eda46a87fc90142d64breed@android.com  fi = ls->FeatureIndex;
39965469607a00d84a07dc638eda46a87fc90142d64breed@android.com
39975469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( ALLOC_ARRAY( ftl, ls->FeatureCount + 1, HB_UInt ) )
39985469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
39995469607a00d84a07dc638eda46a87fc90142d64breed@android.com
40005469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( n = 0; n < ls->FeatureCount; n++ )
40015469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
40025469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( fi[n] >= fl->FeatureCount )
40035469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
40045469607a00d84a07dc638eda46a87fc90142d64breed@android.com      FREE( ftl );
40055469607a00d84a07dc638eda46a87fc90142d64breed@android.com      return ERR(HB_Err_Invalid_SubTable_Format);
40065469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
40075469607a00d84a07dc638eda46a87fc90142d64breed@android.com    ftl[n] = fr[fi[n]].FeatureTag;
40085469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
40095469607a00d84a07dc638eda46a87fc90142d64breed@android.com  ftl[n] = 0;
40105469607a00d84a07dc638eda46a87fc90142d64breed@android.com
40115469607a00d84a07dc638eda46a87fc90142d64breed@android.com  *feature_tag_list = ftl;
40125469607a00d84a07dc638eda46a87fc90142d64breed@android.com
40135469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
40145469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
40155469607a00d84a07dc638eda46a87fc90142d64breed@android.com
40165469607a00d84a07dc638eda46a87fc90142d64breed@android.com
40175469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* Do an individual subtable lookup.  Returns HB_Err_Ok if substitution
40185469607a00d84a07dc638eda46a87fc90142d64breed@android.com   has been done, or HB_Err_Not_Covered if not.                        */
40195469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  GSUB_Do_Glyph_Lookup( HB_GSUBHeader* gsub,
40205469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_UShort       lookup_index,
40215469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_Buffer      buffer,
40225469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       HB_UShort       context_length,
40235469607a00d84a07dc638eda46a87fc90142d64breed@android.com				       int             nesting_level )
40245469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
40255469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error               error = HB_Err_Not_Covered;
40265469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort              i, flags, lookup_count;
40275469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Lookup*             lo;
40285469607a00d84a07dc638eda46a87fc90142d64breed@android.com  int                    lookup_type;
40295469607a00d84a07dc638eda46a87fc90142d64breed@android.com
40305469607a00d84a07dc638eda46a87fc90142d64breed@android.com  nesting_level++;
40315469607a00d84a07dc638eda46a87fc90142d64breed@android.com
40325469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( nesting_level > HB_MAX_NESTING_LEVEL )
40335469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return ERR(HB_Err_Not_Covered); /* ERR() call intended */
40345469607a00d84a07dc638eda46a87fc90142d64breed@android.com
40355469607a00d84a07dc638eda46a87fc90142d64breed@android.com  lookup_count = gsub->LookupList.LookupCount;
40365469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if (lookup_index >= lookup_count)
40375469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return error;
40385469607a00d84a07dc638eda46a87fc90142d64breed@android.com
40395469607a00d84a07dc638eda46a87fc90142d64breed@android.com  lo    = &gsub->LookupList.Lookup[lookup_index];
40405469607a00d84a07dc638eda46a87fc90142d64breed@android.com  flags = lo->LookupFlag;
40415469607a00d84a07dc638eda46a87fc90142d64breed@android.com  lookup_type = lo->LookupType;
40425469607a00d84a07dc638eda46a87fc90142d64breed@android.com
40435469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( i = 0; i < lo->SubTableCount; i++ )
40445469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
40455469607a00d84a07dc638eda46a87fc90142d64breed@android.com    HB_GSUB_SubTable *st = &lo->SubTable[i].st.gsub;
40465469607a00d84a07dc638eda46a87fc90142d64breed@android.com
40475469607a00d84a07dc638eda46a87fc90142d64breed@android.com    switch (lookup_type) {
40485469607a00d84a07dc638eda46a87fc90142d64breed@android.com      case HB_GSUB_LOOKUP_SINGLE:
40495469607a00d84a07dc638eda46a87fc90142d64breed@android.com	error = Lookup_SingleSubst		( gsub, st, buffer, flags, context_length, nesting_level ); break;
40505469607a00d84a07dc638eda46a87fc90142d64breed@android.com      case HB_GSUB_LOOKUP_MULTIPLE:
40515469607a00d84a07dc638eda46a87fc90142d64breed@android.com	error = Lookup_MultipleSubst		( gsub, st, buffer, flags, context_length, nesting_level ); break;
40525469607a00d84a07dc638eda46a87fc90142d64breed@android.com      case HB_GSUB_LOOKUP_ALTERNATE:
40535469607a00d84a07dc638eda46a87fc90142d64breed@android.com	error = Lookup_AlternateSubst		( gsub, st, buffer, flags, context_length, nesting_level ); break;
40545469607a00d84a07dc638eda46a87fc90142d64breed@android.com      case HB_GSUB_LOOKUP_LIGATURE:
40555469607a00d84a07dc638eda46a87fc90142d64breed@android.com	error = Lookup_LigatureSubst		( gsub, st, buffer, flags, context_length, nesting_level ); break;
40565469607a00d84a07dc638eda46a87fc90142d64breed@android.com      case HB_GSUB_LOOKUP_CONTEXT:
40575469607a00d84a07dc638eda46a87fc90142d64breed@android.com	error = Lookup_ContextSubst		( gsub, st, buffer, flags, context_length, nesting_level ); break;
40585469607a00d84a07dc638eda46a87fc90142d64breed@android.com      case HB_GSUB_LOOKUP_CHAIN:
40595469607a00d84a07dc638eda46a87fc90142d64breed@android.com	error = Lookup_ChainContextSubst	( gsub, st, buffer, flags, context_length, nesting_level ); break;
40605469607a00d84a07dc638eda46a87fc90142d64breed@android.com    /*case HB_GSUB_LOOKUP_EXTENSION:
40615469607a00d84a07dc638eda46a87fc90142d64breed@android.com	error = Lookup_ExtensionSubst		( gsub, st, buffer, flags, context_length, nesting_level ); break;*/
40625469607a00d84a07dc638eda46a87fc90142d64breed@android.com      case HB_GSUB_LOOKUP_REVERSE_CHAIN:
40635469607a00d84a07dc638eda46a87fc90142d64breed@android.com	error = Lookup_ReverseChainContextSubst	( gsub, st, buffer, flags, context_length, nesting_level ); break;
40645469607a00d84a07dc638eda46a87fc90142d64breed@android.com      default:
40655469607a00d84a07dc638eda46a87fc90142d64breed@android.com	error = HB_Err_Not_Covered;
40665469607a00d84a07dc638eda46a87fc90142d64breed@android.com    };
40675469607a00d84a07dc638eda46a87fc90142d64breed@android.com
40685469607a00d84a07dc638eda46a87fc90142d64breed@android.com    /* Check whether we have a successful substitution or an error other
40695469607a00d84a07dc638eda46a87fc90142d64breed@android.com       than HB_Err_Not_Covered                                          */
40705469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( error != HB_Err_Not_Covered )
40715469607a00d84a07dc638eda46a87fc90142d64breed@android.com      return error;
40725469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
40735469607a00d84a07dc638eda46a87fc90142d64breed@android.com
40745469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Not_Covered;
40755469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
40765469607a00d84a07dc638eda46a87fc90142d64breed@android.com
40775469607a00d84a07dc638eda46a87fc90142d64breed@android.com
40785469607a00d84a07dc638eda46a87fc90142d64breed@android.comHB_INTERNAL HB_Error
40795469607a00d84a07dc638eda46a87fc90142d64breed@android.com_HB_GSUB_Load_SubTable( HB_GSUB_SubTable* st,
40805469607a00d84a07dc638eda46a87fc90142d64breed@android.com			HB_Stream         stream,
40815469607a00d84a07dc638eda46a87fc90142d64breed@android.com			HB_UShort         lookup_type )
40825469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
40835469607a00d84a07dc638eda46a87fc90142d64breed@android.com  switch (lookup_type) {
40845469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case HB_GSUB_LOOKUP_SINGLE:		return Load_SingleSubst			( st, stream );
40855469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case HB_GSUB_LOOKUP_MULTIPLE:	return Load_MultipleSubst		( st, stream );
40865469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case HB_GSUB_LOOKUP_ALTERNATE:	return Load_AlternateSubst		( st, stream );
40875469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case HB_GSUB_LOOKUP_LIGATURE:	return Load_LigatureSubst		( st, stream );
40885469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case HB_GSUB_LOOKUP_CONTEXT:	return Load_ContextSubst		( st, stream );
40895469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case HB_GSUB_LOOKUP_CHAIN:		return Load_ChainContextSubst		( st, stream );
40905469607a00d84a07dc638eda46a87fc90142d64breed@android.com  /*case HB_GSUB_LOOKUP_EXTENSION:	return Load_ExtensionSubst		( st, stream );*/
40915469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case HB_GSUB_LOOKUP_REVERSE_CHAIN:	return Load_ReverseChainContextSubst	( st, stream );
40925469607a00d84a07dc638eda46a87fc90142d64breed@android.com    default:				return ERR(HB_Err_Invalid_SubTable_Format);
40935469607a00d84a07dc638eda46a87fc90142d64breed@android.com  };
40945469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
40955469607a00d84a07dc638eda46a87fc90142d64breed@android.com
40965469607a00d84a07dc638eda46a87fc90142d64breed@android.com
40975469607a00d84a07dc638eda46a87fc90142d64breed@android.comHB_INTERNAL void
40985469607a00d84a07dc638eda46a87fc90142d64breed@android.com_HB_GSUB_Free_SubTable( HB_GSUB_SubTable* st,
40995469607a00d84a07dc638eda46a87fc90142d64breed@android.com			HB_UShort         lookup_type )
41005469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
41015469607a00d84a07dc638eda46a87fc90142d64breed@android.com  switch ( lookup_type ) {
41025469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case HB_GSUB_LOOKUP_SINGLE:		Free_SingleSubst		( st ); return;
41035469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case HB_GSUB_LOOKUP_MULTIPLE:	Free_MultipleSubst		( st ); return;
41045469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case HB_GSUB_LOOKUP_ALTERNATE:	Free_AlternateSubst		( st ); return;
41055469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case HB_GSUB_LOOKUP_LIGATURE:	Free_LigatureSubst		( st ); return;
41065469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case HB_GSUB_LOOKUP_CONTEXT:	Free_ContextSubst		( st ); return;
41075469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case HB_GSUB_LOOKUP_CHAIN:		Free_ChainContextSubst		( st ); return;
41085469607a00d84a07dc638eda46a87fc90142d64breed@android.com  /*case HB_GSUB_LOOKUP_EXTENSION:	Free_ExtensionSubst		( st ); return;*/
41095469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case HB_GSUB_LOOKUP_REVERSE_CHAIN:	Free_ReverseChainContextSubst	( st ); return;
41105469607a00d84a07dc638eda46a87fc90142d64breed@android.com    default:									return;
41115469607a00d84a07dc638eda46a87fc90142d64breed@android.com  };
41125469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
41135469607a00d84a07dc638eda46a87fc90142d64breed@android.com
41145469607a00d84a07dc638eda46a87fc90142d64breed@android.com
41155469607a00d84a07dc638eda46a87fc90142d64breed@android.com
41165469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* apply one lookup to the input string object */
41175469607a00d84a07dc638eda46a87fc90142d64breed@android.com
41185469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Error  GSUB_Do_String_Lookup( HB_GSUBHeader*   gsub,
41195469607a00d84a07dc638eda46a87fc90142d64breed@android.com				   HB_UShort         lookup_index,
41205469607a00d84a07dc638eda46a87fc90142d64breed@android.com				   HB_Buffer        buffer )
41215469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
41225469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error  error, retError = HB_Err_Not_Covered;
41235469607a00d84a07dc638eda46a87fc90142d64breed@android.com
41245469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt*  properties = gsub->LookupList.Properties;
41255469607a00d84a07dc638eda46a87fc90142d64breed@android.com  int       lookup_type = gsub->LookupList.Lookup[lookup_index].LookupType;
41265469607a00d84a07dc638eda46a87fc90142d64breed@android.com
41275469607a00d84a07dc638eda46a87fc90142d64breed@android.com  const int       nesting_level = 0;
41285469607a00d84a07dc638eda46a87fc90142d64breed@android.com  /* 0xFFFF indicates that we don't have a context length yet */
41295469607a00d84a07dc638eda46a87fc90142d64breed@android.com  const HB_UShort context_length = 0xFFFF;
41305469607a00d84a07dc638eda46a87fc90142d64breed@android.com
41315469607a00d84a07dc638eda46a87fc90142d64breed@android.com  switch (lookup_type) {
41325469607a00d84a07dc638eda46a87fc90142d64breed@android.com
41335469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case HB_GSUB_LOOKUP_SINGLE:
41345469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case HB_GSUB_LOOKUP_MULTIPLE:
41355469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case HB_GSUB_LOOKUP_ALTERNATE:
41365469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case HB_GSUB_LOOKUP_LIGATURE:
41375469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case HB_GSUB_LOOKUP_CONTEXT:
41385469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case HB_GSUB_LOOKUP_CHAIN:
41395469607a00d84a07dc638eda46a87fc90142d64breed@android.com      /* in/out forward substitution (implemented lazy) */
41405469607a00d84a07dc638eda46a87fc90142d64breed@android.com
41415469607a00d84a07dc638eda46a87fc90142d64breed@android.com      _hb_buffer_clear_output ( buffer );
41425469607a00d84a07dc638eda46a87fc90142d64breed@android.com      buffer->in_pos = 0;
41435469607a00d84a07dc638eda46a87fc90142d64breed@android.com  while ( buffer->in_pos < buffer->in_length )
41445469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
41455469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
41465469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
41475469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  error = GSUB_Do_Glyph_Lookup( gsub, lookup_index, buffer, context_length, nesting_level );
41485469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( error )
41495469607a00d84a07dc638eda46a87fc90142d64breed@android.com      {
41505469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( error != HB_Err_Not_Covered )
41515469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  return error;
41525469607a00d84a07dc638eda46a87fc90142d64breed@android.com      }
41535469607a00d84a07dc638eda46a87fc90142d64breed@android.com      else
41545469607a00d84a07dc638eda46a87fc90142d64breed@android.com	retError = error;
41555469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
41565469607a00d84a07dc638eda46a87fc90142d64breed@android.com    else
41575469607a00d84a07dc638eda46a87fc90142d64breed@android.com      error = HB_Err_Not_Covered;
41585469607a00d84a07dc638eda46a87fc90142d64breed@android.com
41595469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if ( error == HB_Err_Not_Covered )
41605469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  if ( COPY_Glyph ( buffer ) )
41615469607a00d84a07dc638eda46a87fc90142d64breed@android.com	return error;
41625469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
41635469607a00d84a07dc638eda46a87fc90142d64breed@android.com      /* we shouldn't swap if error occurred.
41645469607a00d84a07dc638eda46a87fc90142d64breed@android.com       *
41655469607a00d84a07dc638eda46a87fc90142d64breed@android.com       * also don't swap if nothing changed (ie HB_Err_Not_Covered).
41665469607a00d84a07dc638eda46a87fc90142d64breed@android.com       * shouldn't matter in that case though.
41675469607a00d84a07dc638eda46a87fc90142d64breed@android.com       */
41685469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( retError == HB_Err_Ok )
41695469607a00d84a07dc638eda46a87fc90142d64breed@android.com	_hb_buffer_swap( buffer );
41705469607a00d84a07dc638eda46a87fc90142d64breed@android.com
41715469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return retError;
41725469607a00d84a07dc638eda46a87fc90142d64breed@android.com
41735469607a00d84a07dc638eda46a87fc90142d64breed@android.com    case HB_GSUB_LOOKUP_REVERSE_CHAIN:
41745469607a00d84a07dc638eda46a87fc90142d64breed@android.com      /* in-place backward substitution */
41755469607a00d84a07dc638eda46a87fc90142d64breed@android.com
41765469607a00d84a07dc638eda46a87fc90142d64breed@android.com      buffer->in_pos = buffer->in_length - 1;
41775469607a00d84a07dc638eda46a87fc90142d64breed@android.com    do
41785469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
41795469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
41805469607a00d84a07dc638eda46a87fc90142d64breed@android.com	{
41815469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  error = GSUB_Do_Glyph_Lookup( gsub, lookup_index, buffer, context_length, nesting_level );
41825469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  if ( error )
41835469607a00d84a07dc638eda46a87fc90142d64breed@android.com	    {
41845469607a00d84a07dc638eda46a87fc90142d64breed@android.com	      if ( error != HB_Err_Not_Covered )
41855469607a00d84a07dc638eda46a87fc90142d64breed@android.com		return error;
41865469607a00d84a07dc638eda46a87fc90142d64breed@android.com	    }
41875469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  else
41885469607a00d84a07dc638eda46a87fc90142d64breed@android.com	    retError = error;
41895469607a00d84a07dc638eda46a87fc90142d64breed@android.com	}
41905469607a00d84a07dc638eda46a87fc90142d64breed@android.com	else
41915469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  error = HB_Err_Not_Covered;
41925469607a00d84a07dc638eda46a87fc90142d64breed@android.com
41935469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( error == HB_Err_Not_Covered )
41945469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  buffer->in_pos--;
41955469607a00d84a07dc638eda46a87fc90142d64breed@android.com      }
41965469607a00d84a07dc638eda46a87fc90142d64breed@android.com      while ((HB_Int) buffer->in_pos >= 0);
41975469607a00d84a07dc638eda46a87fc90142d64breed@android.com
41985469607a00d84a07dc638eda46a87fc90142d64breed@android.com      return retError;
41995469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42005469607a00d84a07dc638eda46a87fc90142d64breed@android.com  /*case HB_GSUB_LOOKUP_EXTENSION:*/
42015469607a00d84a07dc638eda46a87fc90142d64breed@android.com    default:
42025469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return retError;
42035469607a00d84a07dc638eda46a87fc90142d64breed@android.com  };
42045469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
42055469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42065469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42075469607a00d84a07dc638eda46a87fc90142d64breed@android.comHB_Error  HB_GSUB_Add_Feature( HB_GSUBHeader*  gsub,
42085469607a00d84a07dc638eda46a87fc90142d64breed@android.com			       HB_UShort        feature_index,
42095469607a00d84a07dc638eda46a87fc90142d64breed@android.com			       HB_UInt          property )
42105469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
42115469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort    i;
42125469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42135469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Feature  feature;
42145469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt*     properties;
42155469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort*   index;
42165469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort    lookup_count;
42175469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42185469607a00d84a07dc638eda46a87fc90142d64breed@android.com  /* Each feature can only be added once */
42195469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42205469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( !gsub ||
42215469607a00d84a07dc638eda46a87fc90142d64breed@android.com       feature_index >= gsub->FeatureList.FeatureCount ||
42225469607a00d84a07dc638eda46a87fc90142d64breed@android.com       gsub->FeatureList.ApplyCount == gsub->FeatureList.FeatureCount )
42235469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return ERR(HB_Err_Invalid_Argument);
42245469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42255469607a00d84a07dc638eda46a87fc90142d64breed@android.com  gsub->FeatureList.ApplyOrder[gsub->FeatureList.ApplyCount++] = feature_index;
42265469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42275469607a00d84a07dc638eda46a87fc90142d64breed@android.com  properties = gsub->LookupList.Properties;
42285469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42295469607a00d84a07dc638eda46a87fc90142d64breed@android.com  feature = gsub->FeatureList.FeatureRecord[feature_index].Feature;
42305469607a00d84a07dc638eda46a87fc90142d64breed@android.com  index   = feature.LookupListIndex;
42315469607a00d84a07dc638eda46a87fc90142d64breed@android.com  lookup_count = gsub->LookupList.LookupCount;
42325469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42335469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( i = 0; i < feature.LookupListCount; i++ )
42345469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
42355469607a00d84a07dc638eda46a87fc90142d64breed@android.com    HB_UShort lookup_index = index[i];
42365469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if (lookup_index < lookup_count)
42375469607a00d84a07dc638eda46a87fc90142d64breed@android.com      properties[lookup_index] |= property;
42385469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
42395469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42405469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
42415469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
42425469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42435469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42445469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42455469607a00d84a07dc638eda46a87fc90142d64breed@android.comHB_Error  HB_GSUB_Clear_Features( HB_GSUBHeader*  gsub )
42465469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
42475469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UShort i;
42485469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42495469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_UInt*  properties;
42505469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42515469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42525469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( !gsub )
42535469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return ERR(HB_Err_Invalid_Argument);
42545469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42555469607a00d84a07dc638eda46a87fc90142d64breed@android.com  gsub->FeatureList.ApplyCount = 0;
42565469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42575469607a00d84a07dc638eda46a87fc90142d64breed@android.com  properties = gsub->LookupList.Properties;
42585469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42595469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( i = 0; i < gsub->LookupList.LookupCount; i++ )
42605469607a00d84a07dc638eda46a87fc90142d64breed@android.com    properties[i] = 0;
42615469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42625469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
42635469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
42645469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42655469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42665469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42675469607a00d84a07dc638eda46a87fc90142d64breed@android.comHB_Error  HB_GSUB_Register_Alternate_Function( HB_GSUBHeader*  gsub,
42685469607a00d84a07dc638eda46a87fc90142d64breed@android.com					       HB_AltFunction  altfunc,
42695469607a00d84a07dc638eda46a87fc90142d64breed@android.com					       void*            data )
42705469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
42715469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( !gsub )
42725469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return ERR(HB_Err_Invalid_Argument);
42735469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42745469607a00d84a07dc638eda46a87fc90142d64breed@android.com  gsub->altfunc = altfunc;
42755469607a00d84a07dc638eda46a87fc90142d64breed@android.com  gsub->data    = data;
42765469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42775469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return HB_Err_Ok;
42785469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
42795469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42805469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* returns error if one happened, otherwise returns HB_Err_Not_Covered if no
42815469607a00d84a07dc638eda46a87fc90142d64breed@android.com * feature were applied, or HB_Err_Ok otherwise.
42825469607a00d84a07dc638eda46a87fc90142d64breed@android.com */
42835469607a00d84a07dc638eda46a87fc90142d64breed@android.comHB_Error  HB_GSUB_Apply_String( HB_GSUBHeader*   gsub,
42845469607a00d84a07dc638eda46a87fc90142d64breed@android.com				HB_Buffer        buffer )
42855469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
42865469607a00d84a07dc638eda46a87fc90142d64breed@android.com  HB_Error          error, retError = HB_Err_Not_Covered;
42875469607a00d84a07dc638eda46a87fc90142d64breed@android.com  int               i, j, lookup_count, num_features;
42885469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42895469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( !gsub ||
42905469607a00d84a07dc638eda46a87fc90142d64breed@android.com       !buffer)
42915469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return ERR(HB_Err_Invalid_Argument);
42925469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42935469607a00d84a07dc638eda46a87fc90142d64breed@android.com  if ( buffer->in_length == 0 )
42945469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return retError;
42955469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42965469607a00d84a07dc638eda46a87fc90142d64breed@android.com  lookup_count = gsub->LookupList.LookupCount;
42975469607a00d84a07dc638eda46a87fc90142d64breed@android.com  num_features = gsub->FeatureList.ApplyCount;
42985469607a00d84a07dc638eda46a87fc90142d64breed@android.com
42995469607a00d84a07dc638eda46a87fc90142d64breed@android.com  for ( i = 0; i < num_features; i++)
43005469607a00d84a07dc638eda46a87fc90142d64breed@android.com  {
43015469607a00d84a07dc638eda46a87fc90142d64breed@android.com    HB_UShort  feature_index = gsub->FeatureList.ApplyOrder[i];
43025469607a00d84a07dc638eda46a87fc90142d64breed@android.com    HB_Feature feature = gsub->FeatureList.FeatureRecord[feature_index].Feature;
43035469607a00d84a07dc638eda46a87fc90142d64breed@android.com
43045469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for ( j = 0; j < feature.LookupListCount; j++ )
43055469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {
43065469607a00d84a07dc638eda46a87fc90142d64breed@android.com      HB_UShort         lookup_index = feature.LookupListIndex[j];
43075469607a00d84a07dc638eda46a87fc90142d64breed@android.com
43085469607a00d84a07dc638eda46a87fc90142d64breed@android.com      /* Skip nonexistant lookups */
43095469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if (lookup_index >= lookup_count)
43105469607a00d84a07dc638eda46a87fc90142d64breed@android.com       continue;
43115469607a00d84a07dc638eda46a87fc90142d64breed@android.com
43125469607a00d84a07dc638eda46a87fc90142d64breed@android.com	error = GSUB_Do_String_Lookup( gsub, lookup_index, buffer );
43135469607a00d84a07dc638eda46a87fc90142d64breed@android.com      if ( error )
43145469607a00d84a07dc638eda46a87fc90142d64breed@android.com      {
43155469607a00d84a07dc638eda46a87fc90142d64breed@android.com	if ( error != HB_Err_Not_Covered )
43165469607a00d84a07dc638eda46a87fc90142d64breed@android.com	  return error;
43175469607a00d84a07dc638eda46a87fc90142d64breed@android.com      }
43185469607a00d84a07dc638eda46a87fc90142d64breed@android.com      else
43195469607a00d84a07dc638eda46a87fc90142d64breed@android.com	retError = error;
43205469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
43215469607a00d84a07dc638eda46a87fc90142d64breed@android.com  }
43225469607a00d84a07dc638eda46a87fc90142d64breed@android.com
43235469607a00d84a07dc638eda46a87fc90142d64breed@android.com  error = retError;
43245469607a00d84a07dc638eda46a87fc90142d64breed@android.com
43255469607a00d84a07dc638eda46a87fc90142d64breed@android.com  return error;
43265469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
43275469607a00d84a07dc638eda46a87fc90142d64breed@android.com
43285469607a00d84a07dc638eda46a87fc90142d64breed@android.com
43295469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* END */
4330