15569331642446be05292e3e1f8a51218827168cdclaireho/*
25569331642446be05292e3e1f8a51218827168cdclaireho * Copyright (C) 1998-2004  David Turner and Werner Lemberg
35569331642446be05292e3e1f8a51218827168cdclaireho * Copyright (C) 2006  Behdad Esfahbod
45569331642446be05292e3e1f8a51218827168cdclaireho * Copyright (C) 2007  Red Hat, Inc.
55569331642446be05292e3e1f8a51218827168cdclaireho *
65569331642446be05292e3e1f8a51218827168cdclaireho * This is part of HarfBuzz, an OpenType Layout engine library.
75569331642446be05292e3e1f8a51218827168cdclaireho *
85569331642446be05292e3e1f8a51218827168cdclaireho * Permission is hereby granted, without written agreement and without
95569331642446be05292e3e1f8a51218827168cdclaireho * license or royalty fees, to use, copy, modify, and distribute this
105569331642446be05292e3e1f8a51218827168cdclaireho * software and its documentation for any purpose, provided that the
115569331642446be05292e3e1f8a51218827168cdclaireho * above copyright notice and the following two paragraphs appear in
125569331642446be05292e3e1f8a51218827168cdclaireho * all copies of this software.
135569331642446be05292e3e1f8a51218827168cdclaireho *
145569331642446be05292e3e1f8a51218827168cdclaireho * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
155569331642446be05292e3e1f8a51218827168cdclaireho * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
165569331642446be05292e3e1f8a51218827168cdclaireho * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
175569331642446be05292e3e1f8a51218827168cdclaireho * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
185569331642446be05292e3e1f8a51218827168cdclaireho * DAMAGE.
195569331642446be05292e3e1f8a51218827168cdclaireho *
205569331642446be05292e3e1f8a51218827168cdclaireho * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
215569331642446be05292e3e1f8a51218827168cdclaireho * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
225569331642446be05292e3e1f8a51218827168cdclaireho * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
235569331642446be05292e3e1f8a51218827168cdclaireho * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
245569331642446be05292e3e1f8a51218827168cdclaireho * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
255569331642446be05292e3e1f8a51218827168cdclaireho *
265569331642446be05292e3e1f8a51218827168cdclaireho * Red Hat Author(s): Behdad Esfahbod
275569331642446be05292e3e1f8a51218827168cdclaireho */
285569331642446be05292e3e1f8a51218827168cdclaireho
295569331642446be05292e3e1f8a51218827168cdclaireho#include "harfbuzz-impl.h"
305569331642446be05292e3e1f8a51218827168cdclaireho#include "harfbuzz-gpos-private.h"
315569331642446be05292e3e1f8a51218827168cdclaireho#include "harfbuzz-open-private.h"
325569331642446be05292e3e1f8a51218827168cdclaireho#include "harfbuzz-gdef-private.h"
335569331642446be05292e3e1f8a51218827168cdclaireho#include "harfbuzz-shaper.h"
345569331642446be05292e3e1f8a51218827168cdclaireho
355569331642446be05292e3e1f8a51218827168cdclairehostruct  GPOS_Instance_
365569331642446be05292e3e1f8a51218827168cdclaireho{
375569331642446be05292e3e1f8a51218827168cdclaireho  HB_GPOSHeader*  gpos;
385569331642446be05292e3e1f8a51218827168cdclaireho  HB_Font          font;
395569331642446be05292e3e1f8a51218827168cdclaireho  HB_Bool          dvi;
405569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        load_flags;  /* how the glyph should be loaded */
415569331642446be05292e3e1f8a51218827168cdclaireho  HB_Bool          r2l;
425569331642446be05292e3e1f8a51218827168cdclaireho
435569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        last;        /* the last valid glyph -- used
445569331642446be05292e3e1f8a51218827168cdclaireho				   with cursive positioning     */
455569331642446be05292e3e1f8a51218827168cdclaireho  HB_Fixed           anchor_x;    /* the coordinates of the anchor point */
465569331642446be05292e3e1f8a51218827168cdclaireho  HB_Fixed           anchor_y;    /* of the last valid glyph             */
475569331642446be05292e3e1f8a51218827168cdclaireho};
485569331642446be05292e3e1f8a51218827168cdclaireho
495569331642446be05292e3e1f8a51218827168cdclairehotypedef struct GPOS_Instance_  GPOS_Instance;
505569331642446be05292e3e1f8a51218827168cdclaireho
515569331642446be05292e3e1f8a51218827168cdclaireho
525569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  GPOS_Do_Glyph_Lookup( GPOS_Instance*    gpi,
535569331642446be05292e3e1f8a51218827168cdclaireho				       HB_UShort         lookup_index,
545569331642446be05292e3e1f8a51218827168cdclaireho				       HB_Buffer        buffer,
555569331642446be05292e3e1f8a51218827168cdclaireho				       HB_UShort         context_length,
565569331642446be05292e3e1f8a51218827168cdclaireho				       int               nesting_level );
575569331642446be05292e3e1f8a51218827168cdclaireho
585569331642446be05292e3e1f8a51218827168cdclaireho
595569331642446be05292e3e1f8a51218827168cdclaireho
6057e6107a9d66a9a97b146def0ef38c010f954be6claireho#ifdef HB_SUPPORT_MULTIPLE_MASTER
615569331642446be05292e3e1f8a51218827168cdclaireho/* the client application must replace this with something more
625569331642446be05292e3e1f8a51218827168cdclaireho   meaningful if multiple master fonts are to be supported.     */
635569331642446be05292e3e1f8a51218827168cdclaireho
645569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  default_mmfunc( HB_Font      font,
655569331642446be05292e3e1f8a51218827168cdclaireho				 HB_UShort    metric_id,
665569331642446be05292e3e1f8a51218827168cdclaireho				 HB_Fixed*      metric_value,
675569331642446be05292e3e1f8a51218827168cdclaireho				 void*        data )
685569331642446be05292e3e1f8a51218827168cdclaireho{
695569331642446be05292e3e1f8a51218827168cdclaireho  HB_UNUSED(font);
705569331642446be05292e3e1f8a51218827168cdclaireho  HB_UNUSED(metric_id);
715569331642446be05292e3e1f8a51218827168cdclaireho  HB_UNUSED(metric_value);
725569331642446be05292e3e1f8a51218827168cdclaireho  HB_UNUSED(data);
735569331642446be05292e3e1f8a51218827168cdclaireho  return ERR(HB_Err_Not_Covered); /* ERR() call intended */
745569331642446be05292e3e1f8a51218827168cdclaireho}
7557e6107a9d66a9a97b146def0ef38c010f954be6claireho#endif
765569331642446be05292e3e1f8a51218827168cdclaireho
775569331642446be05292e3e1f8a51218827168cdclaireho
785569331642446be05292e3e1f8a51218827168cdclaireho
795569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_Load_GPOS_Table( HB_Stream stream,
805569331642446be05292e3e1f8a51218827168cdclaireho			      HB_GPOSHeader** retptr,
815569331642446be05292e3e1f8a51218827168cdclaireho			      HB_GDEFHeader*  gdef,
825569331642446be05292e3e1f8a51218827168cdclaireho			      HB_Stream       gdefStream )
835569331642446be05292e3e1f8a51218827168cdclaireho{
845569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt         cur_offset, new_offset, base_offset;
855569331642446be05292e3e1f8a51218827168cdclaireho
865569331642446be05292e3e1f8a51218827168cdclaireho  HB_GPOSHeader*  gpos;
875569331642446be05292e3e1f8a51218827168cdclaireho
885569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error   error;
895569331642446be05292e3e1f8a51218827168cdclaireho
905569331642446be05292e3e1f8a51218827168cdclaireho
915569331642446be05292e3e1f8a51218827168cdclaireho  if ( !retptr )
925569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
935569331642446be05292e3e1f8a51218827168cdclaireho
945569331642446be05292e3e1f8a51218827168cdclaireho  if ( GOTO_Table( TTAG_GPOS ) )
955569331642446be05292e3e1f8a51218827168cdclaireho    return error;
965569331642446be05292e3e1f8a51218827168cdclaireho
975569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
985569331642446be05292e3e1f8a51218827168cdclaireho
995569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC ( gpos, sizeof( *gpos ) ) )
1005569331642446be05292e3e1f8a51218827168cdclaireho    return error;
1015569331642446be05292e3e1f8a51218827168cdclaireho
10257e6107a9d66a9a97b146def0ef38c010f954be6claireho#ifdef HB_SUPPORT_MULTIPLE_MASTER
1035569331642446be05292e3e1f8a51218827168cdclaireho  gpos->mmfunc = default_mmfunc;
10457e6107a9d66a9a97b146def0ef38c010f954be6claireho#endif
1055569331642446be05292e3e1f8a51218827168cdclaireho
1065569331642446be05292e3e1f8a51218827168cdclaireho  /* skip version */
1075569331642446be05292e3e1f8a51218827168cdclaireho
1085569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( base_offset + 4L ) ||
1095569331642446be05292e3e1f8a51218827168cdclaireho       ACCESS_Frame( 2L ) )
1105569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
1115569331642446be05292e3e1f8a51218827168cdclaireho
1125569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
1135569331642446be05292e3e1f8a51218827168cdclaireho
1145569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
1155569331642446be05292e3e1f8a51218827168cdclaireho
1165569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
1175569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
1185569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_ScriptList( &gpos->ScriptList,
1195569331642446be05292e3e1f8a51218827168cdclaireho				  stream ) ) != HB_Err_Ok )
1205569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
1215569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
1225569331642446be05292e3e1f8a51218827168cdclaireho
1235569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
1245569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
1255569331642446be05292e3e1f8a51218827168cdclaireho
1265569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
1275569331642446be05292e3e1f8a51218827168cdclaireho
1285569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
1295569331642446be05292e3e1f8a51218827168cdclaireho
1305569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
1315569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
1325569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_FeatureList( &gpos->FeatureList,
1335569331642446be05292e3e1f8a51218827168cdclaireho				   stream ) ) != HB_Err_Ok )
1345569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
1355569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
1365569331642446be05292e3e1f8a51218827168cdclaireho
1375569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
1385569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
1395569331642446be05292e3e1f8a51218827168cdclaireho
1405569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
1415569331642446be05292e3e1f8a51218827168cdclaireho
1425569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
1435569331642446be05292e3e1f8a51218827168cdclaireho
1445569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
1455569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
1465569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_LookupList( &gpos->LookupList,
1475569331642446be05292e3e1f8a51218827168cdclaireho				  stream, HB_Type_GPOS ) ) != HB_Err_Ok )
1485569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
1495569331642446be05292e3e1f8a51218827168cdclaireho
1505569331642446be05292e3e1f8a51218827168cdclaireho  gpos->gdef = gdef;      /* can be NULL */
1515569331642446be05292e3e1f8a51218827168cdclaireho
1525569331642446be05292e3e1f8a51218827168cdclaireho  if ( ( error =  _HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( gdef, gdefStream,
1535569331642446be05292e3e1f8a51218827168cdclaireho								     gpos->LookupList.Lookup,
1545569331642446be05292e3e1f8a51218827168cdclaireho								     gpos->LookupList.LookupCount ) ) )
1555569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail1;
1565569331642446be05292e3e1f8a51218827168cdclaireho
1575569331642446be05292e3e1f8a51218827168cdclaireho  *retptr = gpos;
1585569331642446be05292e3e1f8a51218827168cdclaireho
1595569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
1605569331642446be05292e3e1f8a51218827168cdclaireho
1615569331642446be05292e3e1f8a51218827168cdclairehoFail1:
1625569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_LookupList( &gpos->LookupList, HB_Type_GPOS );
1635569331642446be05292e3e1f8a51218827168cdclaireho
1645569331642446be05292e3e1f8a51218827168cdclairehoFail2:
1655569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_FeatureList( &gpos->FeatureList );
1665569331642446be05292e3e1f8a51218827168cdclaireho
1675569331642446be05292e3e1f8a51218827168cdclairehoFail3:
1685569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_ScriptList( &gpos->ScriptList );
1695569331642446be05292e3e1f8a51218827168cdclaireho
1705569331642446be05292e3e1f8a51218827168cdclairehoFail4:
1715569331642446be05292e3e1f8a51218827168cdclaireho  FREE( gpos );
1725569331642446be05292e3e1f8a51218827168cdclaireho
1735569331642446be05292e3e1f8a51218827168cdclaireho  return error;
1745569331642446be05292e3e1f8a51218827168cdclaireho}
1755569331642446be05292e3e1f8a51218827168cdclaireho
1765569331642446be05292e3e1f8a51218827168cdclaireho
1775569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_Done_GPOS_Table( HB_GPOSHeader* gpos )
1785569331642446be05292e3e1f8a51218827168cdclaireho{
1795569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_LookupList( &gpos->LookupList, HB_Type_GPOS );
1805569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_FeatureList( &gpos->FeatureList );
1815569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_ScriptList( &gpos->ScriptList );
1825569331642446be05292e3e1f8a51218827168cdclaireho
1835569331642446be05292e3e1f8a51218827168cdclaireho  FREE( gpos );
1845569331642446be05292e3e1f8a51218827168cdclaireho
1855569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
1865569331642446be05292e3e1f8a51218827168cdclaireho}
1875569331642446be05292e3e1f8a51218827168cdclaireho
1885569331642446be05292e3e1f8a51218827168cdclaireho
1895569331642446be05292e3e1f8a51218827168cdclaireho/*****************************
1905569331642446be05292e3e1f8a51218827168cdclaireho * SubTable related functions
1915569331642446be05292e3e1f8a51218827168cdclaireho *****************************/
1925569331642446be05292e3e1f8a51218827168cdclaireho
1935569331642446be05292e3e1f8a51218827168cdclaireho/* shared tables */
1945569331642446be05292e3e1f8a51218827168cdclaireho
1955569331642446be05292e3e1f8a51218827168cdclaireho/* ValueRecord */
1965569331642446be05292e3e1f8a51218827168cdclaireho
1975569331642446be05292e3e1f8a51218827168cdclaireho/* There is a subtle difference in the specs between a `table' and a
1985569331642446be05292e3e1f8a51218827168cdclaireho   `record' -- offsets for device tables in ValueRecords are taken from
1995569331642446be05292e3e1f8a51218827168cdclaireho   the parent table and not the parent record.                          */
2005569331642446be05292e3e1f8a51218827168cdclaireho
2015569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ValueRecord( HB_ValueRecord*  vr,
2025569331642446be05292e3e1f8a51218827168cdclaireho				   HB_UShort         format,
2035569331642446be05292e3e1f8a51218827168cdclaireho				   HB_UInt          base_offset,
2045569331642446be05292e3e1f8a51218827168cdclaireho				   HB_Stream         stream )
2055569331642446be05292e3e1f8a51218827168cdclaireho{
2065569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
2075569331642446be05292e3e1f8a51218827168cdclaireho
2085569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt cur_offset, new_offset;
2095569331642446be05292e3e1f8a51218827168cdclaireho
2105569331642446be05292e3e1f8a51218827168cdclaireho
2115569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT )
2125569331642446be05292e3e1f8a51218827168cdclaireho  {
2135569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
2145569331642446be05292e3e1f8a51218827168cdclaireho      return error;
2155569331642446be05292e3e1f8a51218827168cdclaireho
2165569331642446be05292e3e1f8a51218827168cdclaireho    vr->XPlacement = GET_Short();
2175569331642446be05292e3e1f8a51218827168cdclaireho
2185569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
2195569331642446be05292e3e1f8a51218827168cdclaireho  }
2205569331642446be05292e3e1f8a51218827168cdclaireho  else
2215569331642446be05292e3e1f8a51218827168cdclaireho    vr->XPlacement = 0;
2225569331642446be05292e3e1f8a51218827168cdclaireho
2235569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT )
2245569331642446be05292e3e1f8a51218827168cdclaireho  {
2255569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
2265569331642446be05292e3e1f8a51218827168cdclaireho      return error;
2275569331642446be05292e3e1f8a51218827168cdclaireho
2285569331642446be05292e3e1f8a51218827168cdclaireho    vr->YPlacement = GET_Short();
2295569331642446be05292e3e1f8a51218827168cdclaireho
2305569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
2315569331642446be05292e3e1f8a51218827168cdclaireho  }
2325569331642446be05292e3e1f8a51218827168cdclaireho  else
2335569331642446be05292e3e1f8a51218827168cdclaireho    vr->YPlacement = 0;
2345569331642446be05292e3e1f8a51218827168cdclaireho
2355569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE )
2365569331642446be05292e3e1f8a51218827168cdclaireho  {
2375569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
2385569331642446be05292e3e1f8a51218827168cdclaireho      return error;
2395569331642446be05292e3e1f8a51218827168cdclaireho
2405569331642446be05292e3e1f8a51218827168cdclaireho    vr->XAdvance = GET_Short();
2415569331642446be05292e3e1f8a51218827168cdclaireho
2425569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
2435569331642446be05292e3e1f8a51218827168cdclaireho  }
2445569331642446be05292e3e1f8a51218827168cdclaireho  else
2455569331642446be05292e3e1f8a51218827168cdclaireho    vr->XAdvance = 0;
2465569331642446be05292e3e1f8a51218827168cdclaireho
2475569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE )
2485569331642446be05292e3e1f8a51218827168cdclaireho  {
2495569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
2505569331642446be05292e3e1f8a51218827168cdclaireho      return error;
2515569331642446be05292e3e1f8a51218827168cdclaireho
2525569331642446be05292e3e1f8a51218827168cdclaireho    vr->YAdvance = GET_Short();
2535569331642446be05292e3e1f8a51218827168cdclaireho
2545569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
2555569331642446be05292e3e1f8a51218827168cdclaireho  }
2565569331642446be05292e3e1f8a51218827168cdclaireho  else
2575569331642446be05292e3e1f8a51218827168cdclaireho    vr->YAdvance = 0;
2585569331642446be05292e3e1f8a51218827168cdclaireho
25957e6107a9d66a9a97b146def0ef38c010f954be6claireho  if ( format & HB_GPOS_FORMAT_HAVE_DEVICE_TABLES )
26057e6107a9d66a9a97b146def0ef38c010f954be6claireho  {
26157e6107a9d66a9a97b146def0ef38c010f954be6claireho    if ( ALLOC_ARRAY( vr->DeviceTables, 4, HB_Device ) )
26257e6107a9d66a9a97b146def0ef38c010f954be6claireho      return error;
26357e6107a9d66a9a97b146def0ef38c010f954be6claireho    vr->DeviceTables[VR_X_ADVANCE_DEVICE] = 0;
26457e6107a9d66a9a97b146def0ef38c010f954be6claireho    vr->DeviceTables[VR_Y_ADVANCE_DEVICE] = 0;
26557e6107a9d66a9a97b146def0ef38c010f954be6claireho    vr->DeviceTables[VR_X_PLACEMENT_DEVICE] = 0;
26657e6107a9d66a9a97b146def0ef38c010f954be6claireho    vr->DeviceTables[VR_Y_PLACEMENT_DEVICE] = 0;
26757e6107a9d66a9a97b146def0ef38c010f954be6claireho  }
26857e6107a9d66a9a97b146def0ef38c010f954be6claireho  else
26957e6107a9d66a9a97b146def0ef38c010f954be6claireho  {
27057e6107a9d66a9a97b146def0ef38c010f954be6claireho    vr->DeviceTables = 0;
27157e6107a9d66a9a97b146def0ef38c010f954be6claireho  }
27257e6107a9d66a9a97b146def0ef38c010f954be6claireho
2735569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )
2745569331642446be05292e3e1f8a51218827168cdclaireho  {
2755569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
27657e6107a9d66a9a97b146def0ef38c010f954be6claireho      goto Fail4;
2775569331642446be05292e3e1f8a51218827168cdclaireho
2785569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort();
2795569331642446be05292e3e1f8a51218827168cdclaireho
2805569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
2815569331642446be05292e3e1f8a51218827168cdclaireho
2825569331642446be05292e3e1f8a51218827168cdclaireho    if ( new_offset )
2835569331642446be05292e3e1f8a51218827168cdclaireho    {
2845569331642446be05292e3e1f8a51218827168cdclaireho      new_offset += base_offset;
2855569331642446be05292e3e1f8a51218827168cdclaireho
2865569331642446be05292e3e1f8a51218827168cdclaireho      cur_offset = FILE_Pos();
2875569331642446be05292e3e1f8a51218827168cdclaireho      if ( FILE_Seek( new_offset ) ||
28857e6107a9d66a9a97b146def0ef38c010f954be6claireho	   ( error = _HB_OPEN_Load_Device( &vr->DeviceTables[VR_X_PLACEMENT_DEVICE],
2895569331642446be05292e3e1f8a51218827168cdclaireho				  stream ) ) != HB_Err_Ok )
29057e6107a9d66a9a97b146def0ef38c010f954be6claireho       goto Fail4;
2915569331642446be05292e3e1f8a51218827168cdclaireho      (void)FILE_Seek( cur_offset );
2925569331642446be05292e3e1f8a51218827168cdclaireho    }
2935569331642446be05292e3e1f8a51218827168cdclaireho  }
2945569331642446be05292e3e1f8a51218827168cdclaireho
2955569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )
2965569331642446be05292e3e1f8a51218827168cdclaireho  {
2975569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
2985569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail3;
2995569331642446be05292e3e1f8a51218827168cdclaireho
3005569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort();
3015569331642446be05292e3e1f8a51218827168cdclaireho
3025569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
3035569331642446be05292e3e1f8a51218827168cdclaireho
3045569331642446be05292e3e1f8a51218827168cdclaireho    if ( new_offset )
3055569331642446be05292e3e1f8a51218827168cdclaireho    {
3065569331642446be05292e3e1f8a51218827168cdclaireho      new_offset += base_offset;
3075569331642446be05292e3e1f8a51218827168cdclaireho
3085569331642446be05292e3e1f8a51218827168cdclaireho      cur_offset = FILE_Pos();
3095569331642446be05292e3e1f8a51218827168cdclaireho      if ( FILE_Seek( new_offset ) ||
31057e6107a9d66a9a97b146def0ef38c010f954be6claireho	   ( error = _HB_OPEN_Load_Device( &vr->DeviceTables[VR_Y_PLACEMENT_DEVICE],
3115569331642446be05292e3e1f8a51218827168cdclaireho				  stream ) ) != HB_Err_Ok )
3125569331642446be05292e3e1f8a51218827168cdclaireho	goto Fail3;
3135569331642446be05292e3e1f8a51218827168cdclaireho      (void)FILE_Seek( cur_offset );
3145569331642446be05292e3e1f8a51218827168cdclaireho    }
3155569331642446be05292e3e1f8a51218827168cdclaireho  }
3165569331642446be05292e3e1f8a51218827168cdclaireho
3175569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )
3185569331642446be05292e3e1f8a51218827168cdclaireho  {
3195569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
3205569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail2;
3215569331642446be05292e3e1f8a51218827168cdclaireho
3225569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort();
3235569331642446be05292e3e1f8a51218827168cdclaireho
3245569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
3255569331642446be05292e3e1f8a51218827168cdclaireho
3265569331642446be05292e3e1f8a51218827168cdclaireho    if ( new_offset )
3275569331642446be05292e3e1f8a51218827168cdclaireho    {
3285569331642446be05292e3e1f8a51218827168cdclaireho      new_offset += base_offset;
3295569331642446be05292e3e1f8a51218827168cdclaireho
3305569331642446be05292e3e1f8a51218827168cdclaireho      cur_offset = FILE_Pos();
3315569331642446be05292e3e1f8a51218827168cdclaireho      if ( FILE_Seek( new_offset ) ||
33257e6107a9d66a9a97b146def0ef38c010f954be6claireho	   ( error = _HB_OPEN_Load_Device( &vr->DeviceTables[VR_X_ADVANCE_DEVICE],
3335569331642446be05292e3e1f8a51218827168cdclaireho				  stream ) ) != HB_Err_Ok )
3345569331642446be05292e3e1f8a51218827168cdclaireho	goto Fail2;
3355569331642446be05292e3e1f8a51218827168cdclaireho      (void)FILE_Seek( cur_offset );
3365569331642446be05292e3e1f8a51218827168cdclaireho    }
3375569331642446be05292e3e1f8a51218827168cdclaireho  }
3385569331642446be05292e3e1f8a51218827168cdclaireho
3395569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )
3405569331642446be05292e3e1f8a51218827168cdclaireho  {
3415569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
3425569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
3435569331642446be05292e3e1f8a51218827168cdclaireho
3445569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort();
3455569331642446be05292e3e1f8a51218827168cdclaireho
3465569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
3475569331642446be05292e3e1f8a51218827168cdclaireho
3485569331642446be05292e3e1f8a51218827168cdclaireho    if ( new_offset )
3495569331642446be05292e3e1f8a51218827168cdclaireho    {
3505569331642446be05292e3e1f8a51218827168cdclaireho      new_offset += base_offset;
3515569331642446be05292e3e1f8a51218827168cdclaireho
3525569331642446be05292e3e1f8a51218827168cdclaireho      cur_offset = FILE_Pos();
3535569331642446be05292e3e1f8a51218827168cdclaireho      if ( FILE_Seek( new_offset ) ||
35457e6107a9d66a9a97b146def0ef38c010f954be6claireho	   ( error = _HB_OPEN_Load_Device( &vr->DeviceTables[VR_Y_ADVANCE_DEVICE],
3555569331642446be05292e3e1f8a51218827168cdclaireho				  stream ) ) != HB_Err_Ok )
3565569331642446be05292e3e1f8a51218827168cdclaireho	goto Fail1;
3575569331642446be05292e3e1f8a51218827168cdclaireho      (void)FILE_Seek( cur_offset );
3585569331642446be05292e3e1f8a51218827168cdclaireho    }
3595569331642446be05292e3e1f8a51218827168cdclaireho  }
3605569331642446be05292e3e1f8a51218827168cdclaireho
3615569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT )
3625569331642446be05292e3e1f8a51218827168cdclaireho  {
3635569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
3645569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
3655569331642446be05292e3e1f8a51218827168cdclaireho
36657e6107a9d66a9a97b146def0ef38c010f954be6claireho#ifdef HB_SUPPORT_MULTIPLE_MASTER
3675569331642446be05292e3e1f8a51218827168cdclaireho    vr->XIdPlacement = GET_UShort();
36857e6107a9d66a9a97b146def0ef38c010f954be6claireho#else
36957e6107a9d66a9a97b146def0ef38c010f954be6claireho    (void) GET_UShort();
37057e6107a9d66a9a97b146def0ef38c010f954be6claireho#endif
3715569331642446be05292e3e1f8a51218827168cdclaireho
3725569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
3735569331642446be05292e3e1f8a51218827168cdclaireho  }
37457e6107a9d66a9a97b146def0ef38c010f954be6claireho#ifdef HB_SUPPORT_MULTIPLE_MASTER
3755569331642446be05292e3e1f8a51218827168cdclaireho  else
3765569331642446be05292e3e1f8a51218827168cdclaireho    vr->XIdPlacement = 0;
37757e6107a9d66a9a97b146def0ef38c010f954be6claireho#endif
3785569331642446be05292e3e1f8a51218827168cdclaireho
3795569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT )
3805569331642446be05292e3e1f8a51218827168cdclaireho  {
3815569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
3825569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
3835569331642446be05292e3e1f8a51218827168cdclaireho
38457e6107a9d66a9a97b146def0ef38c010f954be6claireho#ifdef HB_SUPPORT_MULTIPLE_MASTER
3855569331642446be05292e3e1f8a51218827168cdclaireho    vr->YIdPlacement = GET_UShort();
38657e6107a9d66a9a97b146def0ef38c010f954be6claireho#else
38757e6107a9d66a9a97b146def0ef38c010f954be6claireho    (void) GET_UShort();
38857e6107a9d66a9a97b146def0ef38c010f954be6claireho#endif
3895569331642446be05292e3e1f8a51218827168cdclaireho
3905569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
3915569331642446be05292e3e1f8a51218827168cdclaireho  }
39257e6107a9d66a9a97b146def0ef38c010f954be6claireho#ifdef HB_SUPPORT_MULTIPLE_MASTER
3935569331642446be05292e3e1f8a51218827168cdclaireho  else
3945569331642446be05292e3e1f8a51218827168cdclaireho    vr->YIdPlacement = 0;
39557e6107a9d66a9a97b146def0ef38c010f954be6claireho#endif
3965569331642446be05292e3e1f8a51218827168cdclaireho
3975569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE )
3985569331642446be05292e3e1f8a51218827168cdclaireho  {
3995569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
4005569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
4015569331642446be05292e3e1f8a51218827168cdclaireho
40257e6107a9d66a9a97b146def0ef38c010f954be6claireho#ifdef HB_SUPPORT_MULTIPLE_MASTER
4035569331642446be05292e3e1f8a51218827168cdclaireho    vr->XIdAdvance = GET_UShort();
40457e6107a9d66a9a97b146def0ef38c010f954be6claireho#else
40557e6107a9d66a9a97b146def0ef38c010f954be6claireho    (void) GET_UShort();
40657e6107a9d66a9a97b146def0ef38c010f954be6claireho#endif
4075569331642446be05292e3e1f8a51218827168cdclaireho
4085569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
4095569331642446be05292e3e1f8a51218827168cdclaireho  }
41057e6107a9d66a9a97b146def0ef38c010f954be6claireho#ifdef HB_SUPPORT_MULTIPLE_MASTER
4115569331642446be05292e3e1f8a51218827168cdclaireho  else
4125569331642446be05292e3e1f8a51218827168cdclaireho    vr->XIdAdvance = 0;
41357e6107a9d66a9a97b146def0ef38c010f954be6claireho#endif
4145569331642446be05292e3e1f8a51218827168cdclaireho
4155569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE )
4165569331642446be05292e3e1f8a51218827168cdclaireho  {
4175569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
4185569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
4195569331642446be05292e3e1f8a51218827168cdclaireho
42057e6107a9d66a9a97b146def0ef38c010f954be6claireho#ifdef HB_SUPPORT_MULTIPLE_MASTER
4215569331642446be05292e3e1f8a51218827168cdclaireho    vr->YIdAdvance = GET_UShort();
42257e6107a9d66a9a97b146def0ef38c010f954be6claireho#else
42357e6107a9d66a9a97b146def0ef38c010f954be6claireho    (void) GET_UShort();
42457e6107a9d66a9a97b146def0ef38c010f954be6claireho#endif
4255569331642446be05292e3e1f8a51218827168cdclaireho
4265569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
4275569331642446be05292e3e1f8a51218827168cdclaireho  }
42857e6107a9d66a9a97b146def0ef38c010f954be6claireho#ifdef HB_SUPPORT_MULTIPLE_MASTER
4295569331642446be05292e3e1f8a51218827168cdclaireho  else
4305569331642446be05292e3e1f8a51218827168cdclaireho    vr->YIdAdvance = 0;
43157e6107a9d66a9a97b146def0ef38c010f954be6claireho#endif
4325569331642446be05292e3e1f8a51218827168cdclaireho
4335569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
4345569331642446be05292e3e1f8a51218827168cdclaireho
4355569331642446be05292e3e1f8a51218827168cdclairehoFail1:
43657e6107a9d66a9a97b146def0ef38c010f954be6claireho  if ( vr->DeviceTables )
43757e6107a9d66a9a97b146def0ef38c010f954be6claireho    _HB_OPEN_Free_Device( vr->DeviceTables[VR_Y_ADVANCE_DEVICE] );
4385569331642446be05292e3e1f8a51218827168cdclaireho
4395569331642446be05292e3e1f8a51218827168cdclairehoFail2:
44057e6107a9d66a9a97b146def0ef38c010f954be6claireho  if ( vr->DeviceTables )
44157e6107a9d66a9a97b146def0ef38c010f954be6claireho    _HB_OPEN_Free_Device( vr->DeviceTables[VR_X_ADVANCE_DEVICE] );
4425569331642446be05292e3e1f8a51218827168cdclaireho
4435569331642446be05292e3e1f8a51218827168cdclairehoFail3:
44457e6107a9d66a9a97b146def0ef38c010f954be6claireho  if ( vr->DeviceTables )
44557e6107a9d66a9a97b146def0ef38c010f954be6claireho    _HB_OPEN_Free_Device( vr->DeviceTables[VR_Y_PLACEMENT_DEVICE] );
44657e6107a9d66a9a97b146def0ef38c010f954be6claireho
44757e6107a9d66a9a97b146def0ef38c010f954be6clairehoFail4:
44857e6107a9d66a9a97b146def0ef38c010f954be6claireho  FREE( vr->DeviceTables );
4495569331642446be05292e3e1f8a51218827168cdclaireho  return error;
4505569331642446be05292e3e1f8a51218827168cdclaireho}
4515569331642446be05292e3e1f8a51218827168cdclaireho
4525569331642446be05292e3e1f8a51218827168cdclaireho
4535569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ValueRecord( HB_ValueRecord*  vr,
4545569331642446be05292e3e1f8a51218827168cdclaireho			       HB_UShort         format )
4555569331642446be05292e3e1f8a51218827168cdclaireho{
4565569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )
45757e6107a9d66a9a97b146def0ef38c010f954be6claireho    _HB_OPEN_Free_Device( vr->DeviceTables[VR_Y_ADVANCE_DEVICE] );
4585569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )
45957e6107a9d66a9a97b146def0ef38c010f954be6claireho    _HB_OPEN_Free_Device( vr->DeviceTables[VR_X_ADVANCE_DEVICE] );
4605569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )
46157e6107a9d66a9a97b146def0ef38c010f954be6claireho    _HB_OPEN_Free_Device( vr->DeviceTables[VR_Y_PLACEMENT_DEVICE] );
4625569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )
46357e6107a9d66a9a97b146def0ef38c010f954be6claireho    _HB_OPEN_Free_Device( vr->DeviceTables[VR_X_PLACEMENT_DEVICE] );
46457e6107a9d66a9a97b146def0ef38c010f954be6claireho  FREE( vr->DeviceTables );
4655569331642446be05292e3e1f8a51218827168cdclaireho}
4665569331642446be05292e3e1f8a51218827168cdclaireho
4675569331642446be05292e3e1f8a51218827168cdclaireho
4685569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Get_ValueRecord( GPOS_Instance*    gpi,
4695569331642446be05292e3e1f8a51218827168cdclaireho				  HB_ValueRecord*  vr,
4705569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort         format,
4715569331642446be05292e3e1f8a51218827168cdclaireho				  HB_Position      gd )
4725569331642446be05292e3e1f8a51218827168cdclaireho{
4735569331642446be05292e3e1f8a51218827168cdclaireho  HB_Short         pixel_value;
4745569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error         error = HB_Err_Ok;
47557e6107a9d66a9a97b146def0ef38c010f954be6claireho#ifdef HB_SUPPORT_MULTIPLE_MASTER
4765569331642446be05292e3e1f8a51218827168cdclaireho  HB_GPOSHeader*  gpos = gpi->gpos;
47757e6107a9d66a9a97b146def0ef38c010f954be6claireho  HB_Fixed           value;
47857e6107a9d66a9a97b146def0ef38c010f954be6claireho#endif
4795569331642446be05292e3e1f8a51218827168cdclaireho
4805569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort  x_ppem, y_ppem;
4815569331642446be05292e3e1f8a51218827168cdclaireho  HB_16Dot16   x_scale, y_scale;
4825569331642446be05292e3e1f8a51218827168cdclaireho
4835569331642446be05292e3e1f8a51218827168cdclaireho
4845569331642446be05292e3e1f8a51218827168cdclaireho  if ( !format )
4855569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Ok;
4865569331642446be05292e3e1f8a51218827168cdclaireho
4875569331642446be05292e3e1f8a51218827168cdclaireho  x_ppem  = gpi->font->x_ppem;
4885569331642446be05292e3e1f8a51218827168cdclaireho  y_ppem  = gpi->font->y_ppem;
4895569331642446be05292e3e1f8a51218827168cdclaireho  x_scale = gpi->font->x_scale;
4905569331642446be05292e3e1f8a51218827168cdclaireho  y_scale = gpi->font->y_scale;
4915569331642446be05292e3e1f8a51218827168cdclaireho
4925569331642446be05292e3e1f8a51218827168cdclaireho  /* design units -> fractional pixel */
4935569331642446be05292e3e1f8a51218827168cdclaireho
4945569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT )
4955569331642446be05292e3e1f8a51218827168cdclaireho    gd->x_pos += x_scale * vr->XPlacement / 0x10000;
4965569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT )
4975569331642446be05292e3e1f8a51218827168cdclaireho    gd->y_pos += y_scale * vr->YPlacement / 0x10000;
4985569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE )
4995569331642446be05292e3e1f8a51218827168cdclaireho    gd->x_advance += x_scale * vr->XAdvance / 0x10000;
5005569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE )
5015569331642446be05292e3e1f8a51218827168cdclaireho    gd->y_advance += y_scale * vr->YAdvance / 0x10000;
5025569331642446be05292e3e1f8a51218827168cdclaireho
5035569331642446be05292e3e1f8a51218827168cdclaireho  if ( !gpi->dvi )
5045569331642446be05292e3e1f8a51218827168cdclaireho  {
5055569331642446be05292e3e1f8a51218827168cdclaireho    /* pixel -> fractional pixel */
5065569331642446be05292e3e1f8a51218827168cdclaireho
5075569331642446be05292e3e1f8a51218827168cdclaireho    if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )
5085569331642446be05292e3e1f8a51218827168cdclaireho    {
50957e6107a9d66a9a97b146def0ef38c010f954be6claireho      _HB_OPEN_Get_Device( vr->DeviceTables[VR_X_PLACEMENT_DEVICE], x_ppem, &pixel_value );
5105569331642446be05292e3e1f8a51218827168cdclaireho      gd->x_pos += pixel_value << 6;
5115569331642446be05292e3e1f8a51218827168cdclaireho    }
5125569331642446be05292e3e1f8a51218827168cdclaireho    if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )
5135569331642446be05292e3e1f8a51218827168cdclaireho    {
51457e6107a9d66a9a97b146def0ef38c010f954be6claireho      _HB_OPEN_Get_Device( vr->DeviceTables[VR_Y_PLACEMENT_DEVICE], y_ppem, &pixel_value );
5155569331642446be05292e3e1f8a51218827168cdclaireho      gd->y_pos += pixel_value << 6;
5165569331642446be05292e3e1f8a51218827168cdclaireho    }
5175569331642446be05292e3e1f8a51218827168cdclaireho    if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )
5185569331642446be05292e3e1f8a51218827168cdclaireho    {
51957e6107a9d66a9a97b146def0ef38c010f954be6claireho      _HB_OPEN_Get_Device( vr->DeviceTables[VR_X_ADVANCE_DEVICE], x_ppem, &pixel_value );
5205569331642446be05292e3e1f8a51218827168cdclaireho      gd->x_advance += pixel_value << 6;
5215569331642446be05292e3e1f8a51218827168cdclaireho    }
5225569331642446be05292e3e1f8a51218827168cdclaireho    if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )
5235569331642446be05292e3e1f8a51218827168cdclaireho    {
52457e6107a9d66a9a97b146def0ef38c010f954be6claireho      _HB_OPEN_Get_Device( vr->DeviceTables[VR_Y_ADVANCE_DEVICE], y_ppem, &pixel_value );
5255569331642446be05292e3e1f8a51218827168cdclaireho      gd->y_advance += pixel_value << 6;
5265569331642446be05292e3e1f8a51218827168cdclaireho    }
5275569331642446be05292e3e1f8a51218827168cdclaireho  }
5285569331642446be05292e3e1f8a51218827168cdclaireho
52957e6107a9d66a9a97b146def0ef38c010f954be6claireho#ifdef HB_SUPPORT_MULTIPLE_MASTER
5305569331642446be05292e3e1f8a51218827168cdclaireho  /* values returned from mmfunc() are already in fractional pixels */
5315569331642446be05292e3e1f8a51218827168cdclaireho
5325569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT )
5335569331642446be05292e3e1f8a51218827168cdclaireho  {
5345569331642446be05292e3e1f8a51218827168cdclaireho    error = (gpos->mmfunc)( gpi->font, vr->XIdPlacement,
5355569331642446be05292e3e1f8a51218827168cdclaireho			    &value, gpos->data );
5365569331642446be05292e3e1f8a51218827168cdclaireho    if ( error )
5375569331642446be05292e3e1f8a51218827168cdclaireho      return error;
5385569331642446be05292e3e1f8a51218827168cdclaireho    gd->x_pos += value;
5395569331642446be05292e3e1f8a51218827168cdclaireho  }
5405569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT )
5415569331642446be05292e3e1f8a51218827168cdclaireho  {
5425569331642446be05292e3e1f8a51218827168cdclaireho    error = (gpos->mmfunc)( gpi->font, vr->YIdPlacement,
5435569331642446be05292e3e1f8a51218827168cdclaireho			    &value, gpos->data );
5445569331642446be05292e3e1f8a51218827168cdclaireho    if ( error )
5455569331642446be05292e3e1f8a51218827168cdclaireho      return error;
5465569331642446be05292e3e1f8a51218827168cdclaireho    gd->y_pos += value;
5475569331642446be05292e3e1f8a51218827168cdclaireho  }
5485569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE )
5495569331642446be05292e3e1f8a51218827168cdclaireho  {
5505569331642446be05292e3e1f8a51218827168cdclaireho    error = (gpos->mmfunc)( gpi->font, vr->XIdAdvance,
5515569331642446be05292e3e1f8a51218827168cdclaireho			    &value, gpos->data );
5525569331642446be05292e3e1f8a51218827168cdclaireho    if ( error )
5535569331642446be05292e3e1f8a51218827168cdclaireho      return error;
5545569331642446be05292e3e1f8a51218827168cdclaireho    gd->x_advance += value;
5555569331642446be05292e3e1f8a51218827168cdclaireho  }
5565569331642446be05292e3e1f8a51218827168cdclaireho  if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE )
5575569331642446be05292e3e1f8a51218827168cdclaireho  {
5585569331642446be05292e3e1f8a51218827168cdclaireho    error = (gpos->mmfunc)( gpi->font, vr->YIdAdvance,
5595569331642446be05292e3e1f8a51218827168cdclaireho			    &value, gpos->data );
5605569331642446be05292e3e1f8a51218827168cdclaireho    if ( error )
5615569331642446be05292e3e1f8a51218827168cdclaireho      return error;
5625569331642446be05292e3e1f8a51218827168cdclaireho    gd->y_advance += value;
5635569331642446be05292e3e1f8a51218827168cdclaireho  }
56457e6107a9d66a9a97b146def0ef38c010f954be6claireho#endif
5655569331642446be05292e3e1f8a51218827168cdclaireho
5665569331642446be05292e3e1f8a51218827168cdclaireho  return error;
5675569331642446be05292e3e1f8a51218827168cdclaireho}
5685569331642446be05292e3e1f8a51218827168cdclaireho
5695569331642446be05292e3e1f8a51218827168cdclaireho
5705569331642446be05292e3e1f8a51218827168cdclaireho/* AnchorFormat1 */
5715569331642446be05292e3e1f8a51218827168cdclaireho/* AnchorFormat2 */
5725569331642446be05292e3e1f8a51218827168cdclaireho/* AnchorFormat3 */
5735569331642446be05292e3e1f8a51218827168cdclaireho/* AnchorFormat4 */
5745569331642446be05292e3e1f8a51218827168cdclaireho
5755569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_Anchor( HB_Anchor*  an,
5765569331642446be05292e3e1f8a51218827168cdclaireho			      HB_Stream    stream )
5775569331642446be05292e3e1f8a51218827168cdclaireho{
5785569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
5795569331642446be05292e3e1f8a51218827168cdclaireho
5805569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt cur_offset, new_offset, base_offset;
5815569331642446be05292e3e1f8a51218827168cdclaireho
5825569331642446be05292e3e1f8a51218827168cdclaireho
5835569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
5845569331642446be05292e3e1f8a51218827168cdclaireho
5855569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
5865569331642446be05292e3e1f8a51218827168cdclaireho    return error;
5875569331642446be05292e3e1f8a51218827168cdclaireho
5885569331642446be05292e3e1f8a51218827168cdclaireho  an->PosFormat = GET_UShort();
5895569331642446be05292e3e1f8a51218827168cdclaireho
5905569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
5915569331642446be05292e3e1f8a51218827168cdclaireho
5925569331642446be05292e3e1f8a51218827168cdclaireho  switch ( an->PosFormat )
5935569331642446be05292e3e1f8a51218827168cdclaireho  {
5945569331642446be05292e3e1f8a51218827168cdclaireho  case 1:
5955569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 4L ) )
5965569331642446be05292e3e1f8a51218827168cdclaireho      return error;
5975569331642446be05292e3e1f8a51218827168cdclaireho
5985569331642446be05292e3e1f8a51218827168cdclaireho    an->af.af1.XCoordinate = GET_Short();
5995569331642446be05292e3e1f8a51218827168cdclaireho    an->af.af1.YCoordinate = GET_Short();
6005569331642446be05292e3e1f8a51218827168cdclaireho
6015569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
6025569331642446be05292e3e1f8a51218827168cdclaireho    break;
6035569331642446be05292e3e1f8a51218827168cdclaireho
6045569331642446be05292e3e1f8a51218827168cdclaireho  case 2:
6055569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 6L ) )
6065569331642446be05292e3e1f8a51218827168cdclaireho      return error;
6075569331642446be05292e3e1f8a51218827168cdclaireho
6085569331642446be05292e3e1f8a51218827168cdclaireho    an->af.af2.XCoordinate = GET_Short();
6095569331642446be05292e3e1f8a51218827168cdclaireho    an->af.af2.YCoordinate = GET_Short();
6105569331642446be05292e3e1f8a51218827168cdclaireho    an->af.af2.AnchorPoint = GET_UShort();
6115569331642446be05292e3e1f8a51218827168cdclaireho
6125569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
6135569331642446be05292e3e1f8a51218827168cdclaireho    break;
6145569331642446be05292e3e1f8a51218827168cdclaireho
6155569331642446be05292e3e1f8a51218827168cdclaireho  case 3:
6165569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 6L ) )
6175569331642446be05292e3e1f8a51218827168cdclaireho      return error;
6185569331642446be05292e3e1f8a51218827168cdclaireho
6195569331642446be05292e3e1f8a51218827168cdclaireho    an->af.af3.XCoordinate = GET_Short();
6205569331642446be05292e3e1f8a51218827168cdclaireho    an->af.af3.YCoordinate = GET_Short();
6215569331642446be05292e3e1f8a51218827168cdclaireho
6225569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort();
6235569331642446be05292e3e1f8a51218827168cdclaireho
6245569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
6255569331642446be05292e3e1f8a51218827168cdclaireho
6265569331642446be05292e3e1f8a51218827168cdclaireho    if ( new_offset )
6275569331642446be05292e3e1f8a51218827168cdclaireho    {
62857e6107a9d66a9a97b146def0ef38c010f954be6claireho      if ( ALLOC_ARRAY( an->af.af3.DeviceTables, 2, HB_Device ) )
62957e6107a9d66a9a97b146def0ef38c010f954be6claireho        return error;
63057e6107a9d66a9a97b146def0ef38c010f954be6claireho
63157e6107a9d66a9a97b146def0ef38c010f954be6claireho      an->af.af3.DeviceTables[AF3_X_DEVICE_TABLE] = 0;
63257e6107a9d66a9a97b146def0ef38c010f954be6claireho      an->af.af3.DeviceTables[AF3_Y_DEVICE_TABLE] = 0;
63357e6107a9d66a9a97b146def0ef38c010f954be6claireho
6345569331642446be05292e3e1f8a51218827168cdclaireho      new_offset += base_offset;
6355569331642446be05292e3e1f8a51218827168cdclaireho
6365569331642446be05292e3e1f8a51218827168cdclaireho      cur_offset = FILE_Pos();
6375569331642446be05292e3e1f8a51218827168cdclaireho      if ( FILE_Seek( new_offset ) ||
63857e6107a9d66a9a97b146def0ef38c010f954be6claireho	   ( error = _HB_OPEN_Load_Device( &an->af.af3.DeviceTables[AF3_X_DEVICE_TABLE],
6395569331642446be05292e3e1f8a51218827168cdclaireho				  stream ) ) != HB_Err_Ok )
64057e6107a9d66a9a97b146def0ef38c010f954be6claireho	goto Fail2;
6415569331642446be05292e3e1f8a51218827168cdclaireho      (void)FILE_Seek( cur_offset );
6425569331642446be05292e3e1f8a51218827168cdclaireho    }
6435569331642446be05292e3e1f8a51218827168cdclaireho
6445569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
6455569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
6465569331642446be05292e3e1f8a51218827168cdclaireho
6475569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort();
6485569331642446be05292e3e1f8a51218827168cdclaireho
6495569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
6505569331642446be05292e3e1f8a51218827168cdclaireho
6515569331642446be05292e3e1f8a51218827168cdclaireho    if ( new_offset )
6525569331642446be05292e3e1f8a51218827168cdclaireho    {
65357e6107a9d66a9a97b146def0ef38c010f954be6claireho      if ( !an->af.af3.DeviceTables )
65457e6107a9d66a9a97b146def0ef38c010f954be6claireho      {
65557e6107a9d66a9a97b146def0ef38c010f954be6claireho        if ( ALLOC_ARRAY( an->af.af3.DeviceTables, 2, HB_Device ) )
65657e6107a9d66a9a97b146def0ef38c010f954be6claireho          return error;
65757e6107a9d66a9a97b146def0ef38c010f954be6claireho
65857e6107a9d66a9a97b146def0ef38c010f954be6claireho        an->af.af3.DeviceTables[AF3_X_DEVICE_TABLE] = 0;
65957e6107a9d66a9a97b146def0ef38c010f954be6claireho        an->af.af3.DeviceTables[AF3_Y_DEVICE_TABLE] = 0;
66057e6107a9d66a9a97b146def0ef38c010f954be6claireho      }
66157e6107a9d66a9a97b146def0ef38c010f954be6claireho
6625569331642446be05292e3e1f8a51218827168cdclaireho      new_offset += base_offset;
6635569331642446be05292e3e1f8a51218827168cdclaireho
6645569331642446be05292e3e1f8a51218827168cdclaireho      cur_offset = FILE_Pos();
6655569331642446be05292e3e1f8a51218827168cdclaireho      if ( FILE_Seek( new_offset ) ||
66657e6107a9d66a9a97b146def0ef38c010f954be6claireho	   ( error = _HB_OPEN_Load_Device( &an->af.af3.DeviceTables[AF3_Y_DEVICE_TABLE],
6675569331642446be05292e3e1f8a51218827168cdclaireho				  stream ) ) != HB_Err_Ok )
6685569331642446be05292e3e1f8a51218827168cdclaireho	goto Fail;
6695569331642446be05292e3e1f8a51218827168cdclaireho      (void)FILE_Seek( cur_offset );
6705569331642446be05292e3e1f8a51218827168cdclaireho    }
6715569331642446be05292e3e1f8a51218827168cdclaireho    break;
6725569331642446be05292e3e1f8a51218827168cdclaireho
6735569331642446be05292e3e1f8a51218827168cdclaireho  case 4:
6745569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 4L ) )
6755569331642446be05292e3e1f8a51218827168cdclaireho      return error;
6765569331642446be05292e3e1f8a51218827168cdclaireho
67757e6107a9d66a9a97b146def0ef38c010f954be6claireho#ifdef HB_SUPPORT_MULTIPLE_MASTER
6785569331642446be05292e3e1f8a51218827168cdclaireho    an->af.af4.XIdAnchor = GET_UShort();
6795569331642446be05292e3e1f8a51218827168cdclaireho    an->af.af4.YIdAnchor = GET_UShort();
68057e6107a9d66a9a97b146def0ef38c010f954be6claireho#else
68157e6107a9d66a9a97b146def0ef38c010f954be6claireho    (void) GET_UShort();
68257e6107a9d66a9a97b146def0ef38c010f954be6claireho    (void) GET_UShort();
68357e6107a9d66a9a97b146def0ef38c010f954be6claireho#endif
6845569331642446be05292e3e1f8a51218827168cdclaireho
6855569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
6865569331642446be05292e3e1f8a51218827168cdclaireho    break;
6875569331642446be05292e3e1f8a51218827168cdclaireho
6885569331642446be05292e3e1f8a51218827168cdclaireho  default:
6895569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable_Format);
6905569331642446be05292e3e1f8a51218827168cdclaireho  }
6915569331642446be05292e3e1f8a51218827168cdclaireho
6925569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
6935569331642446be05292e3e1f8a51218827168cdclaireho
6945569331642446be05292e3e1f8a51218827168cdclairehoFail:
69557e6107a9d66a9a97b146def0ef38c010f954be6claireho  if ( an->af.af3.DeviceTables )
69657e6107a9d66a9a97b146def0ef38c010f954be6claireho    _HB_OPEN_Free_Device( an->af.af3.DeviceTables[AF3_X_DEVICE_TABLE] );
69757e6107a9d66a9a97b146def0ef38c010f954be6claireho
69857e6107a9d66a9a97b146def0ef38c010f954be6clairehoFail2:
69957e6107a9d66a9a97b146def0ef38c010f954be6claireho  FREE( an->af.af3.DeviceTables );
7005569331642446be05292e3e1f8a51218827168cdclaireho  return error;
7015569331642446be05292e3e1f8a51218827168cdclaireho}
7025569331642446be05292e3e1f8a51218827168cdclaireho
7035569331642446be05292e3e1f8a51218827168cdclaireho
7045569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_Anchor( HB_Anchor*  an)
7055569331642446be05292e3e1f8a51218827168cdclaireho{
70657e6107a9d66a9a97b146def0ef38c010f954be6claireho  if ( an->PosFormat == 3 && an->af.af3.DeviceTables )
7075569331642446be05292e3e1f8a51218827168cdclaireho  {
70857e6107a9d66a9a97b146def0ef38c010f954be6claireho    _HB_OPEN_Free_Device( an->af.af3.DeviceTables[AF3_X_DEVICE_TABLE] );
70957e6107a9d66a9a97b146def0ef38c010f954be6claireho    _HB_OPEN_Free_Device( an->af.af3.DeviceTables[AF3_Y_DEVICE_TABLE] );
71057e6107a9d66a9a97b146def0ef38c010f954be6claireho    FREE( an->af.af3.DeviceTables );
7115569331642446be05292e3e1f8a51218827168cdclaireho  }
7125569331642446be05292e3e1f8a51218827168cdclaireho}
7135569331642446be05292e3e1f8a51218827168cdclaireho
7145569331642446be05292e3e1f8a51218827168cdclaireho
7155569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Get_Anchor( GPOS_Instance*   gpi,
7165569331642446be05292e3e1f8a51218827168cdclaireho			     HB_Anchor*      an,
7175569331642446be05292e3e1f8a51218827168cdclaireho			     HB_UShort        glyph_index,
7185569331642446be05292e3e1f8a51218827168cdclaireho			     HB_Fixed*          x_value,
7195569331642446be05292e3e1f8a51218827168cdclaireho			     HB_Fixed*          y_value )
7205569331642446be05292e3e1f8a51218827168cdclaireho{
7215569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error = HB_Err_Ok;
7225569331642446be05292e3e1f8a51218827168cdclaireho
72357e6107a9d66a9a97b146def0ef38c010f954be6claireho#ifdef HB_SUPPORT_MULTIPLE_MASTER
7245569331642446be05292e3e1f8a51218827168cdclaireho  HB_GPOSHeader*  gpos = gpi->gpos;
72557e6107a9d66a9a97b146def0ef38c010f954be6claireho#endif
7265569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        ap;
7275569331642446be05292e3e1f8a51218827168cdclaireho
7285569331642446be05292e3e1f8a51218827168cdclaireho  HB_Short         pixel_value;
7295569331642446be05292e3e1f8a51218827168cdclaireho
7305569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        x_ppem, y_ppem;
7315569331642446be05292e3e1f8a51218827168cdclaireho  HB_16Dot16         x_scale, y_scale;
7325569331642446be05292e3e1f8a51218827168cdclaireho
7335569331642446be05292e3e1f8a51218827168cdclaireho
7345569331642446be05292e3e1f8a51218827168cdclaireho  x_ppem  = gpi->font->x_ppem;
7355569331642446be05292e3e1f8a51218827168cdclaireho  y_ppem  = gpi->font->y_ppem;
7365569331642446be05292e3e1f8a51218827168cdclaireho  x_scale = gpi->font->x_scale;
7375569331642446be05292e3e1f8a51218827168cdclaireho  y_scale = gpi->font->y_scale;
7385569331642446be05292e3e1f8a51218827168cdclaireho
7395569331642446be05292e3e1f8a51218827168cdclaireho  switch ( an->PosFormat )
7405569331642446be05292e3e1f8a51218827168cdclaireho  {
7415569331642446be05292e3e1f8a51218827168cdclaireho  case 0:
7425569331642446be05292e3e1f8a51218827168cdclaireho    /* The special case of an empty AnchorTable */
7435569331642446be05292e3e1f8a51218827168cdclaireho  default:
7445569331642446be05292e3e1f8a51218827168cdclaireho
7455569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
7465569331642446be05292e3e1f8a51218827168cdclaireho
7475569331642446be05292e3e1f8a51218827168cdclaireho  case 1:
7485569331642446be05292e3e1f8a51218827168cdclaireho    *x_value = x_scale * an->af.af1.XCoordinate / 0x10000;
7495569331642446be05292e3e1f8a51218827168cdclaireho    *y_value = y_scale * an->af.af1.YCoordinate / 0x10000;
7505569331642446be05292e3e1f8a51218827168cdclaireho    break;
7515569331642446be05292e3e1f8a51218827168cdclaireho
7525569331642446be05292e3e1f8a51218827168cdclaireho  case 2:
7535569331642446be05292e3e1f8a51218827168cdclaireho    if ( !gpi->dvi )
7545569331642446be05292e3e1f8a51218827168cdclaireho    {
7555569331642446be05292e3e1f8a51218827168cdclaireho      hb_uint32 n_points = 0;
7565569331642446be05292e3e1f8a51218827168cdclaireho      ap = an->af.af2.AnchorPoint;
7575569331642446be05292e3e1f8a51218827168cdclaireho      if (!gpi->font->klass->getPointInOutline)
7585569331642446be05292e3e1f8a51218827168cdclaireho          goto no_contour_point;
7595569331642446be05292e3e1f8a51218827168cdclaireho      error = gpi->font->klass->getPointInOutline(gpi->font, glyph_index, gpi->load_flags, ap, x_value, y_value, &n_points);
7605569331642446be05292e3e1f8a51218827168cdclaireho      if (error)
7615569331642446be05292e3e1f8a51218827168cdclaireho          return error;
7625569331642446be05292e3e1f8a51218827168cdclaireho      /* if n_points is set to zero, we use the design coordinate value pair.
7635569331642446be05292e3e1f8a51218827168cdclaireho       * This can happen e.g. for sbit glyphs. */
7645569331642446be05292e3e1f8a51218827168cdclaireho      if (!n_points)
7655569331642446be05292e3e1f8a51218827168cdclaireho          goto no_contour_point;
7665569331642446be05292e3e1f8a51218827168cdclaireho    }
7675569331642446be05292e3e1f8a51218827168cdclaireho    else
7685569331642446be05292e3e1f8a51218827168cdclaireho    {
7695569331642446be05292e3e1f8a51218827168cdclaireho    no_contour_point:
7705569331642446be05292e3e1f8a51218827168cdclaireho      *x_value = x_scale * an->af.af3.XCoordinate / 0x10000;
7715569331642446be05292e3e1f8a51218827168cdclaireho      *y_value = y_scale * an->af.af3.YCoordinate / 0x10000;
7725569331642446be05292e3e1f8a51218827168cdclaireho    }
7735569331642446be05292e3e1f8a51218827168cdclaireho    break;
7745569331642446be05292e3e1f8a51218827168cdclaireho
7755569331642446be05292e3e1f8a51218827168cdclaireho  case 3:
7765569331642446be05292e3e1f8a51218827168cdclaireho    if ( !gpi->dvi )
7775569331642446be05292e3e1f8a51218827168cdclaireho    {
77857e6107a9d66a9a97b146def0ef38c010f954be6claireho      _HB_OPEN_Get_Device( an->af.af3.DeviceTables[AF3_X_DEVICE_TABLE], x_ppem, &pixel_value );
7795569331642446be05292e3e1f8a51218827168cdclaireho      *x_value = pixel_value << 6;
78057e6107a9d66a9a97b146def0ef38c010f954be6claireho      _HB_OPEN_Get_Device( an->af.af3.DeviceTables[AF3_Y_DEVICE_TABLE], y_ppem, &pixel_value );
7815569331642446be05292e3e1f8a51218827168cdclaireho      *y_value = pixel_value << 6;
7825569331642446be05292e3e1f8a51218827168cdclaireho    }
7835569331642446be05292e3e1f8a51218827168cdclaireho    else
7845569331642446be05292e3e1f8a51218827168cdclaireho      *x_value = *y_value = 0;
7855569331642446be05292e3e1f8a51218827168cdclaireho
7865569331642446be05292e3e1f8a51218827168cdclaireho    *x_value += x_scale * an->af.af3.XCoordinate / 0x10000;
7875569331642446be05292e3e1f8a51218827168cdclaireho    *y_value += y_scale * an->af.af3.YCoordinate / 0x10000;
7885569331642446be05292e3e1f8a51218827168cdclaireho    break;
7895569331642446be05292e3e1f8a51218827168cdclaireho
7905569331642446be05292e3e1f8a51218827168cdclaireho  case 4:
79157e6107a9d66a9a97b146def0ef38c010f954be6claireho#ifdef HB_SUPPORT_MULTIPLE_MASTER
7925569331642446be05292e3e1f8a51218827168cdclaireho    error = (gpos->mmfunc)( gpi->font, an->af.af4.XIdAnchor,
7935569331642446be05292e3e1f8a51218827168cdclaireho			    x_value, gpos->data );
7945569331642446be05292e3e1f8a51218827168cdclaireho    if ( error )
7955569331642446be05292e3e1f8a51218827168cdclaireho      return error;
7965569331642446be05292e3e1f8a51218827168cdclaireho
7975569331642446be05292e3e1f8a51218827168cdclaireho    error = (gpos->mmfunc)( gpi->font, an->af.af4.YIdAnchor,
7985569331642446be05292e3e1f8a51218827168cdclaireho			    y_value, gpos->data );
7995569331642446be05292e3e1f8a51218827168cdclaireho    if ( error )
8005569331642446be05292e3e1f8a51218827168cdclaireho      return error;
8015569331642446be05292e3e1f8a51218827168cdclaireho    break;
80257e6107a9d66a9a97b146def0ef38c010f954be6claireho#else
80357e6107a9d66a9a97b146def0ef38c010f954be6claireho    return ERR(HB_Err_Not_Covered);
80457e6107a9d66a9a97b146def0ef38c010f954be6claireho#endif
8055569331642446be05292e3e1f8a51218827168cdclaireho  }
8065569331642446be05292e3e1f8a51218827168cdclaireho
8075569331642446be05292e3e1f8a51218827168cdclaireho  return error;
8085569331642446be05292e3e1f8a51218827168cdclaireho}
8095569331642446be05292e3e1f8a51218827168cdclaireho
8105569331642446be05292e3e1f8a51218827168cdclaireho
8115569331642446be05292e3e1f8a51218827168cdclaireho/* MarkArray */
8125569331642446be05292e3e1f8a51218827168cdclaireho
8135569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_MarkArray ( HB_MarkArray*  ma,
8145569331642446be05292e3e1f8a51218827168cdclaireho				  HB_Stream       stream )
8155569331642446be05292e3e1f8a51218827168cdclaireho{
8165569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
8175569331642446be05292e3e1f8a51218827168cdclaireho
8185569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        n, m, count;
8195569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt         cur_offset, new_offset, base_offset;
8205569331642446be05292e3e1f8a51218827168cdclaireho
8215569331642446be05292e3e1f8a51218827168cdclaireho  HB_MarkRecord*  mr;
8225569331642446be05292e3e1f8a51218827168cdclaireho
8235569331642446be05292e3e1f8a51218827168cdclaireho
8245569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
8255569331642446be05292e3e1f8a51218827168cdclaireho
8265569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
8275569331642446be05292e3e1f8a51218827168cdclaireho    return error;
8285569331642446be05292e3e1f8a51218827168cdclaireho
8295569331642446be05292e3e1f8a51218827168cdclaireho  count = ma->MarkCount = GET_UShort();
8305569331642446be05292e3e1f8a51218827168cdclaireho
8315569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
8325569331642446be05292e3e1f8a51218827168cdclaireho
8335569331642446be05292e3e1f8a51218827168cdclaireho  ma->MarkRecord = NULL;
8345569331642446be05292e3e1f8a51218827168cdclaireho
8355569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ma->MarkRecord, count, HB_MarkRecord ) )
8365569331642446be05292e3e1f8a51218827168cdclaireho    return error;
8375569331642446be05292e3e1f8a51218827168cdclaireho
8385569331642446be05292e3e1f8a51218827168cdclaireho  mr = ma->MarkRecord;
8395569331642446be05292e3e1f8a51218827168cdclaireho
8405569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
8415569331642446be05292e3e1f8a51218827168cdclaireho  {
8425569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 4L ) )
8435569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
8445569331642446be05292e3e1f8a51218827168cdclaireho
8455569331642446be05292e3e1f8a51218827168cdclaireho    mr[n].Class = GET_UShort();
8465569331642446be05292e3e1f8a51218827168cdclaireho    new_offset  = GET_UShort() + base_offset;
8475569331642446be05292e3e1f8a51218827168cdclaireho
8485569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
8495569331642446be05292e3e1f8a51218827168cdclaireho
8505569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
8515569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
8525569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_Anchor( &mr[n].MarkAnchor, stream ) ) != HB_Err_Ok )
8535569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
8545569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
8555569331642446be05292e3e1f8a51218827168cdclaireho  }
8565569331642446be05292e3e1f8a51218827168cdclaireho
8575569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
8585569331642446be05292e3e1f8a51218827168cdclaireho
8595569331642446be05292e3e1f8a51218827168cdclairehoFail:
8605569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
8615569331642446be05292e3e1f8a51218827168cdclaireho    Free_Anchor( &mr[m].MarkAnchor );
8625569331642446be05292e3e1f8a51218827168cdclaireho
8635569331642446be05292e3e1f8a51218827168cdclaireho  FREE( mr );
8645569331642446be05292e3e1f8a51218827168cdclaireho  return error;
8655569331642446be05292e3e1f8a51218827168cdclaireho}
8665569331642446be05292e3e1f8a51218827168cdclaireho
8675569331642446be05292e3e1f8a51218827168cdclaireho
8685569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_MarkArray( HB_MarkArray*  ma )
8695569331642446be05292e3e1f8a51218827168cdclaireho{
8705569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        n, count;
8715569331642446be05292e3e1f8a51218827168cdclaireho
8725569331642446be05292e3e1f8a51218827168cdclaireho  HB_MarkRecord*  mr;
8735569331642446be05292e3e1f8a51218827168cdclaireho
8745569331642446be05292e3e1f8a51218827168cdclaireho
8755569331642446be05292e3e1f8a51218827168cdclaireho  if ( ma->MarkRecord )
8765569331642446be05292e3e1f8a51218827168cdclaireho  {
8775569331642446be05292e3e1f8a51218827168cdclaireho    count = ma->MarkCount;
8785569331642446be05292e3e1f8a51218827168cdclaireho    mr    = ma->MarkRecord;
8795569331642446be05292e3e1f8a51218827168cdclaireho
8805569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
8815569331642446be05292e3e1f8a51218827168cdclaireho      Free_Anchor( &mr[n].MarkAnchor );
8825569331642446be05292e3e1f8a51218827168cdclaireho
8835569331642446be05292e3e1f8a51218827168cdclaireho    FREE( mr );
8845569331642446be05292e3e1f8a51218827168cdclaireho  }
8855569331642446be05292e3e1f8a51218827168cdclaireho}
8865569331642446be05292e3e1f8a51218827168cdclaireho
8875569331642446be05292e3e1f8a51218827168cdclaireho
8885569331642446be05292e3e1f8a51218827168cdclaireho/* LookupType 1 */
8895569331642446be05292e3e1f8a51218827168cdclaireho
8905569331642446be05292e3e1f8a51218827168cdclaireho/* SinglePosFormat1 */
8915569331642446be05292e3e1f8a51218827168cdclaireho/* SinglePosFormat2 */
8925569331642446be05292e3e1f8a51218827168cdclaireho
8935569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_SinglePos( HB_GPOS_SubTable* st,
8945569331642446be05292e3e1f8a51218827168cdclaireho				 HB_Stream       stream )
8955569331642446be05292e3e1f8a51218827168cdclaireho{
8965569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
8975569331642446be05292e3e1f8a51218827168cdclaireho  HB_SinglePos*   sp = &st->single;
8985569331642446be05292e3e1f8a51218827168cdclaireho
8995569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort         n, m, count, format;
9005569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt          cur_offset, new_offset, base_offset;
9015569331642446be05292e3e1f8a51218827168cdclaireho
9025569331642446be05292e3e1f8a51218827168cdclaireho  HB_ValueRecord*  vr;
9035569331642446be05292e3e1f8a51218827168cdclaireho
9045569331642446be05292e3e1f8a51218827168cdclaireho
9055569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
9065569331642446be05292e3e1f8a51218827168cdclaireho
9075569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 6L ) )
9085569331642446be05292e3e1f8a51218827168cdclaireho    return error;
9095569331642446be05292e3e1f8a51218827168cdclaireho
9105569331642446be05292e3e1f8a51218827168cdclaireho  sp->PosFormat = GET_UShort();
9115569331642446be05292e3e1f8a51218827168cdclaireho  new_offset    = GET_UShort() + base_offset;
9125569331642446be05292e3e1f8a51218827168cdclaireho
9135569331642446be05292e3e1f8a51218827168cdclaireho  format = sp->ValueFormat = GET_UShort();
9145569331642446be05292e3e1f8a51218827168cdclaireho
9155569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
9165569331642446be05292e3e1f8a51218827168cdclaireho
9175569331642446be05292e3e1f8a51218827168cdclaireho  if ( !format )
9185569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable);
9195569331642446be05292e3e1f8a51218827168cdclaireho
9205569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
9215569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
9225569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_Coverage( &sp->Coverage, stream ) ) != HB_Err_Ok )
9235569331642446be05292e3e1f8a51218827168cdclaireho    return error;
9245569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
9255569331642446be05292e3e1f8a51218827168cdclaireho
9265569331642446be05292e3e1f8a51218827168cdclaireho  switch ( sp->PosFormat )
9275569331642446be05292e3e1f8a51218827168cdclaireho  {
9285569331642446be05292e3e1f8a51218827168cdclaireho  case 1:
9295569331642446be05292e3e1f8a51218827168cdclaireho    error = Load_ValueRecord( &sp->spf.spf1.Value, format,
9305569331642446be05292e3e1f8a51218827168cdclaireho			      base_offset, stream );
9315569331642446be05292e3e1f8a51218827168cdclaireho    if ( error )
9325569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail2;
9335569331642446be05292e3e1f8a51218827168cdclaireho    break;
9345569331642446be05292e3e1f8a51218827168cdclaireho
9355569331642446be05292e3e1f8a51218827168cdclaireho  case 2:
9365569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
9375569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail2;
9385569331642446be05292e3e1f8a51218827168cdclaireho
9395569331642446be05292e3e1f8a51218827168cdclaireho    count = sp->spf.spf2.ValueCount = GET_UShort();
9405569331642446be05292e3e1f8a51218827168cdclaireho
9415569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
9425569331642446be05292e3e1f8a51218827168cdclaireho
9435569331642446be05292e3e1f8a51218827168cdclaireho    sp->spf.spf2.Value = NULL;
9445569331642446be05292e3e1f8a51218827168cdclaireho
9455569331642446be05292e3e1f8a51218827168cdclaireho    if ( ALLOC_ARRAY( sp->spf.spf2.Value, count, HB_ValueRecord ) )
9465569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail2;
9475569331642446be05292e3e1f8a51218827168cdclaireho
9485569331642446be05292e3e1f8a51218827168cdclaireho    vr = sp->spf.spf2.Value;
9495569331642446be05292e3e1f8a51218827168cdclaireho
9505569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
9515569331642446be05292e3e1f8a51218827168cdclaireho    {
9525569331642446be05292e3e1f8a51218827168cdclaireho      error = Load_ValueRecord( &vr[n], format, base_offset, stream );
9535569331642446be05292e3e1f8a51218827168cdclaireho      if ( error )
9545569331642446be05292e3e1f8a51218827168cdclaireho	goto Fail1;
9555569331642446be05292e3e1f8a51218827168cdclaireho    }
9565569331642446be05292e3e1f8a51218827168cdclaireho    break;
9575569331642446be05292e3e1f8a51218827168cdclaireho
9585569331642446be05292e3e1f8a51218827168cdclaireho  default:
9595569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable_Format);
9605569331642446be05292e3e1f8a51218827168cdclaireho  }
9615569331642446be05292e3e1f8a51218827168cdclaireho
9625569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
9635569331642446be05292e3e1f8a51218827168cdclaireho
9645569331642446be05292e3e1f8a51218827168cdclairehoFail1:
9655569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
9665569331642446be05292e3e1f8a51218827168cdclaireho    Free_ValueRecord( &vr[m], format );
9675569331642446be05292e3e1f8a51218827168cdclaireho
9685569331642446be05292e3e1f8a51218827168cdclaireho  FREE( vr );
9695569331642446be05292e3e1f8a51218827168cdclaireho
9705569331642446be05292e3e1f8a51218827168cdclairehoFail2:
9715569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &sp->Coverage );
9725569331642446be05292e3e1f8a51218827168cdclaireho  return error;
9735569331642446be05292e3e1f8a51218827168cdclaireho}
9745569331642446be05292e3e1f8a51218827168cdclaireho
9755569331642446be05292e3e1f8a51218827168cdclaireho
9765569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_SinglePos( HB_GPOS_SubTable* st )
9775569331642446be05292e3e1f8a51218827168cdclaireho{
9785569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort         n, count, format;
9795569331642446be05292e3e1f8a51218827168cdclaireho  HB_SinglePos*   sp = &st->single;
9805569331642446be05292e3e1f8a51218827168cdclaireho
9815569331642446be05292e3e1f8a51218827168cdclaireho  HB_ValueRecord*  v;
9825569331642446be05292e3e1f8a51218827168cdclaireho
9835569331642446be05292e3e1f8a51218827168cdclaireho
9845569331642446be05292e3e1f8a51218827168cdclaireho  format = sp->ValueFormat;
9855569331642446be05292e3e1f8a51218827168cdclaireho
9865569331642446be05292e3e1f8a51218827168cdclaireho  switch ( sp->PosFormat )
9875569331642446be05292e3e1f8a51218827168cdclaireho  {
9885569331642446be05292e3e1f8a51218827168cdclaireho  case 1:
9895569331642446be05292e3e1f8a51218827168cdclaireho    Free_ValueRecord( &sp->spf.spf1.Value, format );
9905569331642446be05292e3e1f8a51218827168cdclaireho    break;
9915569331642446be05292e3e1f8a51218827168cdclaireho
9925569331642446be05292e3e1f8a51218827168cdclaireho  case 2:
9935569331642446be05292e3e1f8a51218827168cdclaireho    if ( sp->spf.spf2.Value )
9945569331642446be05292e3e1f8a51218827168cdclaireho    {
9955569331642446be05292e3e1f8a51218827168cdclaireho      count = sp->spf.spf2.ValueCount;
9965569331642446be05292e3e1f8a51218827168cdclaireho      v     = sp->spf.spf2.Value;
9975569331642446be05292e3e1f8a51218827168cdclaireho
9985569331642446be05292e3e1f8a51218827168cdclaireho      for ( n = 0; n < count; n++ )
9995569331642446be05292e3e1f8a51218827168cdclaireho	Free_ValueRecord( &v[n], format );
10005569331642446be05292e3e1f8a51218827168cdclaireho
10015569331642446be05292e3e1f8a51218827168cdclaireho      FREE( v );
10025569331642446be05292e3e1f8a51218827168cdclaireho    }
10035569331642446be05292e3e1f8a51218827168cdclaireho    break;
10045569331642446be05292e3e1f8a51218827168cdclaireho  default:
10055569331642446be05292e3e1f8a51218827168cdclaireho    break;
10065569331642446be05292e3e1f8a51218827168cdclaireho  }
10075569331642446be05292e3e1f8a51218827168cdclaireho
10085569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &sp->Coverage );
10095569331642446be05292e3e1f8a51218827168cdclaireho}
10105569331642446be05292e3e1f8a51218827168cdclaireho
10115569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_SinglePos( GPOS_Instance*    gpi,
10125569331642446be05292e3e1f8a51218827168cdclaireho				   HB_GPOS_SubTable* st,
10135569331642446be05292e3e1f8a51218827168cdclaireho				   HB_Buffer        buffer,
10145569331642446be05292e3e1f8a51218827168cdclaireho				   HB_UShort         flags,
10155569331642446be05292e3e1f8a51218827168cdclaireho				   HB_UShort         context_length,
10165569331642446be05292e3e1f8a51218827168cdclaireho				   int               nesting_level )
10175569331642446be05292e3e1f8a51218827168cdclaireho{
10185569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        index, property;
10195569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error         error;
10205569331642446be05292e3e1f8a51218827168cdclaireho  HB_GPOSHeader*  gpos = gpi->gpos;
10215569331642446be05292e3e1f8a51218827168cdclaireho  HB_SinglePos*   sp = &st->single;
10225569331642446be05292e3e1f8a51218827168cdclaireho
10235569331642446be05292e3e1f8a51218827168cdclaireho  HB_UNUSED(nesting_level);
10245569331642446be05292e3e1f8a51218827168cdclaireho
10255569331642446be05292e3e1f8a51218827168cdclaireho  if ( context_length != 0xFFFF && context_length < 1 )
10265569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
10275569331642446be05292e3e1f8a51218827168cdclaireho
10285569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
10295569331642446be05292e3e1f8a51218827168cdclaireho    return error;
10305569331642446be05292e3e1f8a51218827168cdclaireho
10315569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Coverage_Index( &sp->Coverage, IN_CURGLYPH(), &index );
10325569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
10335569331642446be05292e3e1f8a51218827168cdclaireho    return error;
10345569331642446be05292e3e1f8a51218827168cdclaireho
10355569331642446be05292e3e1f8a51218827168cdclaireho  switch ( sp->PosFormat )
10365569331642446be05292e3e1f8a51218827168cdclaireho  {
10375569331642446be05292e3e1f8a51218827168cdclaireho  case 1:
10385569331642446be05292e3e1f8a51218827168cdclaireho    error = Get_ValueRecord( gpi, &sp->spf.spf1.Value,
10395569331642446be05292e3e1f8a51218827168cdclaireho			     sp->ValueFormat, POSITION( buffer->in_pos ) );
10405569331642446be05292e3e1f8a51218827168cdclaireho    if ( error )
10415569331642446be05292e3e1f8a51218827168cdclaireho      return error;
10425569331642446be05292e3e1f8a51218827168cdclaireho    break;
10435569331642446be05292e3e1f8a51218827168cdclaireho
10445569331642446be05292e3e1f8a51218827168cdclaireho  case 2:
10455569331642446be05292e3e1f8a51218827168cdclaireho    if ( index >= sp->spf.spf2.ValueCount )
10465569331642446be05292e3e1f8a51218827168cdclaireho      return ERR(HB_Err_Invalid_SubTable);
10475569331642446be05292e3e1f8a51218827168cdclaireho    error = Get_ValueRecord( gpi, &sp->spf.spf2.Value[index],
10485569331642446be05292e3e1f8a51218827168cdclaireho			     sp->ValueFormat, POSITION( buffer->in_pos ) );
10495569331642446be05292e3e1f8a51218827168cdclaireho    if ( error )
10505569331642446be05292e3e1f8a51218827168cdclaireho      return error;
10515569331642446be05292e3e1f8a51218827168cdclaireho    break;
10525569331642446be05292e3e1f8a51218827168cdclaireho
10535569331642446be05292e3e1f8a51218827168cdclaireho  default:
10545569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable);
10555569331642446be05292e3e1f8a51218827168cdclaireho  }
10565569331642446be05292e3e1f8a51218827168cdclaireho
10575569331642446be05292e3e1f8a51218827168cdclaireho  (buffer->in_pos)++;
10585569331642446be05292e3e1f8a51218827168cdclaireho
10595569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
10605569331642446be05292e3e1f8a51218827168cdclaireho}
10615569331642446be05292e3e1f8a51218827168cdclaireho
10625569331642446be05292e3e1f8a51218827168cdclaireho
10635569331642446be05292e3e1f8a51218827168cdclaireho/* LookupType 2 */
10645569331642446be05292e3e1f8a51218827168cdclaireho
10655569331642446be05292e3e1f8a51218827168cdclaireho/* PairSet */
10665569331642446be05292e3e1f8a51218827168cdclaireho
10675569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_PairSet ( HB_PairSet*  ps,
10685569331642446be05292e3e1f8a51218827168cdclaireho				HB_UShort     format1,
10695569331642446be05292e3e1f8a51218827168cdclaireho				HB_UShort     format2,
10705569331642446be05292e3e1f8a51218827168cdclaireho				HB_Stream     stream )
10715569331642446be05292e3e1f8a51218827168cdclaireho{
10725569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
10735569331642446be05292e3e1f8a51218827168cdclaireho
10745569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort             n, m, count;
10755569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt              base_offset;
10765569331642446be05292e3e1f8a51218827168cdclaireho
10775569331642446be05292e3e1f8a51218827168cdclaireho  HB_PairValueRecord*  pvr;
10785569331642446be05292e3e1f8a51218827168cdclaireho
10795569331642446be05292e3e1f8a51218827168cdclaireho
10805569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
10815569331642446be05292e3e1f8a51218827168cdclaireho
10825569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
10835569331642446be05292e3e1f8a51218827168cdclaireho    return error;
10845569331642446be05292e3e1f8a51218827168cdclaireho
10855569331642446be05292e3e1f8a51218827168cdclaireho  count = ps->PairValueCount = GET_UShort();
10865569331642446be05292e3e1f8a51218827168cdclaireho
10875569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
10885569331642446be05292e3e1f8a51218827168cdclaireho
10895569331642446be05292e3e1f8a51218827168cdclaireho  ps->PairValueRecord = NULL;
10905569331642446be05292e3e1f8a51218827168cdclaireho
10915569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ps->PairValueRecord, count, HB_PairValueRecord ) )
10925569331642446be05292e3e1f8a51218827168cdclaireho    return error;
10935569331642446be05292e3e1f8a51218827168cdclaireho
10945569331642446be05292e3e1f8a51218827168cdclaireho  pvr = ps->PairValueRecord;
10955569331642446be05292e3e1f8a51218827168cdclaireho
10965569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
10975569331642446be05292e3e1f8a51218827168cdclaireho  {
10985569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
10995569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
11005569331642446be05292e3e1f8a51218827168cdclaireho
11015569331642446be05292e3e1f8a51218827168cdclaireho    pvr[n].SecondGlyph = GET_UShort();
11025569331642446be05292e3e1f8a51218827168cdclaireho
11035569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
11045569331642446be05292e3e1f8a51218827168cdclaireho
11055569331642446be05292e3e1f8a51218827168cdclaireho    if ( format1 )
11065569331642446be05292e3e1f8a51218827168cdclaireho    {
11075569331642446be05292e3e1f8a51218827168cdclaireho      error = Load_ValueRecord( &pvr[n].Value1, format1,
11085569331642446be05292e3e1f8a51218827168cdclaireho				base_offset, stream );
11095569331642446be05292e3e1f8a51218827168cdclaireho      if ( error )
11105569331642446be05292e3e1f8a51218827168cdclaireho	goto Fail;
11115569331642446be05292e3e1f8a51218827168cdclaireho    }
11125569331642446be05292e3e1f8a51218827168cdclaireho    if ( format2 )
11135569331642446be05292e3e1f8a51218827168cdclaireho    {
11145569331642446be05292e3e1f8a51218827168cdclaireho      error = Load_ValueRecord( &pvr[n].Value2, format2,
11155569331642446be05292e3e1f8a51218827168cdclaireho				base_offset, stream );
11165569331642446be05292e3e1f8a51218827168cdclaireho      if ( error )
11175569331642446be05292e3e1f8a51218827168cdclaireho      {
11185569331642446be05292e3e1f8a51218827168cdclaireho	if ( format1 )
11195569331642446be05292e3e1f8a51218827168cdclaireho	  Free_ValueRecord( &pvr[n].Value1, format1 );
11205569331642446be05292e3e1f8a51218827168cdclaireho	goto Fail;
11215569331642446be05292e3e1f8a51218827168cdclaireho      }
11225569331642446be05292e3e1f8a51218827168cdclaireho    }
11235569331642446be05292e3e1f8a51218827168cdclaireho  }
11245569331642446be05292e3e1f8a51218827168cdclaireho
11255569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
11265569331642446be05292e3e1f8a51218827168cdclaireho
11275569331642446be05292e3e1f8a51218827168cdclairehoFail:
11285569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
11295569331642446be05292e3e1f8a51218827168cdclaireho  {
11305569331642446be05292e3e1f8a51218827168cdclaireho    if ( format1 )
11315569331642446be05292e3e1f8a51218827168cdclaireho      Free_ValueRecord( &pvr[m].Value1, format1 );
11325569331642446be05292e3e1f8a51218827168cdclaireho    if ( format2 )
11335569331642446be05292e3e1f8a51218827168cdclaireho      Free_ValueRecord( &pvr[m].Value2, format2 );
11345569331642446be05292e3e1f8a51218827168cdclaireho  }
11355569331642446be05292e3e1f8a51218827168cdclaireho
11365569331642446be05292e3e1f8a51218827168cdclaireho  FREE( pvr );
11375569331642446be05292e3e1f8a51218827168cdclaireho  return error;
11385569331642446be05292e3e1f8a51218827168cdclaireho}
11395569331642446be05292e3e1f8a51218827168cdclaireho
11405569331642446be05292e3e1f8a51218827168cdclaireho
11415569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_PairSet( HB_PairSet*  ps,
11425569331642446be05292e3e1f8a51218827168cdclaireho			   HB_UShort     format1,
11435569331642446be05292e3e1f8a51218827168cdclaireho			   HB_UShort     format2 )
11445569331642446be05292e3e1f8a51218827168cdclaireho{
11455569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort             n, count;
11465569331642446be05292e3e1f8a51218827168cdclaireho
11475569331642446be05292e3e1f8a51218827168cdclaireho  HB_PairValueRecord*  pvr;
11485569331642446be05292e3e1f8a51218827168cdclaireho
11495569331642446be05292e3e1f8a51218827168cdclaireho
11505569331642446be05292e3e1f8a51218827168cdclaireho  if ( ps->PairValueRecord )
11515569331642446be05292e3e1f8a51218827168cdclaireho  {
11525569331642446be05292e3e1f8a51218827168cdclaireho    count = ps->PairValueCount;
11535569331642446be05292e3e1f8a51218827168cdclaireho    pvr   = ps->PairValueRecord;
11545569331642446be05292e3e1f8a51218827168cdclaireho
11555569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
11565569331642446be05292e3e1f8a51218827168cdclaireho    {
11575569331642446be05292e3e1f8a51218827168cdclaireho      if ( format1 )
11585569331642446be05292e3e1f8a51218827168cdclaireho	Free_ValueRecord( &pvr[n].Value1, format1 );
11595569331642446be05292e3e1f8a51218827168cdclaireho      if ( format2 )
11605569331642446be05292e3e1f8a51218827168cdclaireho	Free_ValueRecord( &pvr[n].Value2, format2 );
11615569331642446be05292e3e1f8a51218827168cdclaireho    }
11625569331642446be05292e3e1f8a51218827168cdclaireho
11635569331642446be05292e3e1f8a51218827168cdclaireho    FREE( pvr );
11645569331642446be05292e3e1f8a51218827168cdclaireho  }
11655569331642446be05292e3e1f8a51218827168cdclaireho}
11665569331642446be05292e3e1f8a51218827168cdclaireho
11675569331642446be05292e3e1f8a51218827168cdclaireho
11685569331642446be05292e3e1f8a51218827168cdclaireho/* PairPosFormat1 */
11695569331642446be05292e3e1f8a51218827168cdclaireho
11705569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_PairPos1( HB_PairPosFormat1*  ppf1,
11715569331642446be05292e3e1f8a51218827168cdclaireho				HB_UShort            format1,
11725569331642446be05292e3e1f8a51218827168cdclaireho				HB_UShort            format2,
11735569331642446be05292e3e1f8a51218827168cdclaireho				HB_Stream            stream )
11745569331642446be05292e3e1f8a51218827168cdclaireho{
11755569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
11765569331642446be05292e3e1f8a51218827168cdclaireho
11775569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort     n, m, count;
11785569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt      cur_offset, new_offset, base_offset;
11795569331642446be05292e3e1f8a51218827168cdclaireho
11805569331642446be05292e3e1f8a51218827168cdclaireho  HB_PairSet*  ps;
11815569331642446be05292e3e1f8a51218827168cdclaireho
11825569331642446be05292e3e1f8a51218827168cdclaireho
11835569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos() - 8L;
11845569331642446be05292e3e1f8a51218827168cdclaireho
11855569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
11865569331642446be05292e3e1f8a51218827168cdclaireho    return error;
11875569331642446be05292e3e1f8a51218827168cdclaireho
11885569331642446be05292e3e1f8a51218827168cdclaireho  count = ppf1->PairSetCount = GET_UShort();
11895569331642446be05292e3e1f8a51218827168cdclaireho
11905569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
11915569331642446be05292e3e1f8a51218827168cdclaireho
11925569331642446be05292e3e1f8a51218827168cdclaireho  ppf1->PairSet = NULL;
11935569331642446be05292e3e1f8a51218827168cdclaireho
11945569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ppf1->PairSet, count, HB_PairSet ) )
11955569331642446be05292e3e1f8a51218827168cdclaireho    return error;
11965569331642446be05292e3e1f8a51218827168cdclaireho
11975569331642446be05292e3e1f8a51218827168cdclaireho  ps = ppf1->PairSet;
11985569331642446be05292e3e1f8a51218827168cdclaireho
11995569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
12005569331642446be05292e3e1f8a51218827168cdclaireho  {
12015569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
12025569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
12035569331642446be05292e3e1f8a51218827168cdclaireho
12045569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
12055569331642446be05292e3e1f8a51218827168cdclaireho
12065569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
12075569331642446be05292e3e1f8a51218827168cdclaireho
12085569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
12095569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
12105569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_PairSet( &ps[n], format1,
12115569331642446be05292e3e1f8a51218827168cdclaireho				 format2, stream ) ) != HB_Err_Ok )
12125569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
12135569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
12145569331642446be05292e3e1f8a51218827168cdclaireho  }
12155569331642446be05292e3e1f8a51218827168cdclaireho
12165569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
12175569331642446be05292e3e1f8a51218827168cdclaireho
12185569331642446be05292e3e1f8a51218827168cdclairehoFail:
12195569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
12205569331642446be05292e3e1f8a51218827168cdclaireho    Free_PairSet( &ps[m], format1, format2 );
12215569331642446be05292e3e1f8a51218827168cdclaireho
12225569331642446be05292e3e1f8a51218827168cdclaireho  FREE( ps );
12235569331642446be05292e3e1f8a51218827168cdclaireho  return error;
12245569331642446be05292e3e1f8a51218827168cdclaireho}
12255569331642446be05292e3e1f8a51218827168cdclaireho
12265569331642446be05292e3e1f8a51218827168cdclaireho
12275569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_PairPos1( HB_PairPosFormat1*  ppf1,
12285569331642446be05292e3e1f8a51218827168cdclaireho			    HB_UShort            format1,
12295569331642446be05292e3e1f8a51218827168cdclaireho			    HB_UShort            format2 )
12305569331642446be05292e3e1f8a51218827168cdclaireho{
12315569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort     n, count;
12325569331642446be05292e3e1f8a51218827168cdclaireho
12335569331642446be05292e3e1f8a51218827168cdclaireho  HB_PairSet*  ps;
12345569331642446be05292e3e1f8a51218827168cdclaireho
12355569331642446be05292e3e1f8a51218827168cdclaireho
12365569331642446be05292e3e1f8a51218827168cdclaireho  if ( ppf1->PairSet )
12375569331642446be05292e3e1f8a51218827168cdclaireho  {
12385569331642446be05292e3e1f8a51218827168cdclaireho    count = ppf1->PairSetCount;
12395569331642446be05292e3e1f8a51218827168cdclaireho    ps    = ppf1->PairSet;
12405569331642446be05292e3e1f8a51218827168cdclaireho
12415569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
12425569331642446be05292e3e1f8a51218827168cdclaireho      Free_PairSet( &ps[n], format1, format2 );
12435569331642446be05292e3e1f8a51218827168cdclaireho
12445569331642446be05292e3e1f8a51218827168cdclaireho    FREE( ps );
12455569331642446be05292e3e1f8a51218827168cdclaireho  }
12465569331642446be05292e3e1f8a51218827168cdclaireho}
12475569331642446be05292e3e1f8a51218827168cdclaireho
12485569331642446be05292e3e1f8a51218827168cdclaireho
12495569331642446be05292e3e1f8a51218827168cdclaireho/* PairPosFormat2 */
12505569331642446be05292e3e1f8a51218827168cdclaireho
12515569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_PairPos2( HB_PairPosFormat2*  ppf2,
12525569331642446be05292e3e1f8a51218827168cdclaireho				HB_UShort            format1,
12535569331642446be05292e3e1f8a51218827168cdclaireho				HB_UShort            format2,
12545569331642446be05292e3e1f8a51218827168cdclaireho				HB_Stream            stream )
12555569331642446be05292e3e1f8a51218827168cdclaireho{
12565569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
12575569331642446be05292e3e1f8a51218827168cdclaireho
12585569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          m, n, k, count1, count2;
12595569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt           cur_offset, new_offset1, new_offset2, base_offset;
12605569331642446be05292e3e1f8a51218827168cdclaireho
12615569331642446be05292e3e1f8a51218827168cdclaireho  HB_Class1Record*  c1r;
12625569331642446be05292e3e1f8a51218827168cdclaireho  HB_Class2Record*  c2r;
12635569331642446be05292e3e1f8a51218827168cdclaireho
12645569331642446be05292e3e1f8a51218827168cdclaireho
12655569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos() - 8L;
12665569331642446be05292e3e1f8a51218827168cdclaireho
12675569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 8L ) )
12685569331642446be05292e3e1f8a51218827168cdclaireho    return error;
12695569331642446be05292e3e1f8a51218827168cdclaireho
12705569331642446be05292e3e1f8a51218827168cdclaireho  new_offset1 = GET_UShort() + base_offset;
12715569331642446be05292e3e1f8a51218827168cdclaireho  new_offset2 = GET_UShort() + base_offset;
12725569331642446be05292e3e1f8a51218827168cdclaireho
12735569331642446be05292e3e1f8a51218827168cdclaireho  /* `Class1Count' and `Class2Count' are the upper limits for class
12745569331642446be05292e3e1f8a51218827168cdclaireho     values, thus we read it now to make additional safety checks.  */
12755569331642446be05292e3e1f8a51218827168cdclaireho
12765569331642446be05292e3e1f8a51218827168cdclaireho  count1 = ppf2->Class1Count = GET_UShort();
12775569331642446be05292e3e1f8a51218827168cdclaireho  count2 = ppf2->Class2Count = GET_UShort();
12785569331642446be05292e3e1f8a51218827168cdclaireho
12795569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
12805569331642446be05292e3e1f8a51218827168cdclaireho
12815569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
12825569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset1 ) ||
12835569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_ClassDefinition( &ppf2->ClassDef1, count1,
12845569331642446be05292e3e1f8a51218827168cdclaireho				       stream ) ) != HB_Err_Ok )
12855569331642446be05292e3e1f8a51218827168cdclaireho    return error;
12865569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset2 ) ||
12875569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_ClassDefinition( &ppf2->ClassDef2, count2,
12885569331642446be05292e3e1f8a51218827168cdclaireho				       stream ) ) != HB_Err_Ok )
12895569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
12905569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
12915569331642446be05292e3e1f8a51218827168cdclaireho
12925569331642446be05292e3e1f8a51218827168cdclaireho  ppf2->Class1Record = NULL;
12935569331642446be05292e3e1f8a51218827168cdclaireho
12945569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ppf2->Class1Record, count1, HB_Class1Record ) )
12955569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
12965569331642446be05292e3e1f8a51218827168cdclaireho
12975569331642446be05292e3e1f8a51218827168cdclaireho  c1r = ppf2->Class1Record;
12985569331642446be05292e3e1f8a51218827168cdclaireho
12995569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < count1; m++ )
13005569331642446be05292e3e1f8a51218827168cdclaireho  {
13015569331642446be05292e3e1f8a51218827168cdclaireho    c1r[m].Class2Record = NULL;
13025569331642446be05292e3e1f8a51218827168cdclaireho
13035569331642446be05292e3e1f8a51218827168cdclaireho    if ( ALLOC_ARRAY( c1r[m].Class2Record, count2, HB_Class2Record ) )
13045569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
13055569331642446be05292e3e1f8a51218827168cdclaireho
13065569331642446be05292e3e1f8a51218827168cdclaireho    c2r = c1r[m].Class2Record;
13075569331642446be05292e3e1f8a51218827168cdclaireho
13085569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count2; n++ )
13095569331642446be05292e3e1f8a51218827168cdclaireho    {
13105569331642446be05292e3e1f8a51218827168cdclaireho      if ( format1 )
13115569331642446be05292e3e1f8a51218827168cdclaireho      {
13125569331642446be05292e3e1f8a51218827168cdclaireho	error = Load_ValueRecord( &c2r[n].Value1, format1,
13135569331642446be05292e3e1f8a51218827168cdclaireho				  base_offset, stream );
13145569331642446be05292e3e1f8a51218827168cdclaireho	if ( error )
13155569331642446be05292e3e1f8a51218827168cdclaireho	  goto Fail0;
13165569331642446be05292e3e1f8a51218827168cdclaireho      }
13175569331642446be05292e3e1f8a51218827168cdclaireho      if ( format2 )
13185569331642446be05292e3e1f8a51218827168cdclaireho      {
13195569331642446be05292e3e1f8a51218827168cdclaireho	error = Load_ValueRecord( &c2r[n].Value2, format2,
13205569331642446be05292e3e1f8a51218827168cdclaireho				  base_offset, stream );
13215569331642446be05292e3e1f8a51218827168cdclaireho	if ( error )
13225569331642446be05292e3e1f8a51218827168cdclaireho	{
13235569331642446be05292e3e1f8a51218827168cdclaireho	  if ( format1 )
13245569331642446be05292e3e1f8a51218827168cdclaireho	    Free_ValueRecord( &c2r[n].Value1, format1 );
13255569331642446be05292e3e1f8a51218827168cdclaireho	  goto Fail0;
13265569331642446be05292e3e1f8a51218827168cdclaireho	}
13275569331642446be05292e3e1f8a51218827168cdclaireho      }
13285569331642446be05292e3e1f8a51218827168cdclaireho    }
13295569331642446be05292e3e1f8a51218827168cdclaireho
13305569331642446be05292e3e1f8a51218827168cdclaireho    continue;
13315569331642446be05292e3e1f8a51218827168cdclaireho
13325569331642446be05292e3e1f8a51218827168cdclaireho  Fail0:
13335569331642446be05292e3e1f8a51218827168cdclaireho    for ( k = 0; k < n; k++ )
13345569331642446be05292e3e1f8a51218827168cdclaireho    {
13355569331642446be05292e3e1f8a51218827168cdclaireho      if ( format1 )
13365569331642446be05292e3e1f8a51218827168cdclaireho	Free_ValueRecord( &c2r[k].Value1, format1 );
13375569331642446be05292e3e1f8a51218827168cdclaireho      if ( format2 )
13385569331642446be05292e3e1f8a51218827168cdclaireho	Free_ValueRecord( &c2r[k].Value2, format2 );
13395569331642446be05292e3e1f8a51218827168cdclaireho    }
13405569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail1;
13415569331642446be05292e3e1f8a51218827168cdclaireho  }
13425569331642446be05292e3e1f8a51218827168cdclaireho
13435569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
13445569331642446be05292e3e1f8a51218827168cdclaireho
13455569331642446be05292e3e1f8a51218827168cdclairehoFail1:
13465569331642446be05292e3e1f8a51218827168cdclaireho  for ( k = 0; k < m; k++ )
13475569331642446be05292e3e1f8a51218827168cdclaireho  {
13485569331642446be05292e3e1f8a51218827168cdclaireho    c2r = c1r[k].Class2Record;
13495569331642446be05292e3e1f8a51218827168cdclaireho
13505569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count2; n++ )
13515569331642446be05292e3e1f8a51218827168cdclaireho    {
13525569331642446be05292e3e1f8a51218827168cdclaireho      if ( format1 )
13535569331642446be05292e3e1f8a51218827168cdclaireho	Free_ValueRecord( &c2r[n].Value1, format1 );
13545569331642446be05292e3e1f8a51218827168cdclaireho      if ( format2 )
13555569331642446be05292e3e1f8a51218827168cdclaireho	Free_ValueRecord( &c2r[n].Value2, format2 );
13565569331642446be05292e3e1f8a51218827168cdclaireho    }
13575569331642446be05292e3e1f8a51218827168cdclaireho
13585569331642446be05292e3e1f8a51218827168cdclaireho    FREE( c2r );
13595569331642446be05292e3e1f8a51218827168cdclaireho  }
13605569331642446be05292e3e1f8a51218827168cdclaireho
13615569331642446be05292e3e1f8a51218827168cdclaireho  FREE( c1r );
13625569331642446be05292e3e1f8a51218827168cdclairehoFail2:
13635569331642446be05292e3e1f8a51218827168cdclaireho
13645569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef2 );
13655569331642446be05292e3e1f8a51218827168cdclaireho
13665569331642446be05292e3e1f8a51218827168cdclairehoFail3:
13675569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef1 );
13685569331642446be05292e3e1f8a51218827168cdclaireho  return error;
13695569331642446be05292e3e1f8a51218827168cdclaireho}
13705569331642446be05292e3e1f8a51218827168cdclaireho
13715569331642446be05292e3e1f8a51218827168cdclaireho
13725569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_PairPos2( HB_PairPosFormat2*  ppf2,
13735569331642446be05292e3e1f8a51218827168cdclaireho			    HB_UShort            format1,
13745569331642446be05292e3e1f8a51218827168cdclaireho			    HB_UShort            format2)
13755569331642446be05292e3e1f8a51218827168cdclaireho{
13765569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          m, n, count1, count2;
13775569331642446be05292e3e1f8a51218827168cdclaireho
13785569331642446be05292e3e1f8a51218827168cdclaireho  HB_Class1Record*  c1r;
13795569331642446be05292e3e1f8a51218827168cdclaireho  HB_Class2Record*  c2r;
13805569331642446be05292e3e1f8a51218827168cdclaireho
13815569331642446be05292e3e1f8a51218827168cdclaireho
13825569331642446be05292e3e1f8a51218827168cdclaireho  if ( ppf2->Class1Record )
13835569331642446be05292e3e1f8a51218827168cdclaireho  {
13845569331642446be05292e3e1f8a51218827168cdclaireho    c1r    = ppf2->Class1Record;
13855569331642446be05292e3e1f8a51218827168cdclaireho    count1 = ppf2->Class1Count;
13865569331642446be05292e3e1f8a51218827168cdclaireho    count2 = ppf2->Class2Count;
13875569331642446be05292e3e1f8a51218827168cdclaireho
13885569331642446be05292e3e1f8a51218827168cdclaireho    for ( m = 0; m < count1; m++ )
13895569331642446be05292e3e1f8a51218827168cdclaireho    {
13905569331642446be05292e3e1f8a51218827168cdclaireho      c2r = c1r[m].Class2Record;
13915569331642446be05292e3e1f8a51218827168cdclaireho
13925569331642446be05292e3e1f8a51218827168cdclaireho      for ( n = 0; n < count2; n++ )
13935569331642446be05292e3e1f8a51218827168cdclaireho      {
13945569331642446be05292e3e1f8a51218827168cdclaireho	if ( format1 )
13955569331642446be05292e3e1f8a51218827168cdclaireho	  Free_ValueRecord( &c2r[n].Value1, format1 );
13965569331642446be05292e3e1f8a51218827168cdclaireho	if ( format2 )
13975569331642446be05292e3e1f8a51218827168cdclaireho	  Free_ValueRecord( &c2r[n].Value2, format2 );
13985569331642446be05292e3e1f8a51218827168cdclaireho      }
13995569331642446be05292e3e1f8a51218827168cdclaireho
14005569331642446be05292e3e1f8a51218827168cdclaireho      FREE( c2r );
14015569331642446be05292e3e1f8a51218827168cdclaireho    }
14025569331642446be05292e3e1f8a51218827168cdclaireho
14035569331642446be05292e3e1f8a51218827168cdclaireho    FREE( c1r );
14045569331642446be05292e3e1f8a51218827168cdclaireho
14055569331642446be05292e3e1f8a51218827168cdclaireho    _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef2 );
14065569331642446be05292e3e1f8a51218827168cdclaireho    _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef1 );
14075569331642446be05292e3e1f8a51218827168cdclaireho  }
14085569331642446be05292e3e1f8a51218827168cdclaireho}
14095569331642446be05292e3e1f8a51218827168cdclaireho
14105569331642446be05292e3e1f8a51218827168cdclaireho
14115569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_PairPos( HB_GPOS_SubTable* st,
14125569331642446be05292e3e1f8a51218827168cdclaireho			       HB_Stream     stream )
14135569331642446be05292e3e1f8a51218827168cdclaireho{
14145569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
14155569331642446be05292e3e1f8a51218827168cdclaireho  HB_PairPos*     pp = &st->pair;
14165569331642446be05292e3e1f8a51218827168cdclaireho
14175569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort         format1, format2;
14185569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt          cur_offset, new_offset, base_offset;
14195569331642446be05292e3e1f8a51218827168cdclaireho
14205569331642446be05292e3e1f8a51218827168cdclaireho
14215569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
14225569331642446be05292e3e1f8a51218827168cdclaireho
14235569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 8L ) )
14245569331642446be05292e3e1f8a51218827168cdclaireho    return error;
14255569331642446be05292e3e1f8a51218827168cdclaireho
14265569331642446be05292e3e1f8a51218827168cdclaireho  pp->PosFormat = GET_UShort();
14275569331642446be05292e3e1f8a51218827168cdclaireho  new_offset    = GET_UShort() + base_offset;
14285569331642446be05292e3e1f8a51218827168cdclaireho
14295569331642446be05292e3e1f8a51218827168cdclaireho  format1 = pp->ValueFormat1 = GET_UShort();
14305569331642446be05292e3e1f8a51218827168cdclaireho  format2 = pp->ValueFormat2 = GET_UShort();
14315569331642446be05292e3e1f8a51218827168cdclaireho
14325569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
14335569331642446be05292e3e1f8a51218827168cdclaireho
14345569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
14355569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
14365569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_Coverage( &pp->Coverage, stream ) ) != HB_Err_Ok )
14375569331642446be05292e3e1f8a51218827168cdclaireho    return error;
14385569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
14395569331642446be05292e3e1f8a51218827168cdclaireho
14405569331642446be05292e3e1f8a51218827168cdclaireho  switch ( pp->PosFormat )
14415569331642446be05292e3e1f8a51218827168cdclaireho  {
14425569331642446be05292e3e1f8a51218827168cdclaireho  case 1:
14435569331642446be05292e3e1f8a51218827168cdclaireho    error = Load_PairPos1( &pp->ppf.ppf1, format1, format2, stream );
14445569331642446be05292e3e1f8a51218827168cdclaireho    if ( error )
14455569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
14465569331642446be05292e3e1f8a51218827168cdclaireho    break;
14475569331642446be05292e3e1f8a51218827168cdclaireho
14485569331642446be05292e3e1f8a51218827168cdclaireho  case 2:
14495569331642446be05292e3e1f8a51218827168cdclaireho    error = Load_PairPos2( &pp->ppf.ppf2, format1, format2, stream );
14505569331642446be05292e3e1f8a51218827168cdclaireho    if ( error )
14515569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
14525569331642446be05292e3e1f8a51218827168cdclaireho    break;
14535569331642446be05292e3e1f8a51218827168cdclaireho
14545569331642446be05292e3e1f8a51218827168cdclaireho  default:
14555569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable_Format);
14565569331642446be05292e3e1f8a51218827168cdclaireho  }
14575569331642446be05292e3e1f8a51218827168cdclaireho
14585569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
14595569331642446be05292e3e1f8a51218827168cdclaireho
14605569331642446be05292e3e1f8a51218827168cdclairehoFail:
14615569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &pp->Coverage );
14625569331642446be05292e3e1f8a51218827168cdclaireho  return error;
14635569331642446be05292e3e1f8a51218827168cdclaireho}
14645569331642446be05292e3e1f8a51218827168cdclaireho
14655569331642446be05292e3e1f8a51218827168cdclaireho
14665569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_PairPos( HB_GPOS_SubTable* st )
14675569331642446be05292e3e1f8a51218827168cdclaireho{
14685569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort  format1, format2;
14695569331642446be05292e3e1f8a51218827168cdclaireho  HB_PairPos*     pp = &st->pair;
14705569331642446be05292e3e1f8a51218827168cdclaireho
14715569331642446be05292e3e1f8a51218827168cdclaireho
14725569331642446be05292e3e1f8a51218827168cdclaireho  format1 = pp->ValueFormat1;
14735569331642446be05292e3e1f8a51218827168cdclaireho  format2 = pp->ValueFormat2;
14745569331642446be05292e3e1f8a51218827168cdclaireho
14755569331642446be05292e3e1f8a51218827168cdclaireho  switch ( pp->PosFormat )
14765569331642446be05292e3e1f8a51218827168cdclaireho  {
14775569331642446be05292e3e1f8a51218827168cdclaireho  case 1:
14785569331642446be05292e3e1f8a51218827168cdclaireho    Free_PairPos1( &pp->ppf.ppf1, format1, format2 );
14795569331642446be05292e3e1f8a51218827168cdclaireho    break;
14805569331642446be05292e3e1f8a51218827168cdclaireho
14815569331642446be05292e3e1f8a51218827168cdclaireho  case 2:
14825569331642446be05292e3e1f8a51218827168cdclaireho    Free_PairPos2( &pp->ppf.ppf2, format1, format2 );
14835569331642446be05292e3e1f8a51218827168cdclaireho    break;
14845569331642446be05292e3e1f8a51218827168cdclaireho
14855569331642446be05292e3e1f8a51218827168cdclaireho  default:
14865569331642446be05292e3e1f8a51218827168cdclaireho    break;
14875569331642446be05292e3e1f8a51218827168cdclaireho  }
14885569331642446be05292e3e1f8a51218827168cdclaireho
14895569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &pp->Coverage );
14905569331642446be05292e3e1f8a51218827168cdclaireho}
14915569331642446be05292e3e1f8a51218827168cdclaireho
14925569331642446be05292e3e1f8a51218827168cdclaireho
14935569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_PairPos1( GPOS_Instance*       gpi,
14945569331642446be05292e3e1f8a51218827168cdclaireho				  HB_PairPosFormat1*  ppf1,
14955569331642446be05292e3e1f8a51218827168cdclaireho				  HB_Buffer           buffer,
14965569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UInt              first_pos,
14975569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort            index,
14985569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort            format1,
14995569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort            format2 )
15005569331642446be05292e3e1f8a51218827168cdclaireho{
15015569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error              error;
15025569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort             numpvr, glyph2;
15035569331642446be05292e3e1f8a51218827168cdclaireho
15045569331642446be05292e3e1f8a51218827168cdclaireho  HB_PairValueRecord*  pvr;
15055569331642446be05292e3e1f8a51218827168cdclaireho
15065569331642446be05292e3e1f8a51218827168cdclaireho
15075569331642446be05292e3e1f8a51218827168cdclaireho  if ( index >= ppf1->PairSetCount )
15085569331642446be05292e3e1f8a51218827168cdclaireho     return ERR(HB_Err_Invalid_SubTable);
15095569331642446be05292e3e1f8a51218827168cdclaireho
15105569331642446be05292e3e1f8a51218827168cdclaireho  pvr = ppf1->PairSet[index].PairValueRecord;
15115569331642446be05292e3e1f8a51218827168cdclaireho  if ( !pvr )
15125569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable);
15135569331642446be05292e3e1f8a51218827168cdclaireho
15145569331642446be05292e3e1f8a51218827168cdclaireho  glyph2 = IN_CURGLYPH();
15155569331642446be05292e3e1f8a51218827168cdclaireho
15165569331642446be05292e3e1f8a51218827168cdclaireho  for ( numpvr = ppf1->PairSet[index].PairValueCount;
15175569331642446be05292e3e1f8a51218827168cdclaireho	numpvr;
15185569331642446be05292e3e1f8a51218827168cdclaireho	numpvr--, pvr++ )
15195569331642446be05292e3e1f8a51218827168cdclaireho  {
15205569331642446be05292e3e1f8a51218827168cdclaireho    if ( glyph2 == pvr->SecondGlyph )
15215569331642446be05292e3e1f8a51218827168cdclaireho    {
15225569331642446be05292e3e1f8a51218827168cdclaireho      error = Get_ValueRecord( gpi, &pvr->Value1, format1,
15235569331642446be05292e3e1f8a51218827168cdclaireho			       POSITION( first_pos ) );
15245569331642446be05292e3e1f8a51218827168cdclaireho      if ( error )
15255569331642446be05292e3e1f8a51218827168cdclaireho	return error;
15265569331642446be05292e3e1f8a51218827168cdclaireho      return Get_ValueRecord( gpi, &pvr->Value2, format2,
15275569331642446be05292e3e1f8a51218827168cdclaireho			      POSITION( buffer->in_pos ) );
15285569331642446be05292e3e1f8a51218827168cdclaireho    }
15295569331642446be05292e3e1f8a51218827168cdclaireho  }
15305569331642446be05292e3e1f8a51218827168cdclaireho
15315569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Not_Covered;
15325569331642446be05292e3e1f8a51218827168cdclaireho}
15335569331642446be05292e3e1f8a51218827168cdclaireho
15345569331642446be05292e3e1f8a51218827168cdclaireho
15355569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_PairPos2( GPOS_Instance*       gpi,
15365569331642446be05292e3e1f8a51218827168cdclaireho				  HB_PairPosFormat2*  ppf2,
15375569331642446be05292e3e1f8a51218827168cdclaireho				  HB_Buffer           buffer,
15385569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UInt              first_pos,
15395569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort            format1,
15405569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort            format2 )
15415569331642446be05292e3e1f8a51218827168cdclaireho{
15425569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error           error;
15435569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          cl1 = 0, cl2 = 0; /* shut compiler up */
15445569331642446be05292e3e1f8a51218827168cdclaireho
15455569331642446be05292e3e1f8a51218827168cdclaireho  HB_Class1Record*  c1r;
15465569331642446be05292e3e1f8a51218827168cdclaireho  HB_Class2Record*  c2r;
15475569331642446be05292e3e1f8a51218827168cdclaireho
15485569331642446be05292e3e1f8a51218827168cdclaireho
15495569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Get_Class( &ppf2->ClassDef1, IN_GLYPH( first_pos ),
15505569331642446be05292e3e1f8a51218827168cdclaireho		     &cl1, NULL );
15515569331642446be05292e3e1f8a51218827168cdclaireho  if ( error && error != HB_Err_Not_Covered )
15525569331642446be05292e3e1f8a51218827168cdclaireho    return error;
15535569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Get_Class( &ppf2->ClassDef2, IN_CURGLYPH(),
15545569331642446be05292e3e1f8a51218827168cdclaireho		     &cl2, NULL );
15555569331642446be05292e3e1f8a51218827168cdclaireho  if ( error && error != HB_Err_Not_Covered )
15565569331642446be05292e3e1f8a51218827168cdclaireho    return error;
15575569331642446be05292e3e1f8a51218827168cdclaireho
15585569331642446be05292e3e1f8a51218827168cdclaireho  c1r = &ppf2->Class1Record[cl1];
15595569331642446be05292e3e1f8a51218827168cdclaireho  if ( !c1r )
15605569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable);
15615569331642446be05292e3e1f8a51218827168cdclaireho  c2r = &c1r->Class2Record[cl2];
15625569331642446be05292e3e1f8a51218827168cdclaireho
15635569331642446be05292e3e1f8a51218827168cdclaireho  error = Get_ValueRecord( gpi, &c2r->Value1, format1, POSITION( first_pos ) );
15645569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
15655569331642446be05292e3e1f8a51218827168cdclaireho    return error;
15665569331642446be05292e3e1f8a51218827168cdclaireho  return Get_ValueRecord( gpi, &c2r->Value2, format2, POSITION( buffer->in_pos ) );
15675569331642446be05292e3e1f8a51218827168cdclaireho}
15685569331642446be05292e3e1f8a51218827168cdclaireho
15695569331642446be05292e3e1f8a51218827168cdclaireho
15705569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_PairPos( GPOS_Instance*    gpi,
15715569331642446be05292e3e1f8a51218827168cdclaireho				 HB_GPOS_SubTable* st,
15725569331642446be05292e3e1f8a51218827168cdclaireho				 HB_Buffer        buffer,
15735569331642446be05292e3e1f8a51218827168cdclaireho				 HB_UShort         flags,
15745569331642446be05292e3e1f8a51218827168cdclaireho				 HB_UShort         context_length,
15755569331642446be05292e3e1f8a51218827168cdclaireho				 int               nesting_level )
15765569331642446be05292e3e1f8a51218827168cdclaireho{
15775569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error         error;
15785569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        index, property;
15795569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt          first_pos;
15805569331642446be05292e3e1f8a51218827168cdclaireho  HB_GPOSHeader*  gpos = gpi->gpos;
15815569331642446be05292e3e1f8a51218827168cdclaireho  HB_PairPos*     pp = &st->pair;
15825569331642446be05292e3e1f8a51218827168cdclaireho
15835569331642446be05292e3e1f8a51218827168cdclaireho  HB_UNUSED(nesting_level);
15845569331642446be05292e3e1f8a51218827168cdclaireho
15855569331642446be05292e3e1f8a51218827168cdclaireho  if ( buffer->in_pos >= buffer->in_length - 1 )
15865569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;           /* Not enough glyphs in stream */
15875569331642446be05292e3e1f8a51218827168cdclaireho
15885569331642446be05292e3e1f8a51218827168cdclaireho  if ( context_length != 0xFFFF && context_length < 2 )
15895569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
15905569331642446be05292e3e1f8a51218827168cdclaireho
15915569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
15925569331642446be05292e3e1f8a51218827168cdclaireho    return error;
15935569331642446be05292e3e1f8a51218827168cdclaireho
15945569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Coverage_Index( &pp->Coverage, IN_CURGLYPH(), &index );
15955569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
15965569331642446be05292e3e1f8a51218827168cdclaireho    return error;
15975569331642446be05292e3e1f8a51218827168cdclaireho
15985569331642446be05292e3e1f8a51218827168cdclaireho  /* second glyph */
15995569331642446be05292e3e1f8a51218827168cdclaireho
16005569331642446be05292e3e1f8a51218827168cdclaireho  first_pos = buffer->in_pos;
16015569331642446be05292e3e1f8a51218827168cdclaireho  (buffer->in_pos)++;
16025569331642446be05292e3e1f8a51218827168cdclaireho
16035569331642446be05292e3e1f8a51218827168cdclaireho  while ( CHECK_Property( gpos->gdef, IN_CURITEM(),
16045569331642446be05292e3e1f8a51218827168cdclaireho			  flags, &property ) )
16055569331642446be05292e3e1f8a51218827168cdclaireho  {
16065569331642446be05292e3e1f8a51218827168cdclaireho    if ( error && error != HB_Err_Not_Covered )
16075569331642446be05292e3e1f8a51218827168cdclaireho      return error;
16085569331642446be05292e3e1f8a51218827168cdclaireho
16095569331642446be05292e3e1f8a51218827168cdclaireho    if ( buffer->in_pos == buffer->in_length )
16105569331642446be05292e3e1f8a51218827168cdclaireho      {
16115569331642446be05292e3e1f8a51218827168cdclaireho	buffer->in_pos = first_pos;
16125569331642446be05292e3e1f8a51218827168cdclaireho        return HB_Err_Not_Covered;
16135569331642446be05292e3e1f8a51218827168cdclaireho      }
16145569331642446be05292e3e1f8a51218827168cdclaireho    (buffer->in_pos)++;
16155569331642446be05292e3e1f8a51218827168cdclaireho
16165569331642446be05292e3e1f8a51218827168cdclaireho  }
16175569331642446be05292e3e1f8a51218827168cdclaireho
16185569331642446be05292e3e1f8a51218827168cdclaireho  switch ( pp->PosFormat )
16195569331642446be05292e3e1f8a51218827168cdclaireho  {
16205569331642446be05292e3e1f8a51218827168cdclaireho  case 1:
16215569331642446be05292e3e1f8a51218827168cdclaireho    error = Lookup_PairPos1( gpi, &pp->ppf.ppf1, buffer,
16225569331642446be05292e3e1f8a51218827168cdclaireho			     first_pos, index,
16235569331642446be05292e3e1f8a51218827168cdclaireho			     pp->ValueFormat1, pp->ValueFormat2 );
16245569331642446be05292e3e1f8a51218827168cdclaireho    break;
16255569331642446be05292e3e1f8a51218827168cdclaireho
16265569331642446be05292e3e1f8a51218827168cdclaireho  case 2:
16275569331642446be05292e3e1f8a51218827168cdclaireho    error = Lookup_PairPos2( gpi, &pp->ppf.ppf2, buffer, first_pos,
16285569331642446be05292e3e1f8a51218827168cdclaireho			     pp->ValueFormat1, pp->ValueFormat2 );
16295569331642446be05292e3e1f8a51218827168cdclaireho    break;
16305569331642446be05292e3e1f8a51218827168cdclaireho
16315569331642446be05292e3e1f8a51218827168cdclaireho  default:
16325569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable_Format);
16335569331642446be05292e3e1f8a51218827168cdclaireho  }
16345569331642446be05292e3e1f8a51218827168cdclaireho
16355569331642446be05292e3e1f8a51218827168cdclaireho  /* if we don't have coverage for the second glyph don't skip it for
16365569331642446be05292e3e1f8a51218827168cdclaireho     further lookups but reset in_pos back to the first_glyph and let
16375569331642446be05292e3e1f8a51218827168cdclaireho     the caller in Do_String_Lookup increment in_pos */
16385569331642446be05292e3e1f8a51218827168cdclaireho  if ( error == HB_Err_Not_Covered )
16395569331642446be05292e3e1f8a51218827168cdclaireho      buffer->in_pos = first_pos;
16405569331642446be05292e3e1f8a51218827168cdclaireho
16415569331642446be05292e3e1f8a51218827168cdclaireho  /* adjusting the `next' glyph */
16425569331642446be05292e3e1f8a51218827168cdclaireho
16435569331642446be05292e3e1f8a51218827168cdclaireho  if ( pp->ValueFormat2 )
16445569331642446be05292e3e1f8a51218827168cdclaireho    (buffer->in_pos)++;
16455569331642446be05292e3e1f8a51218827168cdclaireho
16465569331642446be05292e3e1f8a51218827168cdclaireho  return error;
16475569331642446be05292e3e1f8a51218827168cdclaireho}
16485569331642446be05292e3e1f8a51218827168cdclaireho
16495569331642446be05292e3e1f8a51218827168cdclaireho
16505569331642446be05292e3e1f8a51218827168cdclaireho/* LookupType 3 */
16515569331642446be05292e3e1f8a51218827168cdclaireho
16525569331642446be05292e3e1f8a51218827168cdclaireho/* CursivePosFormat1 */
16535569331642446be05292e3e1f8a51218827168cdclaireho
16545569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_CursivePos( HB_GPOS_SubTable* st,
16555569331642446be05292e3e1f8a51218827168cdclaireho				  HB_Stream        stream )
16565569331642446be05292e3e1f8a51218827168cdclaireho{
16575569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
16585569331642446be05292e3e1f8a51218827168cdclaireho  HB_CursivePos*  cp = &st->cursive;
16595569331642446be05292e3e1f8a51218827168cdclaireho
16605569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort             n, m, count;
16615569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt              cur_offset, new_offset, base_offset;
16625569331642446be05292e3e1f8a51218827168cdclaireho
16635569331642446be05292e3e1f8a51218827168cdclaireho  HB_EntryExitRecord*  eer;
16645569331642446be05292e3e1f8a51218827168cdclaireho
16655569331642446be05292e3e1f8a51218827168cdclaireho
16665569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
16675569331642446be05292e3e1f8a51218827168cdclaireho
16685569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 4L ) )
16695569331642446be05292e3e1f8a51218827168cdclaireho    return error;
16705569331642446be05292e3e1f8a51218827168cdclaireho
16715569331642446be05292e3e1f8a51218827168cdclaireho  cp->PosFormat = GET_UShort();
16725569331642446be05292e3e1f8a51218827168cdclaireho  new_offset    = GET_UShort() + base_offset;
16735569331642446be05292e3e1f8a51218827168cdclaireho
16745569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
16755569331642446be05292e3e1f8a51218827168cdclaireho
16765569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
16775569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
16785569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_Coverage( &cp->Coverage, stream ) ) != HB_Err_Ok )
16795569331642446be05292e3e1f8a51218827168cdclaireho    return error;
16805569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
16815569331642446be05292e3e1f8a51218827168cdclaireho
16825569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
16835569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
16845569331642446be05292e3e1f8a51218827168cdclaireho
16855569331642446be05292e3e1f8a51218827168cdclaireho  count = cp->EntryExitCount = GET_UShort();
16865569331642446be05292e3e1f8a51218827168cdclaireho
16875569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
16885569331642446be05292e3e1f8a51218827168cdclaireho
16895569331642446be05292e3e1f8a51218827168cdclaireho  cp->EntryExitRecord = NULL;
16905569331642446be05292e3e1f8a51218827168cdclaireho
16915569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cp->EntryExitRecord, count, HB_EntryExitRecord ) )
16925569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
16935569331642446be05292e3e1f8a51218827168cdclaireho
16945569331642446be05292e3e1f8a51218827168cdclaireho  eer = cp->EntryExitRecord;
16955569331642446be05292e3e1f8a51218827168cdclaireho
16965569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
16975569331642446be05292e3e1f8a51218827168cdclaireho  {
16985569331642446be05292e3e1f8a51218827168cdclaireho    HB_UInt entry_offset;
16995569331642446be05292e3e1f8a51218827168cdclaireho
17005569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
17015569331642446be05292e3e1f8a51218827168cdclaireho      return error;
17025569331642446be05292e3e1f8a51218827168cdclaireho
17035569331642446be05292e3e1f8a51218827168cdclaireho    entry_offset = new_offset = GET_UShort();
17045569331642446be05292e3e1f8a51218827168cdclaireho
17055569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
17065569331642446be05292e3e1f8a51218827168cdclaireho
17075569331642446be05292e3e1f8a51218827168cdclaireho    if ( new_offset )
17085569331642446be05292e3e1f8a51218827168cdclaireho    {
17095569331642446be05292e3e1f8a51218827168cdclaireho      new_offset += base_offset;
17105569331642446be05292e3e1f8a51218827168cdclaireho
17115569331642446be05292e3e1f8a51218827168cdclaireho      cur_offset = FILE_Pos();
17125569331642446be05292e3e1f8a51218827168cdclaireho      if ( FILE_Seek( new_offset ) ||
17135569331642446be05292e3e1f8a51218827168cdclaireho	   ( error = Load_Anchor( &eer[n].EntryAnchor,
17145569331642446be05292e3e1f8a51218827168cdclaireho				  stream ) ) != HB_Err_Ok )
17155569331642446be05292e3e1f8a51218827168cdclaireho	goto Fail1;
17165569331642446be05292e3e1f8a51218827168cdclaireho      (void)FILE_Seek( cur_offset );
17175569331642446be05292e3e1f8a51218827168cdclaireho    }
17185569331642446be05292e3e1f8a51218827168cdclaireho    else
17195569331642446be05292e3e1f8a51218827168cdclaireho      eer[n].EntryAnchor.PosFormat   = 0;
17205569331642446be05292e3e1f8a51218827168cdclaireho
17215569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
17225569331642446be05292e3e1f8a51218827168cdclaireho      return error;
17235569331642446be05292e3e1f8a51218827168cdclaireho
17245569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort();
17255569331642446be05292e3e1f8a51218827168cdclaireho
17265569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
17275569331642446be05292e3e1f8a51218827168cdclaireho
17285569331642446be05292e3e1f8a51218827168cdclaireho    if ( new_offset )
17295569331642446be05292e3e1f8a51218827168cdclaireho    {
17305569331642446be05292e3e1f8a51218827168cdclaireho      new_offset += base_offset;
17315569331642446be05292e3e1f8a51218827168cdclaireho
17325569331642446be05292e3e1f8a51218827168cdclaireho      cur_offset = FILE_Pos();
17335569331642446be05292e3e1f8a51218827168cdclaireho      if ( FILE_Seek( new_offset ) ||
17345569331642446be05292e3e1f8a51218827168cdclaireho	   ( error = Load_Anchor( &eer[n].ExitAnchor,
17355569331642446be05292e3e1f8a51218827168cdclaireho				  stream ) ) != HB_Err_Ok )
17365569331642446be05292e3e1f8a51218827168cdclaireho      {
17375569331642446be05292e3e1f8a51218827168cdclaireho	if ( entry_offset )
17385569331642446be05292e3e1f8a51218827168cdclaireho	  Free_Anchor( &eer[n].EntryAnchor );
17395569331642446be05292e3e1f8a51218827168cdclaireho	goto Fail1;
17405569331642446be05292e3e1f8a51218827168cdclaireho      }
17415569331642446be05292e3e1f8a51218827168cdclaireho      (void)FILE_Seek( cur_offset );
17425569331642446be05292e3e1f8a51218827168cdclaireho    }
17435569331642446be05292e3e1f8a51218827168cdclaireho    else
17445569331642446be05292e3e1f8a51218827168cdclaireho      eer[n].ExitAnchor.PosFormat   = 0;
17455569331642446be05292e3e1f8a51218827168cdclaireho  }
17465569331642446be05292e3e1f8a51218827168cdclaireho
17475569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
17485569331642446be05292e3e1f8a51218827168cdclaireho
17495569331642446be05292e3e1f8a51218827168cdclairehoFail1:
17505569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
17515569331642446be05292e3e1f8a51218827168cdclaireho  {
17525569331642446be05292e3e1f8a51218827168cdclaireho    Free_Anchor( &eer[m].EntryAnchor );
17535569331642446be05292e3e1f8a51218827168cdclaireho    Free_Anchor( &eer[m].ExitAnchor );
17545569331642446be05292e3e1f8a51218827168cdclaireho  }
17555569331642446be05292e3e1f8a51218827168cdclaireho
17565569331642446be05292e3e1f8a51218827168cdclaireho  FREE( eer );
17575569331642446be05292e3e1f8a51218827168cdclaireho
17585569331642446be05292e3e1f8a51218827168cdclairehoFail2:
17595569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &cp->Coverage );
17605569331642446be05292e3e1f8a51218827168cdclaireho  return error;
17615569331642446be05292e3e1f8a51218827168cdclaireho}
17625569331642446be05292e3e1f8a51218827168cdclaireho
17635569331642446be05292e3e1f8a51218827168cdclaireho
17645569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_CursivePos( HB_GPOS_SubTable* st )
17655569331642446be05292e3e1f8a51218827168cdclaireho{
17665569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort             n, count;
17675569331642446be05292e3e1f8a51218827168cdclaireho  HB_CursivePos*  cp = &st->cursive;
17685569331642446be05292e3e1f8a51218827168cdclaireho
17695569331642446be05292e3e1f8a51218827168cdclaireho  HB_EntryExitRecord*  eer;
17705569331642446be05292e3e1f8a51218827168cdclaireho
17715569331642446be05292e3e1f8a51218827168cdclaireho
17725569331642446be05292e3e1f8a51218827168cdclaireho  if ( cp->EntryExitRecord )
17735569331642446be05292e3e1f8a51218827168cdclaireho  {
17745569331642446be05292e3e1f8a51218827168cdclaireho    count = cp->EntryExitCount;
17755569331642446be05292e3e1f8a51218827168cdclaireho    eer   = cp->EntryExitRecord;
17765569331642446be05292e3e1f8a51218827168cdclaireho
17775569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
17785569331642446be05292e3e1f8a51218827168cdclaireho    {
17795569331642446be05292e3e1f8a51218827168cdclaireho      Free_Anchor( &eer[n].EntryAnchor );
17805569331642446be05292e3e1f8a51218827168cdclaireho      Free_Anchor( &eer[n].ExitAnchor );
17815569331642446be05292e3e1f8a51218827168cdclaireho    }
17825569331642446be05292e3e1f8a51218827168cdclaireho
17835569331642446be05292e3e1f8a51218827168cdclaireho    FREE( eer );
17845569331642446be05292e3e1f8a51218827168cdclaireho  }
17855569331642446be05292e3e1f8a51218827168cdclaireho
17865569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &cp->Coverage );
17875569331642446be05292e3e1f8a51218827168cdclaireho}
17885569331642446be05292e3e1f8a51218827168cdclaireho
17895569331642446be05292e3e1f8a51218827168cdclaireho
17905569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_CursivePos( GPOS_Instance*    gpi,
17915569331642446be05292e3e1f8a51218827168cdclaireho				    HB_GPOS_SubTable* st,
17925569331642446be05292e3e1f8a51218827168cdclaireho				    HB_Buffer        buffer,
17935569331642446be05292e3e1f8a51218827168cdclaireho				    HB_UShort         flags,
17945569331642446be05292e3e1f8a51218827168cdclaireho				    HB_UShort         context_length,
17955569331642446be05292e3e1f8a51218827168cdclaireho				    int               nesting_level )
17965569331642446be05292e3e1f8a51218827168cdclaireho{
17975569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        index, property;
17985569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error         error;
17995569331642446be05292e3e1f8a51218827168cdclaireho  HB_GPOSHeader*  gpos = gpi->gpos;
18005569331642446be05292e3e1f8a51218827168cdclaireho  HB_CursivePos*  cp = &st->cursive;
18015569331642446be05292e3e1f8a51218827168cdclaireho
18025569331642446be05292e3e1f8a51218827168cdclaireho  HB_EntryExitRecord*  eer;
18035569331642446be05292e3e1f8a51218827168cdclaireho  HB_Fixed                entry_x, entry_y;
18045569331642446be05292e3e1f8a51218827168cdclaireho  HB_Fixed                exit_x, exit_y;
18055569331642446be05292e3e1f8a51218827168cdclaireho
18065569331642446be05292e3e1f8a51218827168cdclaireho  HB_UNUSED(nesting_level);
18075569331642446be05292e3e1f8a51218827168cdclaireho
18085569331642446be05292e3e1f8a51218827168cdclaireho  if ( context_length != 0xFFFF && context_length < 1 )
18095569331642446be05292e3e1f8a51218827168cdclaireho  {
18105569331642446be05292e3e1f8a51218827168cdclaireho    gpi->last = 0xFFFF;
18115569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
18125569331642446be05292e3e1f8a51218827168cdclaireho  }
18135569331642446be05292e3e1f8a51218827168cdclaireho
18145569331642446be05292e3e1f8a51218827168cdclaireho  /* Glyphs not having the right GDEF properties will be ignored, i.e.,
18155569331642446be05292e3e1f8a51218827168cdclaireho     gpi->last won't be reset (contrary to user defined properties). */
18165569331642446be05292e3e1f8a51218827168cdclaireho
18175569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
18185569331642446be05292e3e1f8a51218827168cdclaireho    return error;
18195569331642446be05292e3e1f8a51218827168cdclaireho
18205569331642446be05292e3e1f8a51218827168cdclaireho  /* We don't handle mark glyphs here.  According to Andrei, this isn't
18215569331642446be05292e3e1f8a51218827168cdclaireho     possible, but who knows...                                         */
18225569331642446be05292e3e1f8a51218827168cdclaireho
18235569331642446be05292e3e1f8a51218827168cdclaireho  if ( property == HB_GDEF_MARK )
18245569331642446be05292e3e1f8a51218827168cdclaireho  {
18255569331642446be05292e3e1f8a51218827168cdclaireho    gpi->last = 0xFFFF;
18265569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
18275569331642446be05292e3e1f8a51218827168cdclaireho  }
18285569331642446be05292e3e1f8a51218827168cdclaireho
18295569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Coverage_Index( &cp->Coverage, IN_CURGLYPH(), &index );
18305569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
18315569331642446be05292e3e1f8a51218827168cdclaireho  {
18325569331642446be05292e3e1f8a51218827168cdclaireho    gpi->last = 0xFFFF;
18335569331642446be05292e3e1f8a51218827168cdclaireho    return error;
18345569331642446be05292e3e1f8a51218827168cdclaireho  }
18355569331642446be05292e3e1f8a51218827168cdclaireho
18365569331642446be05292e3e1f8a51218827168cdclaireho  if ( index >= cp->EntryExitCount )
18375569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable);
18385569331642446be05292e3e1f8a51218827168cdclaireho
18395569331642446be05292e3e1f8a51218827168cdclaireho  eer = &cp->EntryExitRecord[index];
18405569331642446be05292e3e1f8a51218827168cdclaireho
18415569331642446be05292e3e1f8a51218827168cdclaireho  /* Now comes the messiest part of the whole OpenType
18425569331642446be05292e3e1f8a51218827168cdclaireho     specification.  At first glance, cursive connections seem easy
18435569331642446be05292e3e1f8a51218827168cdclaireho     to understand, but there are pitfalls!  The reason is that
18445569331642446be05292e3e1f8a51218827168cdclaireho     the specs don't mention how to compute the advance values
18455569331642446be05292e3e1f8a51218827168cdclaireho     resp. glyph offsets.  I was told it would be an omission, to
18465569331642446be05292e3e1f8a51218827168cdclaireho     be fixed in the next OpenType version...  Again many thanks to
18475569331642446be05292e3e1f8a51218827168cdclaireho     Andrei Burago <andreib@microsoft.com> for clarifications.
18485569331642446be05292e3e1f8a51218827168cdclaireho
18495569331642446be05292e3e1f8a51218827168cdclaireho     Consider the following example:
18505569331642446be05292e3e1f8a51218827168cdclaireho
18515569331642446be05292e3e1f8a51218827168cdclaireho		      |  xadv1    |
18525569331642446be05292e3e1f8a51218827168cdclaireho		       +---------+
18535569331642446be05292e3e1f8a51218827168cdclaireho		       |         |
18545569331642446be05292e3e1f8a51218827168cdclaireho		 +-----+--+ 1    |
18555569331642446be05292e3e1f8a51218827168cdclaireho		 |     | .|      |
18565569331642446be05292e3e1f8a51218827168cdclaireho		 |    0+--+------+
18575569331642446be05292e3e1f8a51218827168cdclaireho		 |   2    |
18585569331642446be05292e3e1f8a51218827168cdclaireho		 |        |
18595569331642446be05292e3e1f8a51218827168cdclaireho		0+--------+
18605569331642446be05292e3e1f8a51218827168cdclaireho		|  xadv2   |
18615569331642446be05292e3e1f8a51218827168cdclaireho
18625569331642446be05292e3e1f8a51218827168cdclaireho       glyph1: advance width = 12
18635569331642446be05292e3e1f8a51218827168cdclaireho	       anchor point = (3,1)
18645569331642446be05292e3e1f8a51218827168cdclaireho
18655569331642446be05292e3e1f8a51218827168cdclaireho       glyph2: advance width = 11
18665569331642446be05292e3e1f8a51218827168cdclaireho	       anchor point = (9,4)
18675569331642446be05292e3e1f8a51218827168cdclaireho
18685569331642446be05292e3e1f8a51218827168cdclaireho       LSB is 1 for both glyphs (so the boxes drawn above are glyph
18695569331642446be05292e3e1f8a51218827168cdclaireho       bboxes).  Writing direction is R2L; `0' denotes the glyph's
18705569331642446be05292e3e1f8a51218827168cdclaireho       coordinate origin.
18715569331642446be05292e3e1f8a51218827168cdclaireho
18725569331642446be05292e3e1f8a51218827168cdclaireho     Now the surprising part: The advance width of the *left* glyph
18735569331642446be05292e3e1f8a51218827168cdclaireho     (resp. of the *bottom* glyph) will be modified, no matter
18745569331642446be05292e3e1f8a51218827168cdclaireho     whether the writing direction is L2R or R2L (resp. T2B or
18755569331642446be05292e3e1f8a51218827168cdclaireho     B2T)!  This assymetry is caused by the fact that the glyph's
18765569331642446be05292e3e1f8a51218827168cdclaireho     coordinate origin is always the lower left corner for all
18775569331642446be05292e3e1f8a51218827168cdclaireho     writing directions.
18785569331642446be05292e3e1f8a51218827168cdclaireho
18795569331642446be05292e3e1f8a51218827168cdclaireho     Continuing the above example, we can compute the new
18805569331642446be05292e3e1f8a51218827168cdclaireho     (horizontal) advance width of glyph2 as
18815569331642446be05292e3e1f8a51218827168cdclaireho
18825569331642446be05292e3e1f8a51218827168cdclaireho       9 - 3 = 6  ,
18835569331642446be05292e3e1f8a51218827168cdclaireho
18845569331642446be05292e3e1f8a51218827168cdclaireho     and the new vertical offset of glyph2 as
18855569331642446be05292e3e1f8a51218827168cdclaireho
18865569331642446be05292e3e1f8a51218827168cdclaireho       1 - 4 = -3  .
18875569331642446be05292e3e1f8a51218827168cdclaireho
18885569331642446be05292e3e1f8a51218827168cdclaireho
18895569331642446be05292e3e1f8a51218827168cdclaireho     Vertical writing direction is far more complicated:
18905569331642446be05292e3e1f8a51218827168cdclaireho
18915569331642446be05292e3e1f8a51218827168cdclaireho     a) Assuming that we recompute the advance height of the lower glyph:
18925569331642446be05292e3e1f8a51218827168cdclaireho
18935569331642446be05292e3e1f8a51218827168cdclaireho				  --
18945569331642446be05292e3e1f8a51218827168cdclaireho		       +---------+
18955569331642446be05292e3e1f8a51218827168cdclaireho	      --       |         |
18965569331642446be05292e3e1f8a51218827168cdclaireho		 +-----+--+ 1    | yadv1
18975569331642446be05292e3e1f8a51218827168cdclaireho		 |     | .|      |
18985569331642446be05292e3e1f8a51218827168cdclaireho	   yadv2 |    0+--+------+        -- BSB1  --
18995569331642446be05292e3e1f8a51218827168cdclaireho		 |   2    |       --      --        y_offset
19005569331642446be05292e3e1f8a51218827168cdclaireho		 |        |
19015569331642446be05292e3e1f8a51218827168cdclaireho   BSB2 --      0+--------+                        --
19025569331642446be05292e3e1f8a51218827168cdclaireho	--    --
19035569331642446be05292e3e1f8a51218827168cdclaireho
19045569331642446be05292e3e1f8a51218827168cdclaireho       glyph1: advance height = 6
19055569331642446be05292e3e1f8a51218827168cdclaireho	       anchor point = (3,1)
19065569331642446be05292e3e1f8a51218827168cdclaireho
19075569331642446be05292e3e1f8a51218827168cdclaireho       glyph2: advance height = 7
19085569331642446be05292e3e1f8a51218827168cdclaireho	       anchor point = (9,4)
19095569331642446be05292e3e1f8a51218827168cdclaireho
19105569331642446be05292e3e1f8a51218827168cdclaireho       TSB is 1 for both glyphs; writing direction is T2B.
19115569331642446be05292e3e1f8a51218827168cdclaireho
19125569331642446be05292e3e1f8a51218827168cdclaireho
19135569331642446be05292e3e1f8a51218827168cdclaireho	 BSB1     = yadv1 - (TSB1 + ymax1)
19145569331642446be05292e3e1f8a51218827168cdclaireho	 BSB2     = yadv2 - (TSB2 + ymax2)
19155569331642446be05292e3e1f8a51218827168cdclaireho	 y_offset = y2 - y1
19165569331642446be05292e3e1f8a51218827168cdclaireho
19175569331642446be05292e3e1f8a51218827168cdclaireho       vertical advance width of glyph2
19185569331642446be05292e3e1f8a51218827168cdclaireho	 = y_offset + BSB2 - BSB1
19195569331642446be05292e3e1f8a51218827168cdclaireho	 = (y2 - y1) + (yadv2 - (TSB2 + ymax2)) - (yadv1 - (TSB1 + ymax1))
19205569331642446be05292e3e1f8a51218827168cdclaireho	 = y2 - y1 + yadv2 - TSB2 - ymax2 - (yadv1 - TSB1 - ymax1)
19215569331642446be05292e3e1f8a51218827168cdclaireho	 = y2 - y1 + yadv2 - TSB2 - ymax2 - yadv1 + TSB1 + ymax1
19225569331642446be05292e3e1f8a51218827168cdclaireho
19235569331642446be05292e3e1f8a51218827168cdclaireho
19245569331642446be05292e3e1f8a51218827168cdclaireho     b) Assuming that we recompute the advance height of the upper glyph:
19255569331642446be05292e3e1f8a51218827168cdclaireho
19265569331642446be05292e3e1f8a51218827168cdclaireho				  --      --
19275569331642446be05292e3e1f8a51218827168cdclaireho		       +---------+        -- TSB1
19285569331642446be05292e3e1f8a51218827168cdclaireho	--    --       |         |
19295569331642446be05292e3e1f8a51218827168cdclaireho   TSB2 --       +-----+--+ 1    | yadv1   ymax1
19305569331642446be05292e3e1f8a51218827168cdclaireho		 |     | .|      |
19315569331642446be05292e3e1f8a51218827168cdclaireho	   yadv2 |    0+--+------+        --       --
19325569331642446be05292e3e1f8a51218827168cdclaireho    ymax2        |   2    |       --                y_offset
19335569331642446be05292e3e1f8a51218827168cdclaireho		 |        |
19345569331642446be05292e3e1f8a51218827168cdclaireho	--      0+--------+                        --
19355569331642446be05292e3e1f8a51218827168cdclaireho	      --
19365569331642446be05292e3e1f8a51218827168cdclaireho
19375569331642446be05292e3e1f8a51218827168cdclaireho       glyph1: advance height = 6
19385569331642446be05292e3e1f8a51218827168cdclaireho	       anchor point = (3,1)
19395569331642446be05292e3e1f8a51218827168cdclaireho
19405569331642446be05292e3e1f8a51218827168cdclaireho       glyph2: advance height = 7
19415569331642446be05292e3e1f8a51218827168cdclaireho	       anchor point = (9,4)
19425569331642446be05292e3e1f8a51218827168cdclaireho
19435569331642446be05292e3e1f8a51218827168cdclaireho       TSB is 1 for both glyphs; writing direction is T2B.
19445569331642446be05292e3e1f8a51218827168cdclaireho
19455569331642446be05292e3e1f8a51218827168cdclaireho       y_offset = y2 - y1
19465569331642446be05292e3e1f8a51218827168cdclaireho
19475569331642446be05292e3e1f8a51218827168cdclaireho       vertical advance width of glyph2
19485569331642446be05292e3e1f8a51218827168cdclaireho	 = TSB1 + ymax1 + y_offset - (TSB2 + ymax2)
19495569331642446be05292e3e1f8a51218827168cdclaireho	 = TSB1 + ymax1 + y2 - y1 - TSB2 - ymax2
19505569331642446be05292e3e1f8a51218827168cdclaireho
19515569331642446be05292e3e1f8a51218827168cdclaireho
19525569331642446be05292e3e1f8a51218827168cdclaireho     Comparing a) with b) shows that b) is easier to compute.  I'll wait
19535569331642446be05292e3e1f8a51218827168cdclaireho     for a reply from Andrei to see what should really be implemented...
19545569331642446be05292e3e1f8a51218827168cdclaireho
19555569331642446be05292e3e1f8a51218827168cdclaireho     Since horizontal advance widths or vertical advance heights
19565569331642446be05292e3e1f8a51218827168cdclaireho     can be used alone but not together, no ambiguity occurs.        */
19575569331642446be05292e3e1f8a51218827168cdclaireho
19585569331642446be05292e3e1f8a51218827168cdclaireho  if ( gpi->last == 0xFFFF )
19595569331642446be05292e3e1f8a51218827168cdclaireho    goto end;
19605569331642446be05292e3e1f8a51218827168cdclaireho
19615569331642446be05292e3e1f8a51218827168cdclaireho  /* Get_Anchor() returns HB_Err_Not_Covered if there is no anchor
19625569331642446be05292e3e1f8a51218827168cdclaireho     table.                                                         */
19635569331642446be05292e3e1f8a51218827168cdclaireho
19645569331642446be05292e3e1f8a51218827168cdclaireho  error = Get_Anchor( gpi, &eer->EntryAnchor, IN_CURGLYPH(),
19655569331642446be05292e3e1f8a51218827168cdclaireho		      &entry_x, &entry_y );
19665569331642446be05292e3e1f8a51218827168cdclaireho  if ( error == HB_Err_Not_Covered )
19675569331642446be05292e3e1f8a51218827168cdclaireho    goto end;
19685569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
19695569331642446be05292e3e1f8a51218827168cdclaireho    return error;
19705569331642446be05292e3e1f8a51218827168cdclaireho
19715569331642446be05292e3e1f8a51218827168cdclaireho  if ( gpi->r2l )
19725569331642446be05292e3e1f8a51218827168cdclaireho  {
19735569331642446be05292e3e1f8a51218827168cdclaireho    POSITION( buffer->in_pos )->x_advance   = entry_x - gpi->anchor_x;
19745569331642446be05292e3e1f8a51218827168cdclaireho    POSITION( buffer->in_pos )->new_advance = TRUE;
19755569331642446be05292e3e1f8a51218827168cdclaireho  }
19765569331642446be05292e3e1f8a51218827168cdclaireho  else
19775569331642446be05292e3e1f8a51218827168cdclaireho  {
19785569331642446be05292e3e1f8a51218827168cdclaireho    POSITION( gpi->last )->x_advance   = gpi->anchor_x - entry_x;
19795569331642446be05292e3e1f8a51218827168cdclaireho    POSITION( gpi->last )->new_advance = TRUE;
19805569331642446be05292e3e1f8a51218827168cdclaireho  }
19815569331642446be05292e3e1f8a51218827168cdclaireho
19825569331642446be05292e3e1f8a51218827168cdclaireho  if ( flags & HB_LOOKUP_FLAG_RIGHT_TO_LEFT )
19835569331642446be05292e3e1f8a51218827168cdclaireho  {
19845569331642446be05292e3e1f8a51218827168cdclaireho    POSITION( gpi->last )->cursive_chain = gpi->last - buffer->in_pos;
19855569331642446be05292e3e1f8a51218827168cdclaireho    POSITION( gpi->last )->y_pos = entry_y - gpi->anchor_y;
19865569331642446be05292e3e1f8a51218827168cdclaireho  }
19875569331642446be05292e3e1f8a51218827168cdclaireho  else
19885569331642446be05292e3e1f8a51218827168cdclaireho  {
19895569331642446be05292e3e1f8a51218827168cdclaireho    POSITION( buffer->in_pos )->cursive_chain = buffer->in_pos - gpi->last;
19905569331642446be05292e3e1f8a51218827168cdclaireho    POSITION( buffer->in_pos )->y_pos = gpi->anchor_y - entry_y;
19915569331642446be05292e3e1f8a51218827168cdclaireho  }
19925569331642446be05292e3e1f8a51218827168cdclaireho
19935569331642446be05292e3e1f8a51218827168cdclairehoend:
19945569331642446be05292e3e1f8a51218827168cdclaireho  error = Get_Anchor( gpi, &eer->ExitAnchor, IN_CURGLYPH(),
19955569331642446be05292e3e1f8a51218827168cdclaireho		      &exit_x, &exit_y );
19965569331642446be05292e3e1f8a51218827168cdclaireho  if ( error == HB_Err_Not_Covered )
19975569331642446be05292e3e1f8a51218827168cdclaireho    gpi->last = 0xFFFF;
19985569331642446be05292e3e1f8a51218827168cdclaireho  else
19995569331642446be05292e3e1f8a51218827168cdclaireho  {
20005569331642446be05292e3e1f8a51218827168cdclaireho    gpi->last     = buffer->in_pos;
20015569331642446be05292e3e1f8a51218827168cdclaireho    gpi->anchor_x = exit_x;
20025569331642446be05292e3e1f8a51218827168cdclaireho    gpi->anchor_y = exit_y;
20035569331642446be05292e3e1f8a51218827168cdclaireho  }
20045569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
20055569331642446be05292e3e1f8a51218827168cdclaireho    return error;
20065569331642446be05292e3e1f8a51218827168cdclaireho
20075569331642446be05292e3e1f8a51218827168cdclaireho  (buffer->in_pos)++;
20085569331642446be05292e3e1f8a51218827168cdclaireho
20095569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
20105569331642446be05292e3e1f8a51218827168cdclaireho}
20115569331642446be05292e3e1f8a51218827168cdclaireho
20125569331642446be05292e3e1f8a51218827168cdclaireho
20135569331642446be05292e3e1f8a51218827168cdclaireho/* LookupType 4 */
20145569331642446be05292e3e1f8a51218827168cdclaireho
20155569331642446be05292e3e1f8a51218827168cdclaireho/* BaseArray */
20165569331642446be05292e3e1f8a51218827168cdclaireho
20175569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_BaseArray( HB_BaseArray*  ba,
20185569331642446be05292e3e1f8a51218827168cdclaireho				 HB_UShort       num_classes,
20195569331642446be05292e3e1f8a51218827168cdclaireho				 HB_Stream       stream )
20205569331642446be05292e3e1f8a51218827168cdclaireho{
20215569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
20225569331642446be05292e3e1f8a51218827168cdclaireho
20235569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort       m, n, count;
20245569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt         cur_offset, new_offset, base_offset;
20255569331642446be05292e3e1f8a51218827168cdclaireho
20265569331642446be05292e3e1f8a51218827168cdclaireho  HB_BaseRecord  *br;
20275569331642446be05292e3e1f8a51218827168cdclaireho  HB_Anchor      *ban, *bans;
20285569331642446be05292e3e1f8a51218827168cdclaireho
20295569331642446be05292e3e1f8a51218827168cdclaireho
20305569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
20315569331642446be05292e3e1f8a51218827168cdclaireho
20325569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
20335569331642446be05292e3e1f8a51218827168cdclaireho    return error;
20345569331642446be05292e3e1f8a51218827168cdclaireho
20355569331642446be05292e3e1f8a51218827168cdclaireho  count = ba->BaseCount = GET_UShort();
20365569331642446be05292e3e1f8a51218827168cdclaireho
20375569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
20385569331642446be05292e3e1f8a51218827168cdclaireho
20395569331642446be05292e3e1f8a51218827168cdclaireho  ba->BaseRecord = NULL;
20405569331642446be05292e3e1f8a51218827168cdclaireho
20415569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ba->BaseRecord, count, HB_BaseRecord ) )
20425569331642446be05292e3e1f8a51218827168cdclaireho    return error;
20435569331642446be05292e3e1f8a51218827168cdclaireho
20445569331642446be05292e3e1f8a51218827168cdclaireho  br = ba->BaseRecord;
20455569331642446be05292e3e1f8a51218827168cdclaireho
20465569331642446be05292e3e1f8a51218827168cdclaireho  bans = NULL;
20475569331642446be05292e3e1f8a51218827168cdclaireho
20485569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( bans, count * num_classes, HB_Anchor ) )
20495569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail;
20505569331642446be05292e3e1f8a51218827168cdclaireho
20515569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < count; m++ )
20525569331642446be05292e3e1f8a51218827168cdclaireho  {
20535569331642446be05292e3e1f8a51218827168cdclaireho    br[m].BaseAnchor = NULL;
20545569331642446be05292e3e1f8a51218827168cdclaireho
20555569331642446be05292e3e1f8a51218827168cdclaireho    ban = br[m].BaseAnchor = bans + m * num_classes;
20565569331642446be05292e3e1f8a51218827168cdclaireho
20575569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < num_classes; n++ )
20585569331642446be05292e3e1f8a51218827168cdclaireho    {
20595569331642446be05292e3e1f8a51218827168cdclaireho      if ( ACCESS_Frame( 2L ) )
20605569331642446be05292e3e1f8a51218827168cdclaireho	goto Fail;
20615569331642446be05292e3e1f8a51218827168cdclaireho
20625569331642446be05292e3e1f8a51218827168cdclaireho      new_offset = GET_UShort() + base_offset;
20635569331642446be05292e3e1f8a51218827168cdclaireho
20645569331642446be05292e3e1f8a51218827168cdclaireho      FORGET_Frame();
20655569331642446be05292e3e1f8a51218827168cdclaireho
20665569331642446be05292e3e1f8a51218827168cdclaireho      if (new_offset == base_offset) {
20675569331642446be05292e3e1f8a51218827168cdclaireho	/* XXX
20685569331642446be05292e3e1f8a51218827168cdclaireho	 * Doulos SIL Regular is buggy and has zero offsets here.
20695569331642446be05292e3e1f8a51218827168cdclaireho	 * Skip it
20705569331642446be05292e3e1f8a51218827168cdclaireho	 */
20715569331642446be05292e3e1f8a51218827168cdclaireho	ban[n].PosFormat = 0;
20725569331642446be05292e3e1f8a51218827168cdclaireho	continue;
20735569331642446be05292e3e1f8a51218827168cdclaireho      }
20745569331642446be05292e3e1f8a51218827168cdclaireho
20755569331642446be05292e3e1f8a51218827168cdclaireho      cur_offset = FILE_Pos();
20765569331642446be05292e3e1f8a51218827168cdclaireho      if ( FILE_Seek( new_offset ) ||
20775569331642446be05292e3e1f8a51218827168cdclaireho	   ( error = Load_Anchor( &ban[n], stream ) ) != HB_Err_Ok )
20785569331642446be05292e3e1f8a51218827168cdclaireho	goto Fail;
20795569331642446be05292e3e1f8a51218827168cdclaireho      (void)FILE_Seek( cur_offset );
20805569331642446be05292e3e1f8a51218827168cdclaireho    }
20815569331642446be05292e3e1f8a51218827168cdclaireho  }
20825569331642446be05292e3e1f8a51218827168cdclaireho
20835569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
20845569331642446be05292e3e1f8a51218827168cdclaireho
20855569331642446be05292e3e1f8a51218827168cdclairehoFail:
20865569331642446be05292e3e1f8a51218827168cdclaireho  FREE( bans );
20875569331642446be05292e3e1f8a51218827168cdclaireho  FREE( br );
20885569331642446be05292e3e1f8a51218827168cdclaireho  return error;
20895569331642446be05292e3e1f8a51218827168cdclaireho}
20905569331642446be05292e3e1f8a51218827168cdclaireho
20915569331642446be05292e3e1f8a51218827168cdclaireho
20925569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_BaseArray( HB_BaseArray*  ba,
20935569331642446be05292e3e1f8a51218827168cdclaireho			     HB_UShort       num_classes )
20945569331642446be05292e3e1f8a51218827168cdclaireho{
20955569331642446be05292e3e1f8a51218827168cdclaireho  HB_BaseRecord  *br;
20965569331642446be05292e3e1f8a51218827168cdclaireho  HB_Anchor      *bans;
20975569331642446be05292e3e1f8a51218827168cdclaireho
20985569331642446be05292e3e1f8a51218827168cdclaireho  if ( ba->BaseRecord )
20995569331642446be05292e3e1f8a51218827168cdclaireho  {
21005569331642446be05292e3e1f8a51218827168cdclaireho    br    = ba->BaseRecord;
21015569331642446be05292e3e1f8a51218827168cdclaireho
21025569331642446be05292e3e1f8a51218827168cdclaireho    if ( ba->BaseCount )
21035569331642446be05292e3e1f8a51218827168cdclaireho    {
21045569331642446be05292e3e1f8a51218827168cdclaireho      HB_UShort i, count;
21055569331642446be05292e3e1f8a51218827168cdclaireho      count = num_classes * ba->BaseCount;
21065569331642446be05292e3e1f8a51218827168cdclaireho      bans = br[0].BaseAnchor;
21075569331642446be05292e3e1f8a51218827168cdclaireho      for (i = 0; i < count; i++)
21085569331642446be05292e3e1f8a51218827168cdclaireho        Free_Anchor (&bans[i]);
21095569331642446be05292e3e1f8a51218827168cdclaireho      FREE( bans );
21105569331642446be05292e3e1f8a51218827168cdclaireho    }
21115569331642446be05292e3e1f8a51218827168cdclaireho
21125569331642446be05292e3e1f8a51218827168cdclaireho    FREE( br );
21135569331642446be05292e3e1f8a51218827168cdclaireho  }
21145569331642446be05292e3e1f8a51218827168cdclaireho}
21155569331642446be05292e3e1f8a51218827168cdclaireho
21165569331642446be05292e3e1f8a51218827168cdclaireho
21175569331642446be05292e3e1f8a51218827168cdclaireho/* MarkBasePosFormat1 */
21185569331642446be05292e3e1f8a51218827168cdclaireho
21195569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_MarkBasePos( HB_GPOS_SubTable* st,
21205569331642446be05292e3e1f8a51218827168cdclaireho				   HB_Stream         stream )
21215569331642446be05292e3e1f8a51218827168cdclaireho{
21225569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
21235569331642446be05292e3e1f8a51218827168cdclaireho  HB_MarkBasePos* mbp = &st->markbase;
21245569331642446be05292e3e1f8a51218827168cdclaireho
21255569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt  cur_offset, new_offset, base_offset;
21265569331642446be05292e3e1f8a51218827168cdclaireho
21275569331642446be05292e3e1f8a51218827168cdclaireho
21285569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
21295569331642446be05292e3e1f8a51218827168cdclaireho
21305569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 4L ) )
21315569331642446be05292e3e1f8a51218827168cdclaireho    return error;
21325569331642446be05292e3e1f8a51218827168cdclaireho
21335569331642446be05292e3e1f8a51218827168cdclaireho  mbp->PosFormat = GET_UShort();
21345569331642446be05292e3e1f8a51218827168cdclaireho  new_offset     = GET_UShort() + base_offset;
21355569331642446be05292e3e1f8a51218827168cdclaireho
21365569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
21375569331642446be05292e3e1f8a51218827168cdclaireho
21385569331642446be05292e3e1f8a51218827168cdclaireho  if (mbp->PosFormat != 1)
21395569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable_Format);
21405569331642446be05292e3e1f8a51218827168cdclaireho
21415569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
21425569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
21435569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_Coverage( &mbp->MarkCoverage, stream ) ) != HB_Err_Ok )
21445569331642446be05292e3e1f8a51218827168cdclaireho    return error;
21455569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
21465569331642446be05292e3e1f8a51218827168cdclaireho
21475569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
21485569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
21495569331642446be05292e3e1f8a51218827168cdclaireho
21505569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
21515569331642446be05292e3e1f8a51218827168cdclaireho
21525569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
21535569331642446be05292e3e1f8a51218827168cdclaireho
21545569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
21555569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
21565569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_Coverage( &mbp->BaseCoverage, stream ) ) != HB_Err_Ok )
21575569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
21585569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
21595569331642446be05292e3e1f8a51218827168cdclaireho
21605569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 4L ) )
21615569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
21625569331642446be05292e3e1f8a51218827168cdclaireho
21635569331642446be05292e3e1f8a51218827168cdclaireho  mbp->ClassCount = GET_UShort();
21645569331642446be05292e3e1f8a51218827168cdclaireho  new_offset      = GET_UShort() + base_offset;
21655569331642446be05292e3e1f8a51218827168cdclaireho
21665569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
21675569331642446be05292e3e1f8a51218827168cdclaireho
21685569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
21695569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
21705569331642446be05292e3e1f8a51218827168cdclaireho       ( error = Load_MarkArray( &mbp->MarkArray, stream ) ) != HB_Err_Ok )
21715569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
21725569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
21735569331642446be05292e3e1f8a51218827168cdclaireho
21745569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
21755569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail1;
21765569331642446be05292e3e1f8a51218827168cdclaireho
21775569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
21785569331642446be05292e3e1f8a51218827168cdclaireho
21795569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
21805569331642446be05292e3e1f8a51218827168cdclaireho
21815569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
21825569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
21835569331642446be05292e3e1f8a51218827168cdclaireho       ( error = Load_BaseArray( &mbp->BaseArray, mbp->ClassCount,
21845569331642446be05292e3e1f8a51218827168cdclaireho				 stream ) ) != HB_Err_Ok )
21855569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail1;
21865569331642446be05292e3e1f8a51218827168cdclaireho
21875569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
21885569331642446be05292e3e1f8a51218827168cdclaireho
21895569331642446be05292e3e1f8a51218827168cdclairehoFail1:
21905569331642446be05292e3e1f8a51218827168cdclaireho  Free_MarkArray( &mbp->MarkArray );
21915569331642446be05292e3e1f8a51218827168cdclaireho
21925569331642446be05292e3e1f8a51218827168cdclairehoFail2:
21935569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &mbp->BaseCoverage );
21945569331642446be05292e3e1f8a51218827168cdclaireho
21955569331642446be05292e3e1f8a51218827168cdclairehoFail3:
21965569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &mbp->MarkCoverage );
21975569331642446be05292e3e1f8a51218827168cdclaireho  return error;
21985569331642446be05292e3e1f8a51218827168cdclaireho}
21995569331642446be05292e3e1f8a51218827168cdclaireho
22005569331642446be05292e3e1f8a51218827168cdclaireho
22015569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_MarkBasePos( HB_GPOS_SubTable* st )
22025569331642446be05292e3e1f8a51218827168cdclaireho{
22035569331642446be05292e3e1f8a51218827168cdclaireho  HB_MarkBasePos* mbp = &st->markbase;
22045569331642446be05292e3e1f8a51218827168cdclaireho
22055569331642446be05292e3e1f8a51218827168cdclaireho  Free_BaseArray( &mbp->BaseArray, mbp->ClassCount );
22065569331642446be05292e3e1f8a51218827168cdclaireho  Free_MarkArray( &mbp->MarkArray );
22075569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &mbp->BaseCoverage );
22085569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &mbp->MarkCoverage );
22095569331642446be05292e3e1f8a51218827168cdclaireho}
22105569331642446be05292e3e1f8a51218827168cdclaireho
22115569331642446be05292e3e1f8a51218827168cdclaireho
22125569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_MarkBasePos( GPOS_Instance*    gpi,
22135569331642446be05292e3e1f8a51218827168cdclaireho				     HB_GPOS_SubTable* st,
22145569331642446be05292e3e1f8a51218827168cdclaireho				     HB_Buffer        buffer,
22155569331642446be05292e3e1f8a51218827168cdclaireho				     HB_UShort         flags,
22165569331642446be05292e3e1f8a51218827168cdclaireho				     HB_UShort         context_length,
22175569331642446be05292e3e1f8a51218827168cdclaireho				     int               nesting_level )
22185569331642446be05292e3e1f8a51218827168cdclaireho{
22195569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        i, j, mark_index, base_index, property, class;
22205569331642446be05292e3e1f8a51218827168cdclaireho  HB_Fixed           x_mark_value, y_mark_value, x_base_value, y_base_value;
22215569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error         error;
22225569331642446be05292e3e1f8a51218827168cdclaireho  HB_GPOSHeader*  gpos = gpi->gpos;
22235569331642446be05292e3e1f8a51218827168cdclaireho  HB_MarkBasePos* mbp = &st->markbase;
22245569331642446be05292e3e1f8a51218827168cdclaireho
22255569331642446be05292e3e1f8a51218827168cdclaireho  HB_MarkArray*   ma;
22265569331642446be05292e3e1f8a51218827168cdclaireho  HB_BaseArray*   ba;
22275569331642446be05292e3e1f8a51218827168cdclaireho  HB_BaseRecord*  br;
22285569331642446be05292e3e1f8a51218827168cdclaireho  HB_Anchor*      mark_anchor;
22295569331642446be05292e3e1f8a51218827168cdclaireho  HB_Anchor*      base_anchor;
22305569331642446be05292e3e1f8a51218827168cdclaireho
22315569331642446be05292e3e1f8a51218827168cdclaireho  HB_Position     o;
22325569331642446be05292e3e1f8a51218827168cdclaireho
22335569331642446be05292e3e1f8a51218827168cdclaireho  HB_UNUSED(nesting_level);
22345569331642446be05292e3e1f8a51218827168cdclaireho
22355569331642446be05292e3e1f8a51218827168cdclaireho  if ( context_length != 0xFFFF && context_length < 1 )
22365569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
22375569331642446be05292e3e1f8a51218827168cdclaireho
22385569331642446be05292e3e1f8a51218827168cdclaireho  if ( flags & HB_LOOKUP_FLAG_IGNORE_BASE_GLYPHS )
22395569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
22405569331642446be05292e3e1f8a51218827168cdclaireho
22415569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gpos->gdef, IN_CURITEM(),
22425569331642446be05292e3e1f8a51218827168cdclaireho		       flags, &property ) )
22435569331642446be05292e3e1f8a51218827168cdclaireho    return error;
22445569331642446be05292e3e1f8a51218827168cdclaireho
22455569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Coverage_Index( &mbp->MarkCoverage, IN_CURGLYPH(),
22465569331642446be05292e3e1f8a51218827168cdclaireho			  &mark_index );
22475569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
22485569331642446be05292e3e1f8a51218827168cdclaireho    return error;
22495569331642446be05292e3e1f8a51218827168cdclaireho
22505569331642446be05292e3e1f8a51218827168cdclaireho  /* now we search backwards for a non-mark glyph */
22515569331642446be05292e3e1f8a51218827168cdclaireho
22525569331642446be05292e3e1f8a51218827168cdclaireho  i = 1;
22535569331642446be05292e3e1f8a51218827168cdclaireho  j = buffer->in_pos - 1;
22545569331642446be05292e3e1f8a51218827168cdclaireho
22555569331642446be05292e3e1f8a51218827168cdclaireho  while ( i <= buffer->in_pos )
22565569331642446be05292e3e1f8a51218827168cdclaireho  {
22575569331642446be05292e3e1f8a51218827168cdclaireho    error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
22585569331642446be05292e3e1f8a51218827168cdclaireho					&property );
22595569331642446be05292e3e1f8a51218827168cdclaireho    if ( error )
22605569331642446be05292e3e1f8a51218827168cdclaireho      return error;
22615569331642446be05292e3e1f8a51218827168cdclaireho
22625569331642446be05292e3e1f8a51218827168cdclaireho    if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
22635569331642446be05292e3e1f8a51218827168cdclaireho      break;
22645569331642446be05292e3e1f8a51218827168cdclaireho
22655569331642446be05292e3e1f8a51218827168cdclaireho    i++;
22665569331642446be05292e3e1f8a51218827168cdclaireho    j--;
22675569331642446be05292e3e1f8a51218827168cdclaireho  }
22685569331642446be05292e3e1f8a51218827168cdclaireho
22695569331642446be05292e3e1f8a51218827168cdclaireho  /* The following assertion is too strong -- at least for mangal.ttf. */
22705569331642446be05292e3e1f8a51218827168cdclaireho#if 0
22715569331642446be05292e3e1f8a51218827168cdclaireho  if ( property != HB_GDEF_BASE_GLYPH )
22725569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
22735569331642446be05292e3e1f8a51218827168cdclaireho#endif
22745569331642446be05292e3e1f8a51218827168cdclaireho
22755569331642446be05292e3e1f8a51218827168cdclaireho  if ( i > buffer->in_pos )
22765569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
22775569331642446be05292e3e1f8a51218827168cdclaireho
22785569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Coverage_Index( &mbp->BaseCoverage, IN_GLYPH( j ),
22795569331642446be05292e3e1f8a51218827168cdclaireho			  &base_index );
22805569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
22815569331642446be05292e3e1f8a51218827168cdclaireho    return error;
22825569331642446be05292e3e1f8a51218827168cdclaireho
22835569331642446be05292e3e1f8a51218827168cdclaireho  ma = &mbp->MarkArray;
22845569331642446be05292e3e1f8a51218827168cdclaireho
22855569331642446be05292e3e1f8a51218827168cdclaireho  if ( mark_index >= ma->MarkCount )
22865569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable);
22875569331642446be05292e3e1f8a51218827168cdclaireho
22885569331642446be05292e3e1f8a51218827168cdclaireho  class       = ma->MarkRecord[mark_index].Class;
22895569331642446be05292e3e1f8a51218827168cdclaireho  mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor;
22905569331642446be05292e3e1f8a51218827168cdclaireho
22915569331642446be05292e3e1f8a51218827168cdclaireho  if ( class >= mbp->ClassCount )
22925569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable);
22935569331642446be05292e3e1f8a51218827168cdclaireho
22945569331642446be05292e3e1f8a51218827168cdclaireho  ba = &mbp->BaseArray;
22955569331642446be05292e3e1f8a51218827168cdclaireho
22965569331642446be05292e3e1f8a51218827168cdclaireho  if ( base_index >= ba->BaseCount )
22975569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable);
22985569331642446be05292e3e1f8a51218827168cdclaireho
22995569331642446be05292e3e1f8a51218827168cdclaireho  br          = &ba->BaseRecord[base_index];
23005569331642446be05292e3e1f8a51218827168cdclaireho  base_anchor = &br->BaseAnchor[class];
23015569331642446be05292e3e1f8a51218827168cdclaireho
23025569331642446be05292e3e1f8a51218827168cdclaireho  error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH(),
23035569331642446be05292e3e1f8a51218827168cdclaireho		      &x_mark_value, &y_mark_value );
23045569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
23055569331642446be05292e3e1f8a51218827168cdclaireho    return error;
23065569331642446be05292e3e1f8a51218827168cdclaireho
23075569331642446be05292e3e1f8a51218827168cdclaireho  error = Get_Anchor( gpi, base_anchor, IN_GLYPH( j ),
23085569331642446be05292e3e1f8a51218827168cdclaireho		      &x_base_value, &y_base_value );
23095569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
23105569331642446be05292e3e1f8a51218827168cdclaireho    return error;
23115569331642446be05292e3e1f8a51218827168cdclaireho
23125569331642446be05292e3e1f8a51218827168cdclaireho  /* anchor points are not cumulative */
23135569331642446be05292e3e1f8a51218827168cdclaireho
23145569331642446be05292e3e1f8a51218827168cdclaireho  o = POSITION( buffer->in_pos );
23155569331642446be05292e3e1f8a51218827168cdclaireho
23165569331642446be05292e3e1f8a51218827168cdclaireho  o->x_pos     = x_base_value - x_mark_value;
23175569331642446be05292e3e1f8a51218827168cdclaireho  o->y_pos     = y_base_value - y_mark_value;
23185569331642446be05292e3e1f8a51218827168cdclaireho  o->x_advance = 0;
23195569331642446be05292e3e1f8a51218827168cdclaireho  o->y_advance = 0;
23205569331642446be05292e3e1f8a51218827168cdclaireho  o->back      = i;
23215569331642446be05292e3e1f8a51218827168cdclaireho
23225569331642446be05292e3e1f8a51218827168cdclaireho  (buffer->in_pos)++;
23235569331642446be05292e3e1f8a51218827168cdclaireho
23245569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
23255569331642446be05292e3e1f8a51218827168cdclaireho}
23265569331642446be05292e3e1f8a51218827168cdclaireho
23275569331642446be05292e3e1f8a51218827168cdclaireho
23285569331642446be05292e3e1f8a51218827168cdclaireho/* LookupType 5 */
23295569331642446be05292e3e1f8a51218827168cdclaireho
23305569331642446be05292e3e1f8a51218827168cdclaireho/* LigatureAttach */
23315569331642446be05292e3e1f8a51218827168cdclaireho
23325569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_LigatureAttach( HB_LigatureAttach*  lat,
23335569331642446be05292e3e1f8a51218827168cdclaireho				      HB_UShort            num_classes,
23345569331642446be05292e3e1f8a51218827168cdclaireho				      HB_Stream            stream )
23355569331642446be05292e3e1f8a51218827168cdclaireho{
23365569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
23375569331642446be05292e3e1f8a51218827168cdclaireho
23385569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort             m, n, k, count;
23395569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt              cur_offset, new_offset, base_offset;
23405569331642446be05292e3e1f8a51218827168cdclaireho
23415569331642446be05292e3e1f8a51218827168cdclaireho  HB_ComponentRecord*  cr;
23425569331642446be05292e3e1f8a51218827168cdclaireho  HB_Anchor*           lan;
23435569331642446be05292e3e1f8a51218827168cdclaireho
23445569331642446be05292e3e1f8a51218827168cdclaireho
23455569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
23465569331642446be05292e3e1f8a51218827168cdclaireho
23475569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
23485569331642446be05292e3e1f8a51218827168cdclaireho    return error;
23495569331642446be05292e3e1f8a51218827168cdclaireho
23505569331642446be05292e3e1f8a51218827168cdclaireho  count = lat->ComponentCount = GET_UShort();
23515569331642446be05292e3e1f8a51218827168cdclaireho
23525569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
23535569331642446be05292e3e1f8a51218827168cdclaireho
23545569331642446be05292e3e1f8a51218827168cdclaireho  lat->ComponentRecord = NULL;
23555569331642446be05292e3e1f8a51218827168cdclaireho
23565569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( lat->ComponentRecord, count, HB_ComponentRecord ) )
23575569331642446be05292e3e1f8a51218827168cdclaireho    return error;
23585569331642446be05292e3e1f8a51218827168cdclaireho
23595569331642446be05292e3e1f8a51218827168cdclaireho  cr = lat->ComponentRecord;
23605569331642446be05292e3e1f8a51218827168cdclaireho
23615569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < count; m++ )
23625569331642446be05292e3e1f8a51218827168cdclaireho  {
23635569331642446be05292e3e1f8a51218827168cdclaireho    cr[m].LigatureAnchor = NULL;
23645569331642446be05292e3e1f8a51218827168cdclaireho
23655569331642446be05292e3e1f8a51218827168cdclaireho    if ( ALLOC_ARRAY( cr[m].LigatureAnchor, num_classes, HB_Anchor ) )
23665569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
23675569331642446be05292e3e1f8a51218827168cdclaireho
23685569331642446be05292e3e1f8a51218827168cdclaireho    lan = cr[m].LigatureAnchor;
23695569331642446be05292e3e1f8a51218827168cdclaireho
23705569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < num_classes; n++ )
23715569331642446be05292e3e1f8a51218827168cdclaireho    {
23725569331642446be05292e3e1f8a51218827168cdclaireho      if ( ACCESS_Frame( 2L ) )
23735569331642446be05292e3e1f8a51218827168cdclaireho	goto Fail0;
23745569331642446be05292e3e1f8a51218827168cdclaireho
23755569331642446be05292e3e1f8a51218827168cdclaireho      new_offset = GET_UShort();
23765569331642446be05292e3e1f8a51218827168cdclaireho
23775569331642446be05292e3e1f8a51218827168cdclaireho      FORGET_Frame();
23785569331642446be05292e3e1f8a51218827168cdclaireho
23795569331642446be05292e3e1f8a51218827168cdclaireho      if ( new_offset )
23805569331642446be05292e3e1f8a51218827168cdclaireho      {
23815569331642446be05292e3e1f8a51218827168cdclaireho	new_offset += base_offset;
23825569331642446be05292e3e1f8a51218827168cdclaireho
23835569331642446be05292e3e1f8a51218827168cdclaireho	cur_offset = FILE_Pos();
23845569331642446be05292e3e1f8a51218827168cdclaireho	if ( FILE_Seek( new_offset ) ||
23855569331642446be05292e3e1f8a51218827168cdclaireho	     ( error = Load_Anchor( &lan[n], stream ) ) != HB_Err_Ok )
23865569331642446be05292e3e1f8a51218827168cdclaireho	  goto Fail0;
23875569331642446be05292e3e1f8a51218827168cdclaireho	(void)FILE_Seek( cur_offset );
23885569331642446be05292e3e1f8a51218827168cdclaireho      }
23895569331642446be05292e3e1f8a51218827168cdclaireho      else
23905569331642446be05292e3e1f8a51218827168cdclaireho	lan[n].PosFormat = 0;
23915569331642446be05292e3e1f8a51218827168cdclaireho    }
23925569331642446be05292e3e1f8a51218827168cdclaireho
23935569331642446be05292e3e1f8a51218827168cdclaireho    continue;
23945569331642446be05292e3e1f8a51218827168cdclaireho  Fail0:
23955569331642446be05292e3e1f8a51218827168cdclaireho    for ( k = 0; k < n; k++ )
23965569331642446be05292e3e1f8a51218827168cdclaireho      Free_Anchor( &lan[k] );
23975569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail;
23985569331642446be05292e3e1f8a51218827168cdclaireho  }
23995569331642446be05292e3e1f8a51218827168cdclaireho
24005569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
24015569331642446be05292e3e1f8a51218827168cdclaireho
24025569331642446be05292e3e1f8a51218827168cdclairehoFail:
24035569331642446be05292e3e1f8a51218827168cdclaireho  for ( k = 0; k < m; k++ )
24045569331642446be05292e3e1f8a51218827168cdclaireho  {
24055569331642446be05292e3e1f8a51218827168cdclaireho    lan = cr[k].LigatureAnchor;
24065569331642446be05292e3e1f8a51218827168cdclaireho
24075569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < num_classes; n++ )
24085569331642446be05292e3e1f8a51218827168cdclaireho      Free_Anchor( &lan[n] );
24095569331642446be05292e3e1f8a51218827168cdclaireho
24105569331642446be05292e3e1f8a51218827168cdclaireho    FREE( lan );
24115569331642446be05292e3e1f8a51218827168cdclaireho  }
24125569331642446be05292e3e1f8a51218827168cdclaireho
24135569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cr );
24145569331642446be05292e3e1f8a51218827168cdclaireho  return error;
24155569331642446be05292e3e1f8a51218827168cdclaireho}
24165569331642446be05292e3e1f8a51218827168cdclaireho
24175569331642446be05292e3e1f8a51218827168cdclaireho
24185569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_LigatureAttach( HB_LigatureAttach*  lat,
24195569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort            num_classes )
24205569331642446be05292e3e1f8a51218827168cdclaireho{
24215569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        m, n, count;
24225569331642446be05292e3e1f8a51218827168cdclaireho
24235569331642446be05292e3e1f8a51218827168cdclaireho  HB_ComponentRecord*  cr;
24245569331642446be05292e3e1f8a51218827168cdclaireho  HB_Anchor*           lan;
24255569331642446be05292e3e1f8a51218827168cdclaireho
24265569331642446be05292e3e1f8a51218827168cdclaireho
24275569331642446be05292e3e1f8a51218827168cdclaireho  if ( lat->ComponentRecord )
24285569331642446be05292e3e1f8a51218827168cdclaireho  {
24295569331642446be05292e3e1f8a51218827168cdclaireho    count = lat->ComponentCount;
24305569331642446be05292e3e1f8a51218827168cdclaireho    cr    = lat->ComponentRecord;
24315569331642446be05292e3e1f8a51218827168cdclaireho
24325569331642446be05292e3e1f8a51218827168cdclaireho    for ( m = 0; m < count; m++ )
24335569331642446be05292e3e1f8a51218827168cdclaireho    {
24345569331642446be05292e3e1f8a51218827168cdclaireho      lan = cr[m].LigatureAnchor;
24355569331642446be05292e3e1f8a51218827168cdclaireho
24365569331642446be05292e3e1f8a51218827168cdclaireho      for ( n = 0; n < num_classes; n++ )
24375569331642446be05292e3e1f8a51218827168cdclaireho	Free_Anchor( &lan[n] );
24385569331642446be05292e3e1f8a51218827168cdclaireho
24395569331642446be05292e3e1f8a51218827168cdclaireho      FREE( lan );
24405569331642446be05292e3e1f8a51218827168cdclaireho    }
24415569331642446be05292e3e1f8a51218827168cdclaireho
24425569331642446be05292e3e1f8a51218827168cdclaireho    FREE( cr );
24435569331642446be05292e3e1f8a51218827168cdclaireho  }
24445569331642446be05292e3e1f8a51218827168cdclaireho}
24455569331642446be05292e3e1f8a51218827168cdclaireho
24465569331642446be05292e3e1f8a51218827168cdclaireho
24475569331642446be05292e3e1f8a51218827168cdclaireho/* LigatureArray */
24485569331642446be05292e3e1f8a51218827168cdclaireho
24495569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_LigatureArray( HB_LigatureArray*  la,
24505569331642446be05292e3e1f8a51218827168cdclaireho				     HB_UShort           num_classes,
24515569331642446be05292e3e1f8a51218827168cdclaireho				     HB_Stream           stream )
24525569331642446be05292e3e1f8a51218827168cdclaireho{
24535569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
24545569331642446be05292e3e1f8a51218827168cdclaireho
24555569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort            n, m, count;
24565569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt             cur_offset, new_offset, base_offset;
24575569331642446be05292e3e1f8a51218827168cdclaireho
24585569331642446be05292e3e1f8a51218827168cdclaireho  HB_LigatureAttach*  lat;
24595569331642446be05292e3e1f8a51218827168cdclaireho
24605569331642446be05292e3e1f8a51218827168cdclaireho
24615569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
24625569331642446be05292e3e1f8a51218827168cdclaireho
24635569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
24645569331642446be05292e3e1f8a51218827168cdclaireho    return error;
24655569331642446be05292e3e1f8a51218827168cdclaireho
24665569331642446be05292e3e1f8a51218827168cdclaireho  count = la->LigatureCount = GET_UShort();
24675569331642446be05292e3e1f8a51218827168cdclaireho
24685569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
24695569331642446be05292e3e1f8a51218827168cdclaireho
24705569331642446be05292e3e1f8a51218827168cdclaireho  la->LigatureAttach = NULL;
24715569331642446be05292e3e1f8a51218827168cdclaireho
24725569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( la->LigatureAttach, count, HB_LigatureAttach ) )
24735569331642446be05292e3e1f8a51218827168cdclaireho    return error;
24745569331642446be05292e3e1f8a51218827168cdclaireho
24755569331642446be05292e3e1f8a51218827168cdclaireho  lat = la->LigatureAttach;
24765569331642446be05292e3e1f8a51218827168cdclaireho
24775569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
24785569331642446be05292e3e1f8a51218827168cdclaireho  {
24795569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
24805569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
24815569331642446be05292e3e1f8a51218827168cdclaireho
24825569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
24835569331642446be05292e3e1f8a51218827168cdclaireho
24845569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
24855569331642446be05292e3e1f8a51218827168cdclaireho
24865569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
24875569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
24885569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_LigatureAttach( &lat[n], num_classes,
24895569331642446be05292e3e1f8a51218827168cdclaireho					stream ) ) != HB_Err_Ok )
24905569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
24915569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
24925569331642446be05292e3e1f8a51218827168cdclaireho  }
24935569331642446be05292e3e1f8a51218827168cdclaireho
24945569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
24955569331642446be05292e3e1f8a51218827168cdclaireho
24965569331642446be05292e3e1f8a51218827168cdclairehoFail:
24975569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
24985569331642446be05292e3e1f8a51218827168cdclaireho    Free_LigatureAttach( &lat[m], num_classes );
24995569331642446be05292e3e1f8a51218827168cdclaireho
25005569331642446be05292e3e1f8a51218827168cdclaireho  FREE( lat );
25015569331642446be05292e3e1f8a51218827168cdclaireho  return error;
25025569331642446be05292e3e1f8a51218827168cdclaireho}
25035569331642446be05292e3e1f8a51218827168cdclaireho
25045569331642446be05292e3e1f8a51218827168cdclaireho
25055569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_LigatureArray( HB_LigatureArray*  la,
25065569331642446be05292e3e1f8a51218827168cdclaireho				 HB_UShort           num_classes )
25075569331642446be05292e3e1f8a51218827168cdclaireho{
25085569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort            n, count;
25095569331642446be05292e3e1f8a51218827168cdclaireho
25105569331642446be05292e3e1f8a51218827168cdclaireho  HB_LigatureAttach*  lat;
25115569331642446be05292e3e1f8a51218827168cdclaireho
25125569331642446be05292e3e1f8a51218827168cdclaireho
25135569331642446be05292e3e1f8a51218827168cdclaireho  if ( la->LigatureAttach )
25145569331642446be05292e3e1f8a51218827168cdclaireho  {
25155569331642446be05292e3e1f8a51218827168cdclaireho    count = la->LigatureCount;
25165569331642446be05292e3e1f8a51218827168cdclaireho    lat   = la->LigatureAttach;
25175569331642446be05292e3e1f8a51218827168cdclaireho
25185569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
25195569331642446be05292e3e1f8a51218827168cdclaireho      Free_LigatureAttach( &lat[n], num_classes );
25205569331642446be05292e3e1f8a51218827168cdclaireho
25215569331642446be05292e3e1f8a51218827168cdclaireho    FREE( lat );
25225569331642446be05292e3e1f8a51218827168cdclaireho  }
25235569331642446be05292e3e1f8a51218827168cdclaireho}
25245569331642446be05292e3e1f8a51218827168cdclaireho
25255569331642446be05292e3e1f8a51218827168cdclaireho
25265569331642446be05292e3e1f8a51218827168cdclaireho/* MarkLigPosFormat1 */
25275569331642446be05292e3e1f8a51218827168cdclaireho
25285569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_MarkLigPos( HB_GPOS_SubTable* st,
25295569331642446be05292e3e1f8a51218827168cdclaireho				  HB_Stream        stream )
25305569331642446be05292e3e1f8a51218827168cdclaireho{
25315569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
25325569331642446be05292e3e1f8a51218827168cdclaireho  HB_MarkLigPos*  mlp = &st->marklig;
25335569331642446be05292e3e1f8a51218827168cdclaireho
25345569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt  cur_offset, new_offset, base_offset;
25355569331642446be05292e3e1f8a51218827168cdclaireho
25365569331642446be05292e3e1f8a51218827168cdclaireho
25375569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
25385569331642446be05292e3e1f8a51218827168cdclaireho
25395569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 4L ) )
25405569331642446be05292e3e1f8a51218827168cdclaireho    return error;
25415569331642446be05292e3e1f8a51218827168cdclaireho
25425569331642446be05292e3e1f8a51218827168cdclaireho  mlp->PosFormat = GET_UShort();
25435569331642446be05292e3e1f8a51218827168cdclaireho  new_offset     = GET_UShort() + base_offset;
25445569331642446be05292e3e1f8a51218827168cdclaireho
25455569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
25465569331642446be05292e3e1f8a51218827168cdclaireho
25475569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
25485569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
25495569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_Coverage( &mlp->MarkCoverage, stream ) ) != HB_Err_Ok )
25505569331642446be05292e3e1f8a51218827168cdclaireho    return error;
25515569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
25525569331642446be05292e3e1f8a51218827168cdclaireho
25535569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
25545569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
25555569331642446be05292e3e1f8a51218827168cdclaireho
25565569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
25575569331642446be05292e3e1f8a51218827168cdclaireho
25585569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
25595569331642446be05292e3e1f8a51218827168cdclaireho
25605569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
25615569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
25625569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_Coverage( &mlp->LigatureCoverage,
25635569331642446be05292e3e1f8a51218827168cdclaireho				stream ) ) != HB_Err_Ok )
25645569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
25655569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
25665569331642446be05292e3e1f8a51218827168cdclaireho
25675569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 4L ) )
25685569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
25695569331642446be05292e3e1f8a51218827168cdclaireho
25705569331642446be05292e3e1f8a51218827168cdclaireho  mlp->ClassCount = GET_UShort();
25715569331642446be05292e3e1f8a51218827168cdclaireho  new_offset      = GET_UShort() + base_offset;
25725569331642446be05292e3e1f8a51218827168cdclaireho
25735569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
25745569331642446be05292e3e1f8a51218827168cdclaireho
25755569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
25765569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
25775569331642446be05292e3e1f8a51218827168cdclaireho       ( error = Load_MarkArray( &mlp->MarkArray, stream ) ) != HB_Err_Ok )
25785569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
25795569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
25805569331642446be05292e3e1f8a51218827168cdclaireho
25815569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
25825569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail1;
25835569331642446be05292e3e1f8a51218827168cdclaireho
25845569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
25855569331642446be05292e3e1f8a51218827168cdclaireho
25865569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
25875569331642446be05292e3e1f8a51218827168cdclaireho
25885569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
25895569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
25905569331642446be05292e3e1f8a51218827168cdclaireho       ( error = Load_LigatureArray( &mlp->LigatureArray, mlp->ClassCount,
25915569331642446be05292e3e1f8a51218827168cdclaireho				     stream ) ) != HB_Err_Ok )
25925569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail1;
25935569331642446be05292e3e1f8a51218827168cdclaireho
25945569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
25955569331642446be05292e3e1f8a51218827168cdclaireho
25965569331642446be05292e3e1f8a51218827168cdclairehoFail1:
25975569331642446be05292e3e1f8a51218827168cdclaireho  Free_MarkArray( &mlp->MarkArray );
25985569331642446be05292e3e1f8a51218827168cdclaireho
25995569331642446be05292e3e1f8a51218827168cdclairehoFail2:
26005569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &mlp->LigatureCoverage );
26015569331642446be05292e3e1f8a51218827168cdclaireho
26025569331642446be05292e3e1f8a51218827168cdclairehoFail3:
26035569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &mlp->MarkCoverage );
26045569331642446be05292e3e1f8a51218827168cdclaireho  return error;
26055569331642446be05292e3e1f8a51218827168cdclaireho}
26065569331642446be05292e3e1f8a51218827168cdclaireho
26075569331642446be05292e3e1f8a51218827168cdclaireho
26085569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_MarkLigPos( HB_GPOS_SubTable* st)
26095569331642446be05292e3e1f8a51218827168cdclaireho{
26105569331642446be05292e3e1f8a51218827168cdclaireho  HB_MarkLigPos*  mlp = &st->marklig;
26115569331642446be05292e3e1f8a51218827168cdclaireho
26125569331642446be05292e3e1f8a51218827168cdclaireho  Free_LigatureArray( &mlp->LigatureArray, mlp->ClassCount );
26135569331642446be05292e3e1f8a51218827168cdclaireho  Free_MarkArray( &mlp->MarkArray );
26145569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &mlp->LigatureCoverage );
26155569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &mlp->MarkCoverage );
26165569331642446be05292e3e1f8a51218827168cdclaireho}
26175569331642446be05292e3e1f8a51218827168cdclaireho
26185569331642446be05292e3e1f8a51218827168cdclaireho
26195569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_MarkLigPos( GPOS_Instance*    gpi,
26205569331642446be05292e3e1f8a51218827168cdclaireho				    HB_GPOS_SubTable* st,
26215569331642446be05292e3e1f8a51218827168cdclaireho				    HB_Buffer        buffer,
26225569331642446be05292e3e1f8a51218827168cdclaireho				    HB_UShort         flags,
26235569331642446be05292e3e1f8a51218827168cdclaireho				    HB_UShort         context_length,
26245569331642446be05292e3e1f8a51218827168cdclaireho				    int               nesting_level )
26255569331642446be05292e3e1f8a51218827168cdclaireho{
26265569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        i, j, mark_index, lig_index, property, class;
26275569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        mark_glyph;
26285569331642446be05292e3e1f8a51218827168cdclaireho  HB_Fixed           x_mark_value, y_mark_value, x_lig_value, y_lig_value;
26295569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error         error;
26305569331642446be05292e3e1f8a51218827168cdclaireho  HB_GPOSHeader*  gpos = gpi->gpos;
26315569331642446be05292e3e1f8a51218827168cdclaireho  HB_MarkLigPos*  mlp = &st->marklig;
26325569331642446be05292e3e1f8a51218827168cdclaireho
26335569331642446be05292e3e1f8a51218827168cdclaireho  HB_MarkArray*        ma;
26345569331642446be05292e3e1f8a51218827168cdclaireho  HB_LigatureArray*    la;
26355569331642446be05292e3e1f8a51218827168cdclaireho  HB_LigatureAttach*   lat;
26365569331642446be05292e3e1f8a51218827168cdclaireho  HB_ComponentRecord*  cr;
26375569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort             comp_index;
26385569331642446be05292e3e1f8a51218827168cdclaireho  HB_Anchor*           mark_anchor;
26395569331642446be05292e3e1f8a51218827168cdclaireho  HB_Anchor*           lig_anchor;
26405569331642446be05292e3e1f8a51218827168cdclaireho
26415569331642446be05292e3e1f8a51218827168cdclaireho  HB_Position    o;
26425569331642446be05292e3e1f8a51218827168cdclaireho
26435569331642446be05292e3e1f8a51218827168cdclaireho  HB_UNUSED(nesting_level);
26445569331642446be05292e3e1f8a51218827168cdclaireho
26455569331642446be05292e3e1f8a51218827168cdclaireho  if ( context_length != 0xFFFF && context_length < 1 )
26465569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
26475569331642446be05292e3e1f8a51218827168cdclaireho
26485569331642446be05292e3e1f8a51218827168cdclaireho  if ( flags & HB_LOOKUP_FLAG_IGNORE_LIGATURES )
26495569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
26505569331642446be05292e3e1f8a51218827168cdclaireho
26515569331642446be05292e3e1f8a51218827168cdclaireho  mark_glyph = IN_CURGLYPH();
26525569331642446be05292e3e1f8a51218827168cdclaireho
26535569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
26545569331642446be05292e3e1f8a51218827168cdclaireho    return error;
26555569331642446be05292e3e1f8a51218827168cdclaireho
26565569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Coverage_Index( &mlp->MarkCoverage, mark_glyph, &mark_index );
26575569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
26585569331642446be05292e3e1f8a51218827168cdclaireho    return error;
26595569331642446be05292e3e1f8a51218827168cdclaireho
26605569331642446be05292e3e1f8a51218827168cdclaireho  /* now we search backwards for a non-mark glyph */
26615569331642446be05292e3e1f8a51218827168cdclaireho
26625569331642446be05292e3e1f8a51218827168cdclaireho  i = 1;
26635569331642446be05292e3e1f8a51218827168cdclaireho  j = buffer->in_pos - 1;
26645569331642446be05292e3e1f8a51218827168cdclaireho
26655569331642446be05292e3e1f8a51218827168cdclaireho  while ( i <= buffer->in_pos )
26665569331642446be05292e3e1f8a51218827168cdclaireho  {
26675569331642446be05292e3e1f8a51218827168cdclaireho    error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
26685569331642446be05292e3e1f8a51218827168cdclaireho					&property );
26695569331642446be05292e3e1f8a51218827168cdclaireho    if ( error )
26705569331642446be05292e3e1f8a51218827168cdclaireho      return error;
26715569331642446be05292e3e1f8a51218827168cdclaireho
26725569331642446be05292e3e1f8a51218827168cdclaireho    if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
26735569331642446be05292e3e1f8a51218827168cdclaireho      break;
26745569331642446be05292e3e1f8a51218827168cdclaireho
26755569331642446be05292e3e1f8a51218827168cdclaireho    i++;
26765569331642446be05292e3e1f8a51218827168cdclaireho    j--;
26775569331642446be05292e3e1f8a51218827168cdclaireho  }
26785569331642446be05292e3e1f8a51218827168cdclaireho
26795569331642446be05292e3e1f8a51218827168cdclaireho  /* Similar to Lookup_MarkBasePos(), I suspect that this assertion is
26805569331642446be05292e3e1f8a51218827168cdclaireho     too strong, thus it is commented out.                             */
26815569331642446be05292e3e1f8a51218827168cdclaireho#if 0
26825569331642446be05292e3e1f8a51218827168cdclaireho  if ( property != HB_GDEF_LIGATURE )
26835569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
26845569331642446be05292e3e1f8a51218827168cdclaireho#endif
26855569331642446be05292e3e1f8a51218827168cdclaireho
26865569331642446be05292e3e1f8a51218827168cdclaireho  if ( i > buffer->in_pos )
26875569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
26885569331642446be05292e3e1f8a51218827168cdclaireho
26895569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Coverage_Index( &mlp->LigatureCoverage, IN_GLYPH( j ),
26905569331642446be05292e3e1f8a51218827168cdclaireho			  &lig_index );
26915569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
26925569331642446be05292e3e1f8a51218827168cdclaireho    return error;
26935569331642446be05292e3e1f8a51218827168cdclaireho
26945569331642446be05292e3e1f8a51218827168cdclaireho  ma = &mlp->MarkArray;
26955569331642446be05292e3e1f8a51218827168cdclaireho
26965569331642446be05292e3e1f8a51218827168cdclaireho  if ( mark_index >= ma->MarkCount )
26975569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable);
26985569331642446be05292e3e1f8a51218827168cdclaireho
26995569331642446be05292e3e1f8a51218827168cdclaireho  class       = ma->MarkRecord[mark_index].Class;
27005569331642446be05292e3e1f8a51218827168cdclaireho  mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor;
27015569331642446be05292e3e1f8a51218827168cdclaireho
27025569331642446be05292e3e1f8a51218827168cdclaireho  if ( class >= mlp->ClassCount )
27035569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable);
27045569331642446be05292e3e1f8a51218827168cdclaireho
27055569331642446be05292e3e1f8a51218827168cdclaireho  la = &mlp->LigatureArray;
27065569331642446be05292e3e1f8a51218827168cdclaireho
27075569331642446be05292e3e1f8a51218827168cdclaireho  if ( lig_index >= la->LigatureCount )
27085569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable);
27095569331642446be05292e3e1f8a51218827168cdclaireho
27105569331642446be05292e3e1f8a51218827168cdclaireho  lat = &la->LigatureAttach[lig_index];
27115569331642446be05292e3e1f8a51218827168cdclaireho
27125569331642446be05292e3e1f8a51218827168cdclaireho  /* We must now check whether the ligature ID of the current mark glyph
27135569331642446be05292e3e1f8a51218827168cdclaireho     is identical to the ligature ID of the found ligature.  If yes, we
27145569331642446be05292e3e1f8a51218827168cdclaireho     can directly use the component index.  If not, we attach the mark
27155569331642446be05292e3e1f8a51218827168cdclaireho     glyph to the last component of the ligature.                        */
27165569331642446be05292e3e1f8a51218827168cdclaireho
27175569331642446be05292e3e1f8a51218827168cdclaireho  if ( IN_LIGID( j ) == IN_LIGID( buffer->in_pos) )
27185569331642446be05292e3e1f8a51218827168cdclaireho  {
27195569331642446be05292e3e1f8a51218827168cdclaireho    comp_index = IN_COMPONENT( buffer->in_pos );
27205569331642446be05292e3e1f8a51218827168cdclaireho    if ( comp_index >= lat->ComponentCount )
27215569331642446be05292e3e1f8a51218827168cdclaireho      return HB_Err_Not_Covered;
27225569331642446be05292e3e1f8a51218827168cdclaireho  }
27235569331642446be05292e3e1f8a51218827168cdclaireho  else
27245569331642446be05292e3e1f8a51218827168cdclaireho    comp_index = lat->ComponentCount - 1;
27255569331642446be05292e3e1f8a51218827168cdclaireho
27265569331642446be05292e3e1f8a51218827168cdclaireho  cr         = &lat->ComponentRecord[comp_index];
27275569331642446be05292e3e1f8a51218827168cdclaireho  lig_anchor = &cr->LigatureAnchor[class];
27285569331642446be05292e3e1f8a51218827168cdclaireho
27295569331642446be05292e3e1f8a51218827168cdclaireho  error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH(),
27305569331642446be05292e3e1f8a51218827168cdclaireho		      &x_mark_value, &y_mark_value );
27315569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
27325569331642446be05292e3e1f8a51218827168cdclaireho    return error;
27335569331642446be05292e3e1f8a51218827168cdclaireho  error = Get_Anchor( gpi, lig_anchor, IN_GLYPH( j ),
27345569331642446be05292e3e1f8a51218827168cdclaireho		      &x_lig_value, &y_lig_value );
27355569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
27365569331642446be05292e3e1f8a51218827168cdclaireho    return error;
27375569331642446be05292e3e1f8a51218827168cdclaireho
27385569331642446be05292e3e1f8a51218827168cdclaireho  /* anchor points are not cumulative */
27395569331642446be05292e3e1f8a51218827168cdclaireho
27405569331642446be05292e3e1f8a51218827168cdclaireho  o = POSITION( buffer->in_pos );
27415569331642446be05292e3e1f8a51218827168cdclaireho
27425569331642446be05292e3e1f8a51218827168cdclaireho  o->x_pos     = x_lig_value - x_mark_value;
27435569331642446be05292e3e1f8a51218827168cdclaireho  o->y_pos     = y_lig_value - y_mark_value;
27445569331642446be05292e3e1f8a51218827168cdclaireho  o->x_advance = 0;
27455569331642446be05292e3e1f8a51218827168cdclaireho  o->y_advance = 0;
27465569331642446be05292e3e1f8a51218827168cdclaireho  o->back      = i;
27475569331642446be05292e3e1f8a51218827168cdclaireho
27485569331642446be05292e3e1f8a51218827168cdclaireho  (buffer->in_pos)++;
27495569331642446be05292e3e1f8a51218827168cdclaireho
27505569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
27515569331642446be05292e3e1f8a51218827168cdclaireho}
27525569331642446be05292e3e1f8a51218827168cdclaireho
27535569331642446be05292e3e1f8a51218827168cdclaireho
27545569331642446be05292e3e1f8a51218827168cdclaireho/* LookupType 6 */
27555569331642446be05292e3e1f8a51218827168cdclaireho
27565569331642446be05292e3e1f8a51218827168cdclaireho/* Mark2Array */
27575569331642446be05292e3e1f8a51218827168cdclaireho
27585569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_Mark2Array( HB_Mark2Array*  m2a,
27595569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort        num_classes,
27605569331642446be05292e3e1f8a51218827168cdclaireho				  HB_Stream        stream )
27615569331642446be05292e3e1f8a51218827168cdclaireho{
27625569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
27635569331642446be05292e3e1f8a51218827168cdclaireho
27645569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        m, n, count;
27655569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt          cur_offset, new_offset, base_offset;
27665569331642446be05292e3e1f8a51218827168cdclaireho
27675569331642446be05292e3e1f8a51218827168cdclaireho  HB_Mark2Record  *m2r;
27685569331642446be05292e3e1f8a51218827168cdclaireho  HB_Anchor       *m2an, *m2ans;
27695569331642446be05292e3e1f8a51218827168cdclaireho
27705569331642446be05292e3e1f8a51218827168cdclaireho
27715569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
27725569331642446be05292e3e1f8a51218827168cdclaireho
27735569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
27745569331642446be05292e3e1f8a51218827168cdclaireho    return error;
27755569331642446be05292e3e1f8a51218827168cdclaireho
27765569331642446be05292e3e1f8a51218827168cdclaireho  count = m2a->Mark2Count = GET_UShort();
27775569331642446be05292e3e1f8a51218827168cdclaireho
27785569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
27795569331642446be05292e3e1f8a51218827168cdclaireho
27805569331642446be05292e3e1f8a51218827168cdclaireho  m2a->Mark2Record = NULL;
27815569331642446be05292e3e1f8a51218827168cdclaireho
27825569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( m2a->Mark2Record, count, HB_Mark2Record ) )
27835569331642446be05292e3e1f8a51218827168cdclaireho    return error;
27845569331642446be05292e3e1f8a51218827168cdclaireho
27855569331642446be05292e3e1f8a51218827168cdclaireho  m2r = m2a->Mark2Record;
27865569331642446be05292e3e1f8a51218827168cdclaireho
27875569331642446be05292e3e1f8a51218827168cdclaireho  m2ans = NULL;
27885569331642446be05292e3e1f8a51218827168cdclaireho
27895569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( m2ans, count * num_classes, HB_Anchor ) )
27905569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail;
27915569331642446be05292e3e1f8a51218827168cdclaireho
27925569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < count; m++ )
27935569331642446be05292e3e1f8a51218827168cdclaireho  {
27945569331642446be05292e3e1f8a51218827168cdclaireho    m2an = m2r[m].Mark2Anchor = m2ans + m * num_classes;
27955569331642446be05292e3e1f8a51218827168cdclaireho
27965569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < num_classes; n++ )
27975569331642446be05292e3e1f8a51218827168cdclaireho    {
27985569331642446be05292e3e1f8a51218827168cdclaireho      if ( ACCESS_Frame( 2L ) )
27995569331642446be05292e3e1f8a51218827168cdclaireho	goto Fail;
28005569331642446be05292e3e1f8a51218827168cdclaireho
28015569331642446be05292e3e1f8a51218827168cdclaireho      new_offset = GET_UShort() + base_offset;
28025569331642446be05292e3e1f8a51218827168cdclaireho
28035569331642446be05292e3e1f8a51218827168cdclaireho      FORGET_Frame();
28045569331642446be05292e3e1f8a51218827168cdclaireho
28055569331642446be05292e3e1f8a51218827168cdclaireho      if (new_offset == base_offset) {
28065569331642446be05292e3e1f8a51218827168cdclaireho        /* Anchor table not provided.  Skip loading.
28075569331642446be05292e3e1f8a51218827168cdclaireho	 * Some versions of FreeSans hit this. */
28085569331642446be05292e3e1f8a51218827168cdclaireho        m2an[n].PosFormat = 0;
28095569331642446be05292e3e1f8a51218827168cdclaireho	continue;
28105569331642446be05292e3e1f8a51218827168cdclaireho      }
28115569331642446be05292e3e1f8a51218827168cdclaireho
28125569331642446be05292e3e1f8a51218827168cdclaireho      cur_offset = FILE_Pos();
28135569331642446be05292e3e1f8a51218827168cdclaireho      if ( FILE_Seek( new_offset ) ||
28145569331642446be05292e3e1f8a51218827168cdclaireho	   ( error = Load_Anchor( &m2an[n], stream ) ) != HB_Err_Ok )
28155569331642446be05292e3e1f8a51218827168cdclaireho	goto Fail;
28165569331642446be05292e3e1f8a51218827168cdclaireho      (void)FILE_Seek( cur_offset );
28175569331642446be05292e3e1f8a51218827168cdclaireho    }
28185569331642446be05292e3e1f8a51218827168cdclaireho  }
28195569331642446be05292e3e1f8a51218827168cdclaireho
28205569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
28215569331642446be05292e3e1f8a51218827168cdclaireho
28225569331642446be05292e3e1f8a51218827168cdclairehoFail:
28235569331642446be05292e3e1f8a51218827168cdclaireho  FREE( m2ans );
28245569331642446be05292e3e1f8a51218827168cdclaireho  FREE( m2r );
28255569331642446be05292e3e1f8a51218827168cdclaireho  return error;
28265569331642446be05292e3e1f8a51218827168cdclaireho}
28275569331642446be05292e3e1f8a51218827168cdclaireho
28285569331642446be05292e3e1f8a51218827168cdclaireho
28295569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_Mark2Array( HB_Mark2Array*  m2a,
28305569331642446be05292e3e1f8a51218827168cdclaireho			      HB_UShort        num_classes )
28315569331642446be05292e3e1f8a51218827168cdclaireho{
28325569331642446be05292e3e1f8a51218827168cdclaireho  HB_Mark2Record  *m2r;
28335569331642446be05292e3e1f8a51218827168cdclaireho  HB_Anchor       *m2ans;
28345569331642446be05292e3e1f8a51218827168cdclaireho
28355569331642446be05292e3e1f8a51218827168cdclaireho  HB_UNUSED(num_classes);
28365569331642446be05292e3e1f8a51218827168cdclaireho
28375569331642446be05292e3e1f8a51218827168cdclaireho  if ( m2a->Mark2Record )
28385569331642446be05292e3e1f8a51218827168cdclaireho  {
28395569331642446be05292e3e1f8a51218827168cdclaireho    m2r   = m2a->Mark2Record;
28405569331642446be05292e3e1f8a51218827168cdclaireho
28415569331642446be05292e3e1f8a51218827168cdclaireho    if ( m2a->Mark2Count )
28425569331642446be05292e3e1f8a51218827168cdclaireho    {
28435569331642446be05292e3e1f8a51218827168cdclaireho      m2ans = m2r[0].Mark2Anchor;
28445569331642446be05292e3e1f8a51218827168cdclaireho      FREE( m2ans );
28455569331642446be05292e3e1f8a51218827168cdclaireho    }
28465569331642446be05292e3e1f8a51218827168cdclaireho
28475569331642446be05292e3e1f8a51218827168cdclaireho    FREE( m2r );
28485569331642446be05292e3e1f8a51218827168cdclaireho  }
28495569331642446be05292e3e1f8a51218827168cdclaireho}
28505569331642446be05292e3e1f8a51218827168cdclaireho
28515569331642446be05292e3e1f8a51218827168cdclaireho
28525569331642446be05292e3e1f8a51218827168cdclaireho/* MarkMarkPosFormat1 */
28535569331642446be05292e3e1f8a51218827168cdclaireho
28545569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_MarkMarkPos( HB_GPOS_SubTable* st,
28555569331642446be05292e3e1f8a51218827168cdclaireho				   HB_Stream         stream )
28565569331642446be05292e3e1f8a51218827168cdclaireho{
28575569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
28585569331642446be05292e3e1f8a51218827168cdclaireho  HB_MarkMarkPos* mmp = &st->markmark;
28595569331642446be05292e3e1f8a51218827168cdclaireho
28605569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt  cur_offset, new_offset, base_offset;
28615569331642446be05292e3e1f8a51218827168cdclaireho
28625569331642446be05292e3e1f8a51218827168cdclaireho
28635569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
28645569331642446be05292e3e1f8a51218827168cdclaireho
28655569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 4L ) )
28665569331642446be05292e3e1f8a51218827168cdclaireho    return error;
28675569331642446be05292e3e1f8a51218827168cdclaireho
28685569331642446be05292e3e1f8a51218827168cdclaireho  mmp->PosFormat = GET_UShort();
28695569331642446be05292e3e1f8a51218827168cdclaireho  new_offset     = GET_UShort() + base_offset;
28705569331642446be05292e3e1f8a51218827168cdclaireho
28715569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
28725569331642446be05292e3e1f8a51218827168cdclaireho
28735569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
28745569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
28755569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_Coverage( &mmp->Mark1Coverage,
28765569331642446be05292e3e1f8a51218827168cdclaireho				stream ) ) != HB_Err_Ok )
28775569331642446be05292e3e1f8a51218827168cdclaireho    return error;
28785569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
28795569331642446be05292e3e1f8a51218827168cdclaireho
28805569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
28815569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
28825569331642446be05292e3e1f8a51218827168cdclaireho
28835569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
28845569331642446be05292e3e1f8a51218827168cdclaireho
28855569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
28865569331642446be05292e3e1f8a51218827168cdclaireho
28875569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
28885569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
28895569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_Coverage( &mmp->Mark2Coverage,
28905569331642446be05292e3e1f8a51218827168cdclaireho				stream ) ) != HB_Err_Ok )
28915569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
28925569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
28935569331642446be05292e3e1f8a51218827168cdclaireho
28945569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 4L ) )
28955569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
28965569331642446be05292e3e1f8a51218827168cdclaireho
28975569331642446be05292e3e1f8a51218827168cdclaireho  mmp->ClassCount = GET_UShort();
28985569331642446be05292e3e1f8a51218827168cdclaireho  new_offset      = GET_UShort() + base_offset;
28995569331642446be05292e3e1f8a51218827168cdclaireho
29005569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
29015569331642446be05292e3e1f8a51218827168cdclaireho
29025569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
29035569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
29045569331642446be05292e3e1f8a51218827168cdclaireho       ( error = Load_MarkArray( &mmp->Mark1Array, stream ) ) != HB_Err_Ok )
29055569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
29065569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
29075569331642446be05292e3e1f8a51218827168cdclaireho
29085569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
29095569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail1;
29105569331642446be05292e3e1f8a51218827168cdclaireho
29115569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
29125569331642446be05292e3e1f8a51218827168cdclaireho
29135569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
29145569331642446be05292e3e1f8a51218827168cdclaireho
29155569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
29165569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
29175569331642446be05292e3e1f8a51218827168cdclaireho       ( error = Load_Mark2Array( &mmp->Mark2Array, mmp->ClassCount,
29185569331642446be05292e3e1f8a51218827168cdclaireho				  stream ) ) != HB_Err_Ok )
29195569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail1;
29205569331642446be05292e3e1f8a51218827168cdclaireho
29215569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
29225569331642446be05292e3e1f8a51218827168cdclaireho
29235569331642446be05292e3e1f8a51218827168cdclairehoFail1:
29245569331642446be05292e3e1f8a51218827168cdclaireho  Free_MarkArray( &mmp->Mark1Array );
29255569331642446be05292e3e1f8a51218827168cdclaireho
29265569331642446be05292e3e1f8a51218827168cdclairehoFail2:
29275569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &mmp->Mark2Coverage );
29285569331642446be05292e3e1f8a51218827168cdclaireho
29295569331642446be05292e3e1f8a51218827168cdclairehoFail3:
29305569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &mmp->Mark1Coverage );
29315569331642446be05292e3e1f8a51218827168cdclaireho  return error;
29325569331642446be05292e3e1f8a51218827168cdclaireho}
29335569331642446be05292e3e1f8a51218827168cdclaireho
29345569331642446be05292e3e1f8a51218827168cdclaireho
29355569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_MarkMarkPos( HB_GPOS_SubTable* st)
29365569331642446be05292e3e1f8a51218827168cdclaireho{
29375569331642446be05292e3e1f8a51218827168cdclaireho  HB_MarkMarkPos* mmp = &st->markmark;
29385569331642446be05292e3e1f8a51218827168cdclaireho
29395569331642446be05292e3e1f8a51218827168cdclaireho  Free_Mark2Array( &mmp->Mark2Array, mmp->ClassCount );
29405569331642446be05292e3e1f8a51218827168cdclaireho  Free_MarkArray( &mmp->Mark1Array );
29415569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &mmp->Mark2Coverage );
29425569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &mmp->Mark1Coverage );
29435569331642446be05292e3e1f8a51218827168cdclaireho}
29445569331642446be05292e3e1f8a51218827168cdclaireho
29455569331642446be05292e3e1f8a51218827168cdclaireho
29465569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_MarkMarkPos( GPOS_Instance*    gpi,
29475569331642446be05292e3e1f8a51218827168cdclaireho				     HB_GPOS_SubTable* st,
29485569331642446be05292e3e1f8a51218827168cdclaireho				     HB_Buffer        buffer,
29495569331642446be05292e3e1f8a51218827168cdclaireho				     HB_UShort         flags,
29505569331642446be05292e3e1f8a51218827168cdclaireho				     HB_UShort         context_length,
29515569331642446be05292e3e1f8a51218827168cdclaireho				     int               nesting_level )
29525569331642446be05292e3e1f8a51218827168cdclaireho{
29535569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        i, j, mark1_index, mark2_index, property, class;
29545569331642446be05292e3e1f8a51218827168cdclaireho  HB_Fixed           x_mark1_value, y_mark1_value,
29555569331642446be05292e3e1f8a51218827168cdclaireho		   x_mark2_value, y_mark2_value;
29565569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error         error;
29575569331642446be05292e3e1f8a51218827168cdclaireho  HB_GPOSHeader*  gpos = gpi->gpos;
29585569331642446be05292e3e1f8a51218827168cdclaireho  HB_MarkMarkPos* mmp = &st->markmark;
29595569331642446be05292e3e1f8a51218827168cdclaireho
29605569331642446be05292e3e1f8a51218827168cdclaireho  HB_MarkArray*    ma1;
29615569331642446be05292e3e1f8a51218827168cdclaireho  HB_Mark2Array*   ma2;
29625569331642446be05292e3e1f8a51218827168cdclaireho  HB_Mark2Record*  m2r;
29635569331642446be05292e3e1f8a51218827168cdclaireho  HB_Anchor*       mark1_anchor;
29645569331642446be05292e3e1f8a51218827168cdclaireho  HB_Anchor*       mark2_anchor;
29655569331642446be05292e3e1f8a51218827168cdclaireho
29665569331642446be05292e3e1f8a51218827168cdclaireho  HB_Position    o;
29675569331642446be05292e3e1f8a51218827168cdclaireho
29685569331642446be05292e3e1f8a51218827168cdclaireho  HB_UNUSED(nesting_level);
29695569331642446be05292e3e1f8a51218827168cdclaireho
29705569331642446be05292e3e1f8a51218827168cdclaireho  if ( context_length != 0xFFFF && context_length < 1 )
29715569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
29725569331642446be05292e3e1f8a51218827168cdclaireho
29735569331642446be05292e3e1f8a51218827168cdclaireho  if ( flags & HB_LOOKUP_FLAG_IGNORE_MARKS )
29745569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
29755569331642446be05292e3e1f8a51218827168cdclaireho
29765569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gpos->gdef, IN_CURITEM(),
29775569331642446be05292e3e1f8a51218827168cdclaireho		       flags, &property ) )
29785569331642446be05292e3e1f8a51218827168cdclaireho    return error;
29795569331642446be05292e3e1f8a51218827168cdclaireho
29805569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Coverage_Index( &mmp->Mark1Coverage, IN_CURGLYPH(),
29815569331642446be05292e3e1f8a51218827168cdclaireho			  &mark1_index );
29825569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
29835569331642446be05292e3e1f8a51218827168cdclaireho    return error;
29845569331642446be05292e3e1f8a51218827168cdclaireho
29855569331642446be05292e3e1f8a51218827168cdclaireho  /* now we search backwards for a suitable mark glyph until a non-mark
29865569331642446be05292e3e1f8a51218827168cdclaireho     glyph                                                */
29875569331642446be05292e3e1f8a51218827168cdclaireho
29885569331642446be05292e3e1f8a51218827168cdclaireho  if ( buffer->in_pos == 0 )
29895569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
29905569331642446be05292e3e1f8a51218827168cdclaireho
29915569331642446be05292e3e1f8a51218827168cdclaireho  i = 1;
29925569331642446be05292e3e1f8a51218827168cdclaireho  j = buffer->in_pos - 1;
29935569331642446be05292e3e1f8a51218827168cdclaireho  while ( i <= buffer->in_pos )
29945569331642446be05292e3e1f8a51218827168cdclaireho  {
29955569331642446be05292e3e1f8a51218827168cdclaireho    error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
29965569331642446be05292e3e1f8a51218827168cdclaireho					&property );
29975569331642446be05292e3e1f8a51218827168cdclaireho    if ( error )
29985569331642446be05292e3e1f8a51218827168cdclaireho      return error;
29995569331642446be05292e3e1f8a51218827168cdclaireho
30005569331642446be05292e3e1f8a51218827168cdclaireho    if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
30015569331642446be05292e3e1f8a51218827168cdclaireho      return HB_Err_Not_Covered;
30025569331642446be05292e3e1f8a51218827168cdclaireho
30035569331642446be05292e3e1f8a51218827168cdclaireho    if ( flags & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
30045569331642446be05292e3e1f8a51218827168cdclaireho    {
30055569331642446be05292e3e1f8a51218827168cdclaireho      if ( property == (flags & 0xFF00) )
30065569331642446be05292e3e1f8a51218827168cdclaireho        break;
30075569331642446be05292e3e1f8a51218827168cdclaireho    }
30085569331642446be05292e3e1f8a51218827168cdclaireho    else
30095569331642446be05292e3e1f8a51218827168cdclaireho      break;
30105569331642446be05292e3e1f8a51218827168cdclaireho
30115569331642446be05292e3e1f8a51218827168cdclaireho    i++;
30125569331642446be05292e3e1f8a51218827168cdclaireho    j--;
30135569331642446be05292e3e1f8a51218827168cdclaireho  }
30145569331642446be05292e3e1f8a51218827168cdclaireho
30155b51d0c851af1852ecc7562790cbbbee156c2c44claireho  if ( i > buffer->in_pos )
30165b51d0c851af1852ecc7562790cbbbee156c2c44claireho    return HB_Err_Not_Covered;
30175b51d0c851af1852ecc7562790cbbbee156c2c44claireho
30185569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Coverage_Index( &mmp->Mark2Coverage, IN_GLYPH( j ),
30195569331642446be05292e3e1f8a51218827168cdclaireho			  &mark2_index );
30205569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
30215569331642446be05292e3e1f8a51218827168cdclaireho    return error;
30225569331642446be05292e3e1f8a51218827168cdclaireho
30235569331642446be05292e3e1f8a51218827168cdclaireho  ma1 = &mmp->Mark1Array;
30245569331642446be05292e3e1f8a51218827168cdclaireho
30255569331642446be05292e3e1f8a51218827168cdclaireho  if ( mark1_index >= ma1->MarkCount )
30265569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable);
30275569331642446be05292e3e1f8a51218827168cdclaireho
30285569331642446be05292e3e1f8a51218827168cdclaireho  class        = ma1->MarkRecord[mark1_index].Class;
30295569331642446be05292e3e1f8a51218827168cdclaireho  mark1_anchor = &ma1->MarkRecord[mark1_index].MarkAnchor;
30305569331642446be05292e3e1f8a51218827168cdclaireho
30315569331642446be05292e3e1f8a51218827168cdclaireho  if ( class >= mmp->ClassCount )
30325569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable);
30335569331642446be05292e3e1f8a51218827168cdclaireho
30345569331642446be05292e3e1f8a51218827168cdclaireho  ma2 = &mmp->Mark2Array;
30355569331642446be05292e3e1f8a51218827168cdclaireho
30365569331642446be05292e3e1f8a51218827168cdclaireho  if ( mark2_index >= ma2->Mark2Count )
30375569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable);
30385569331642446be05292e3e1f8a51218827168cdclaireho
30395569331642446be05292e3e1f8a51218827168cdclaireho  m2r          = &ma2->Mark2Record[mark2_index];
30405569331642446be05292e3e1f8a51218827168cdclaireho  mark2_anchor = &m2r->Mark2Anchor[class];
30415569331642446be05292e3e1f8a51218827168cdclaireho
30425569331642446be05292e3e1f8a51218827168cdclaireho  error = Get_Anchor( gpi, mark1_anchor, IN_CURGLYPH(),
30435569331642446be05292e3e1f8a51218827168cdclaireho		      &x_mark1_value, &y_mark1_value );
30445569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
30455569331642446be05292e3e1f8a51218827168cdclaireho    return error;
30465569331642446be05292e3e1f8a51218827168cdclaireho  error = Get_Anchor( gpi, mark2_anchor, IN_GLYPH( j ),
30475569331642446be05292e3e1f8a51218827168cdclaireho		      &x_mark2_value, &y_mark2_value );
30485569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
30495569331642446be05292e3e1f8a51218827168cdclaireho    return error;
30505569331642446be05292e3e1f8a51218827168cdclaireho
30515569331642446be05292e3e1f8a51218827168cdclaireho  /* anchor points are not cumulative */
30525569331642446be05292e3e1f8a51218827168cdclaireho
30535569331642446be05292e3e1f8a51218827168cdclaireho  o = POSITION( buffer->in_pos );
30545569331642446be05292e3e1f8a51218827168cdclaireho
30555569331642446be05292e3e1f8a51218827168cdclaireho  o->x_pos     = x_mark2_value - x_mark1_value;
30565569331642446be05292e3e1f8a51218827168cdclaireho  o->y_pos     = y_mark2_value - y_mark1_value;
30575569331642446be05292e3e1f8a51218827168cdclaireho  o->x_advance = 0;
30585569331642446be05292e3e1f8a51218827168cdclaireho  o->y_advance = 0;
30595569331642446be05292e3e1f8a51218827168cdclaireho  o->back      = 1;
30605569331642446be05292e3e1f8a51218827168cdclaireho
30615569331642446be05292e3e1f8a51218827168cdclaireho  (buffer->in_pos)++;
30625569331642446be05292e3e1f8a51218827168cdclaireho
30635569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
30645569331642446be05292e3e1f8a51218827168cdclaireho}
30655569331642446be05292e3e1f8a51218827168cdclaireho
30665569331642446be05292e3e1f8a51218827168cdclaireho
30675569331642446be05292e3e1f8a51218827168cdclaireho/* Do the actual positioning for a context positioning (either format
30685569331642446be05292e3e1f8a51218827168cdclaireho   7 or 8).  This is only called after we've determined that the stream
30695569331642446be05292e3e1f8a51218827168cdclaireho   matches the subrule.                                                 */
30705569331642446be05292e3e1f8a51218827168cdclaireho
30715569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Do_ContextPos( GPOS_Instance*        gpi,
30725569331642446be05292e3e1f8a51218827168cdclaireho				HB_UShort             GlyphCount,
30735569331642446be05292e3e1f8a51218827168cdclaireho				HB_UShort             PosCount,
30745569331642446be05292e3e1f8a51218827168cdclaireho				HB_PosLookupRecord*  pos,
30755569331642446be05292e3e1f8a51218827168cdclaireho				HB_Buffer            buffer,
30765569331642446be05292e3e1f8a51218827168cdclaireho				int                   nesting_level )
30775569331642446be05292e3e1f8a51218827168cdclaireho{
30785569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
30795569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt   i, old_pos;
30805569331642446be05292e3e1f8a51218827168cdclaireho
30815569331642446be05292e3e1f8a51218827168cdclaireho
30825569331642446be05292e3e1f8a51218827168cdclaireho  i = 0;
30835569331642446be05292e3e1f8a51218827168cdclaireho
30845569331642446be05292e3e1f8a51218827168cdclaireho  while ( i < GlyphCount )
30855569331642446be05292e3e1f8a51218827168cdclaireho  {
30865569331642446be05292e3e1f8a51218827168cdclaireho    if ( PosCount && i == pos->SequenceIndex )
30875569331642446be05292e3e1f8a51218827168cdclaireho    {
30885569331642446be05292e3e1f8a51218827168cdclaireho      old_pos = buffer->in_pos;
30895569331642446be05292e3e1f8a51218827168cdclaireho
30905569331642446be05292e3e1f8a51218827168cdclaireho      /* Do a positioning */
30915569331642446be05292e3e1f8a51218827168cdclaireho
30925569331642446be05292e3e1f8a51218827168cdclaireho      error = GPOS_Do_Glyph_Lookup( gpi, pos->LookupListIndex, buffer,
30935569331642446be05292e3e1f8a51218827168cdclaireho				    GlyphCount, nesting_level );
30945569331642446be05292e3e1f8a51218827168cdclaireho
30955569331642446be05292e3e1f8a51218827168cdclaireho      if ( error )
30965569331642446be05292e3e1f8a51218827168cdclaireho	return error;
30975569331642446be05292e3e1f8a51218827168cdclaireho
30985569331642446be05292e3e1f8a51218827168cdclaireho      pos++;
30995569331642446be05292e3e1f8a51218827168cdclaireho      PosCount--;
31005569331642446be05292e3e1f8a51218827168cdclaireho      i += buffer->in_pos - old_pos;
31015569331642446be05292e3e1f8a51218827168cdclaireho    }
31025569331642446be05292e3e1f8a51218827168cdclaireho    else
31035569331642446be05292e3e1f8a51218827168cdclaireho    {
31045569331642446be05292e3e1f8a51218827168cdclaireho      i++;
31055569331642446be05292e3e1f8a51218827168cdclaireho      (buffer->in_pos)++;
31065569331642446be05292e3e1f8a51218827168cdclaireho    }
31075569331642446be05292e3e1f8a51218827168cdclaireho  }
31085569331642446be05292e3e1f8a51218827168cdclaireho
31095569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
31105569331642446be05292e3e1f8a51218827168cdclaireho}
31115569331642446be05292e3e1f8a51218827168cdclaireho
31125569331642446be05292e3e1f8a51218827168cdclaireho
31135569331642446be05292e3e1f8a51218827168cdclaireho/* LookupType 7 */
31145569331642446be05292e3e1f8a51218827168cdclaireho
31155569331642446be05292e3e1f8a51218827168cdclaireho/* PosRule */
31165569331642446be05292e3e1f8a51218827168cdclaireho
31175569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_PosRule( HB_PosRule*  pr,
31185569331642446be05292e3e1f8a51218827168cdclaireho			       HB_Stream     stream )
31195569331642446be05292e3e1f8a51218827168cdclaireho{
31205569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
31215569331642446be05292e3e1f8a51218827168cdclaireho
31225569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort             n, count;
31235569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*            i;
31245569331642446be05292e3e1f8a51218827168cdclaireho
31255569331642446be05292e3e1f8a51218827168cdclaireho  HB_PosLookupRecord*  plr;
31265569331642446be05292e3e1f8a51218827168cdclaireho
31275569331642446be05292e3e1f8a51218827168cdclaireho
31285569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 4L ) )
31295569331642446be05292e3e1f8a51218827168cdclaireho    return error;
31305569331642446be05292e3e1f8a51218827168cdclaireho
31315569331642446be05292e3e1f8a51218827168cdclaireho  pr->GlyphCount = GET_UShort();
31325569331642446be05292e3e1f8a51218827168cdclaireho  pr->PosCount   = GET_UShort();
31335569331642446be05292e3e1f8a51218827168cdclaireho
31345569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
31355569331642446be05292e3e1f8a51218827168cdclaireho
31365569331642446be05292e3e1f8a51218827168cdclaireho  pr->Input = NULL;
31375569331642446be05292e3e1f8a51218827168cdclaireho
31385569331642446be05292e3e1f8a51218827168cdclaireho  count = pr->GlyphCount - 1;         /* only GlyphCount - 1 elements */
31395569331642446be05292e3e1f8a51218827168cdclaireho
31405569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( pr->Input, count, HB_UShort ) )
31415569331642446be05292e3e1f8a51218827168cdclaireho    return error;
31425569331642446be05292e3e1f8a51218827168cdclaireho
31435569331642446be05292e3e1f8a51218827168cdclaireho  i = pr->Input;
31445569331642446be05292e3e1f8a51218827168cdclaireho
31455569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
31465569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
31475569331642446be05292e3e1f8a51218827168cdclaireho
31485569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
31495569331642446be05292e3e1f8a51218827168cdclaireho    i[n] = GET_UShort();
31505569331642446be05292e3e1f8a51218827168cdclaireho
31515569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
31525569331642446be05292e3e1f8a51218827168cdclaireho
31535569331642446be05292e3e1f8a51218827168cdclaireho  pr->PosLookupRecord = NULL;
31545569331642446be05292e3e1f8a51218827168cdclaireho
31555569331642446be05292e3e1f8a51218827168cdclaireho  count = pr->PosCount;
31565569331642446be05292e3e1f8a51218827168cdclaireho
31575569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( pr->PosLookupRecord, count, HB_PosLookupRecord ) )
31585569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
31595569331642446be05292e3e1f8a51218827168cdclaireho
31605569331642446be05292e3e1f8a51218827168cdclaireho  plr = pr->PosLookupRecord;
31615569331642446be05292e3e1f8a51218827168cdclaireho
31625569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 4L ) )
31635569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail1;
31645569331642446be05292e3e1f8a51218827168cdclaireho
31655569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
31665569331642446be05292e3e1f8a51218827168cdclaireho  {
31675569331642446be05292e3e1f8a51218827168cdclaireho    plr[n].SequenceIndex   = GET_UShort();
31685569331642446be05292e3e1f8a51218827168cdclaireho    plr[n].LookupListIndex = GET_UShort();
31695569331642446be05292e3e1f8a51218827168cdclaireho  }
31705569331642446be05292e3e1f8a51218827168cdclaireho
31715569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
31725569331642446be05292e3e1f8a51218827168cdclaireho
31735569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
31745569331642446be05292e3e1f8a51218827168cdclaireho
31755569331642446be05292e3e1f8a51218827168cdclairehoFail1:
31765569331642446be05292e3e1f8a51218827168cdclaireho  FREE( plr );
31775569331642446be05292e3e1f8a51218827168cdclaireho
31785569331642446be05292e3e1f8a51218827168cdclairehoFail2:
31795569331642446be05292e3e1f8a51218827168cdclaireho  FREE( i );
31805569331642446be05292e3e1f8a51218827168cdclaireho  return error;
31815569331642446be05292e3e1f8a51218827168cdclaireho}
31825569331642446be05292e3e1f8a51218827168cdclaireho
31835569331642446be05292e3e1f8a51218827168cdclaireho
31845569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_PosRule( HB_PosRule*  pr )
31855569331642446be05292e3e1f8a51218827168cdclaireho{
31865569331642446be05292e3e1f8a51218827168cdclaireho  FREE( pr->PosLookupRecord );
31875569331642446be05292e3e1f8a51218827168cdclaireho  FREE( pr->Input );
31885569331642446be05292e3e1f8a51218827168cdclaireho}
31895569331642446be05292e3e1f8a51218827168cdclaireho
31905569331642446be05292e3e1f8a51218827168cdclaireho
31915569331642446be05292e3e1f8a51218827168cdclaireho/* PosRuleSet */
31925569331642446be05292e3e1f8a51218827168cdclaireho
31935569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_PosRuleSet( HB_PosRuleSet*  prs,
31945569331642446be05292e3e1f8a51218827168cdclaireho				  HB_Stream        stream )
31955569331642446be05292e3e1f8a51218827168cdclaireho{
31965569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
31975569331642446be05292e3e1f8a51218827168cdclaireho
31985569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort     n, m, count;
31995569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt      cur_offset, new_offset, base_offset;
32005569331642446be05292e3e1f8a51218827168cdclaireho
32015569331642446be05292e3e1f8a51218827168cdclaireho  HB_PosRule*  pr;
32025569331642446be05292e3e1f8a51218827168cdclaireho
32035569331642446be05292e3e1f8a51218827168cdclaireho
32045569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
32055569331642446be05292e3e1f8a51218827168cdclaireho
32065569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
32075569331642446be05292e3e1f8a51218827168cdclaireho    return error;
32085569331642446be05292e3e1f8a51218827168cdclaireho
32095569331642446be05292e3e1f8a51218827168cdclaireho  count = prs->PosRuleCount = GET_UShort();
32105569331642446be05292e3e1f8a51218827168cdclaireho
32115569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
32125569331642446be05292e3e1f8a51218827168cdclaireho
32135569331642446be05292e3e1f8a51218827168cdclaireho  prs->PosRule = NULL;
32145569331642446be05292e3e1f8a51218827168cdclaireho
32155569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( prs->PosRule, count, HB_PosRule ) )
32165569331642446be05292e3e1f8a51218827168cdclaireho    return error;
32175569331642446be05292e3e1f8a51218827168cdclaireho
32185569331642446be05292e3e1f8a51218827168cdclaireho  pr = prs->PosRule;
32195569331642446be05292e3e1f8a51218827168cdclaireho
32205569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
32215569331642446be05292e3e1f8a51218827168cdclaireho  {
32225569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
32235569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
32245569331642446be05292e3e1f8a51218827168cdclaireho
32255569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
32265569331642446be05292e3e1f8a51218827168cdclaireho
32275569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
32285569331642446be05292e3e1f8a51218827168cdclaireho
32295569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
32305569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
32315569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_PosRule( &pr[n], stream ) ) != HB_Err_Ok )
32325569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
32335569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
32345569331642446be05292e3e1f8a51218827168cdclaireho  }
32355569331642446be05292e3e1f8a51218827168cdclaireho
32365569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
32375569331642446be05292e3e1f8a51218827168cdclaireho
32385569331642446be05292e3e1f8a51218827168cdclairehoFail:
32395569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
32405569331642446be05292e3e1f8a51218827168cdclaireho    Free_PosRule( &pr[m] );
32415569331642446be05292e3e1f8a51218827168cdclaireho
32425569331642446be05292e3e1f8a51218827168cdclaireho  FREE( pr );
32435569331642446be05292e3e1f8a51218827168cdclaireho  return error;
32445569331642446be05292e3e1f8a51218827168cdclaireho}
32455569331642446be05292e3e1f8a51218827168cdclaireho
32465569331642446be05292e3e1f8a51218827168cdclaireho
32475569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_PosRuleSet( HB_PosRuleSet*  prs )
32485569331642446be05292e3e1f8a51218827168cdclaireho{
32495569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort     n, count;
32505569331642446be05292e3e1f8a51218827168cdclaireho
32515569331642446be05292e3e1f8a51218827168cdclaireho  HB_PosRule*  pr;
32525569331642446be05292e3e1f8a51218827168cdclaireho
32535569331642446be05292e3e1f8a51218827168cdclaireho
32545569331642446be05292e3e1f8a51218827168cdclaireho  if ( prs->PosRule )
32555569331642446be05292e3e1f8a51218827168cdclaireho  {
32565569331642446be05292e3e1f8a51218827168cdclaireho    count = prs->PosRuleCount;
32575569331642446be05292e3e1f8a51218827168cdclaireho    pr    = prs->PosRule;
32585569331642446be05292e3e1f8a51218827168cdclaireho
32595569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
32605569331642446be05292e3e1f8a51218827168cdclaireho      Free_PosRule( &pr[n] );
32615569331642446be05292e3e1f8a51218827168cdclaireho
32625569331642446be05292e3e1f8a51218827168cdclaireho    FREE( pr );
32635569331642446be05292e3e1f8a51218827168cdclaireho  }
32645569331642446be05292e3e1f8a51218827168cdclaireho}
32655569331642446be05292e3e1f8a51218827168cdclaireho
32665569331642446be05292e3e1f8a51218827168cdclaireho
32675569331642446be05292e3e1f8a51218827168cdclaireho/* ContextPosFormat1 */
32685569331642446be05292e3e1f8a51218827168cdclaireho
32695569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ContextPos1( HB_ContextPosFormat1*  cpf1,
32705569331642446be05292e3e1f8a51218827168cdclaireho				   HB_Stream               stream )
32715569331642446be05292e3e1f8a51218827168cdclaireho{
32725569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
32735569331642446be05292e3e1f8a51218827168cdclaireho
32745569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        n, m, count;
32755569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt         cur_offset, new_offset, base_offset;
32765569331642446be05292e3e1f8a51218827168cdclaireho
32775569331642446be05292e3e1f8a51218827168cdclaireho  HB_PosRuleSet*  prs;
32785569331642446be05292e3e1f8a51218827168cdclaireho
32795569331642446be05292e3e1f8a51218827168cdclaireho
32805569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos() - 2L;
32815569331642446be05292e3e1f8a51218827168cdclaireho
32825569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
32835569331642446be05292e3e1f8a51218827168cdclaireho    return error;
32845569331642446be05292e3e1f8a51218827168cdclaireho
32855569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
32865569331642446be05292e3e1f8a51218827168cdclaireho
32875569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
32885569331642446be05292e3e1f8a51218827168cdclaireho
32895569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
32905569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
32915569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_Coverage( &cpf1->Coverage, stream ) ) != HB_Err_Ok )
32925569331642446be05292e3e1f8a51218827168cdclaireho    return error;
32935569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
32945569331642446be05292e3e1f8a51218827168cdclaireho
32955569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
32965569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
32975569331642446be05292e3e1f8a51218827168cdclaireho
32985569331642446be05292e3e1f8a51218827168cdclaireho  count = cpf1->PosRuleSetCount = GET_UShort();
32995569331642446be05292e3e1f8a51218827168cdclaireho
33005569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
33015569331642446be05292e3e1f8a51218827168cdclaireho
33025569331642446be05292e3e1f8a51218827168cdclaireho  cpf1->PosRuleSet = NULL;
33035569331642446be05292e3e1f8a51218827168cdclaireho
33045569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cpf1->PosRuleSet, count, HB_PosRuleSet ) )
33055569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
33065569331642446be05292e3e1f8a51218827168cdclaireho
33075569331642446be05292e3e1f8a51218827168cdclaireho  prs = cpf1->PosRuleSet;
33085569331642446be05292e3e1f8a51218827168cdclaireho
33095569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
33105569331642446be05292e3e1f8a51218827168cdclaireho  {
33115569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
33125569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
33135569331642446be05292e3e1f8a51218827168cdclaireho
33145569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
33155569331642446be05292e3e1f8a51218827168cdclaireho
33165569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
33175569331642446be05292e3e1f8a51218827168cdclaireho
33185569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
33195569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
33205569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_PosRuleSet( &prs[n], stream ) ) != HB_Err_Ok )
33215569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
33225569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
33235569331642446be05292e3e1f8a51218827168cdclaireho  }
33245569331642446be05292e3e1f8a51218827168cdclaireho
33255569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
33265569331642446be05292e3e1f8a51218827168cdclaireho
33275569331642446be05292e3e1f8a51218827168cdclairehoFail1:
33285569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
33295569331642446be05292e3e1f8a51218827168cdclaireho    Free_PosRuleSet( &prs[m] );
33305569331642446be05292e3e1f8a51218827168cdclaireho
33315569331642446be05292e3e1f8a51218827168cdclaireho  FREE( prs );
33325569331642446be05292e3e1f8a51218827168cdclaireho
33335569331642446be05292e3e1f8a51218827168cdclairehoFail2:
33345569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &cpf1->Coverage );
33355569331642446be05292e3e1f8a51218827168cdclaireho  return error;
33365569331642446be05292e3e1f8a51218827168cdclaireho}
33375569331642446be05292e3e1f8a51218827168cdclaireho
33385569331642446be05292e3e1f8a51218827168cdclaireho
33395569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ContextPos1( HB_ContextPosFormat1*  cpf1 )
33405569331642446be05292e3e1f8a51218827168cdclaireho{
33415569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        n, count;
33425569331642446be05292e3e1f8a51218827168cdclaireho
33435569331642446be05292e3e1f8a51218827168cdclaireho  HB_PosRuleSet*  prs;
33445569331642446be05292e3e1f8a51218827168cdclaireho
33455569331642446be05292e3e1f8a51218827168cdclaireho
33465569331642446be05292e3e1f8a51218827168cdclaireho  if ( cpf1->PosRuleSet )
33475569331642446be05292e3e1f8a51218827168cdclaireho  {
33485569331642446be05292e3e1f8a51218827168cdclaireho    count = cpf1->PosRuleSetCount;
33495569331642446be05292e3e1f8a51218827168cdclaireho    prs   = cpf1->PosRuleSet;
33505569331642446be05292e3e1f8a51218827168cdclaireho
33515569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
33525569331642446be05292e3e1f8a51218827168cdclaireho      Free_PosRuleSet( &prs[n] );
33535569331642446be05292e3e1f8a51218827168cdclaireho
33545569331642446be05292e3e1f8a51218827168cdclaireho    FREE( prs );
33555569331642446be05292e3e1f8a51218827168cdclaireho  }
33565569331642446be05292e3e1f8a51218827168cdclaireho
33575569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &cpf1->Coverage );
33585569331642446be05292e3e1f8a51218827168cdclaireho}
33595569331642446be05292e3e1f8a51218827168cdclaireho
33605569331642446be05292e3e1f8a51218827168cdclaireho
33615569331642446be05292e3e1f8a51218827168cdclaireho/* PosClassRule */
33625569331642446be05292e3e1f8a51218827168cdclaireho
33635569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_PosClassRule( HB_ContextPosFormat2*  cpf2,
33645569331642446be05292e3e1f8a51218827168cdclaireho				    HB_PosClassRule*       pcr,
33655569331642446be05292e3e1f8a51218827168cdclaireho				    HB_Stream               stream )
33665569331642446be05292e3e1f8a51218827168cdclaireho{
33675569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
33685569331642446be05292e3e1f8a51218827168cdclaireho
33695569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort             n, count;
33705569331642446be05292e3e1f8a51218827168cdclaireho
33715569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*            c;
33725569331642446be05292e3e1f8a51218827168cdclaireho  HB_PosLookupRecord*  plr;
33735569331642446be05292e3e1f8a51218827168cdclaireho
33745569331642446be05292e3e1f8a51218827168cdclaireho
33755569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 4L ) )
33765569331642446be05292e3e1f8a51218827168cdclaireho    return error;
33775569331642446be05292e3e1f8a51218827168cdclaireho
33785569331642446be05292e3e1f8a51218827168cdclaireho  pcr->GlyphCount = GET_UShort();
33795569331642446be05292e3e1f8a51218827168cdclaireho  pcr->PosCount   = GET_UShort();
33805569331642446be05292e3e1f8a51218827168cdclaireho
33815569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
33825569331642446be05292e3e1f8a51218827168cdclaireho
33835569331642446be05292e3e1f8a51218827168cdclaireho  if ( pcr->GlyphCount > cpf2->MaxContextLength )
33845569331642446be05292e3e1f8a51218827168cdclaireho    cpf2->MaxContextLength = pcr->GlyphCount;
33855569331642446be05292e3e1f8a51218827168cdclaireho
33865569331642446be05292e3e1f8a51218827168cdclaireho  pcr->Class = NULL;
33875569331642446be05292e3e1f8a51218827168cdclaireho
33885569331642446be05292e3e1f8a51218827168cdclaireho  count = pcr->GlyphCount - 1;        /* only GlyphCount - 1 elements */
33895569331642446be05292e3e1f8a51218827168cdclaireho
33905569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( pcr->Class, count, HB_UShort ) )
33915569331642446be05292e3e1f8a51218827168cdclaireho    return error;
33925569331642446be05292e3e1f8a51218827168cdclaireho
33935569331642446be05292e3e1f8a51218827168cdclaireho  c = pcr->Class;
33945569331642446be05292e3e1f8a51218827168cdclaireho
33955569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
33965569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
33975569331642446be05292e3e1f8a51218827168cdclaireho
33985569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
33995569331642446be05292e3e1f8a51218827168cdclaireho    c[n] = GET_UShort();
34005569331642446be05292e3e1f8a51218827168cdclaireho
34015569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
34025569331642446be05292e3e1f8a51218827168cdclaireho
34035569331642446be05292e3e1f8a51218827168cdclaireho  pcr->PosLookupRecord = NULL;
34045569331642446be05292e3e1f8a51218827168cdclaireho
34055569331642446be05292e3e1f8a51218827168cdclaireho  count = pcr->PosCount;
34065569331642446be05292e3e1f8a51218827168cdclaireho
34075569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( pcr->PosLookupRecord, count, HB_PosLookupRecord ) )
34085569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
34095569331642446be05292e3e1f8a51218827168cdclaireho
34105569331642446be05292e3e1f8a51218827168cdclaireho  plr = pcr->PosLookupRecord;
34115569331642446be05292e3e1f8a51218827168cdclaireho
34125569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 4L ) )
34135569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail1;
34145569331642446be05292e3e1f8a51218827168cdclaireho
34155569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
34165569331642446be05292e3e1f8a51218827168cdclaireho  {
34175569331642446be05292e3e1f8a51218827168cdclaireho    plr[n].SequenceIndex   = GET_UShort();
34185569331642446be05292e3e1f8a51218827168cdclaireho    plr[n].LookupListIndex = GET_UShort();
34195569331642446be05292e3e1f8a51218827168cdclaireho  }
34205569331642446be05292e3e1f8a51218827168cdclaireho
34215569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
34225569331642446be05292e3e1f8a51218827168cdclaireho
34235569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
34245569331642446be05292e3e1f8a51218827168cdclaireho
34255569331642446be05292e3e1f8a51218827168cdclairehoFail1:
34265569331642446be05292e3e1f8a51218827168cdclaireho  FREE( plr );
34275569331642446be05292e3e1f8a51218827168cdclaireho
34285569331642446be05292e3e1f8a51218827168cdclairehoFail2:
34295569331642446be05292e3e1f8a51218827168cdclaireho  FREE( c );
34305569331642446be05292e3e1f8a51218827168cdclaireho  return error;
34315569331642446be05292e3e1f8a51218827168cdclaireho}
34325569331642446be05292e3e1f8a51218827168cdclaireho
34335569331642446be05292e3e1f8a51218827168cdclaireho
34345569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_PosClassRule( HB_PosClassRule*  pcr )
34355569331642446be05292e3e1f8a51218827168cdclaireho{
34365569331642446be05292e3e1f8a51218827168cdclaireho  FREE( pcr->PosLookupRecord );
34375569331642446be05292e3e1f8a51218827168cdclaireho  FREE( pcr->Class );
34385569331642446be05292e3e1f8a51218827168cdclaireho}
34395569331642446be05292e3e1f8a51218827168cdclaireho
34405569331642446be05292e3e1f8a51218827168cdclaireho
34415569331642446be05292e3e1f8a51218827168cdclaireho/* PosClassSet */
34425569331642446be05292e3e1f8a51218827168cdclaireho
34435569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_PosClassSet( HB_ContextPosFormat2*  cpf2,
34445569331642446be05292e3e1f8a51218827168cdclaireho				   HB_PosClassSet*        pcs,
34455569331642446be05292e3e1f8a51218827168cdclaireho				   HB_Stream               stream )
34465569331642446be05292e3e1f8a51218827168cdclaireho{
34475569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
34485569331642446be05292e3e1f8a51218827168cdclaireho
34495569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          n, m, count;
34505569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt           cur_offset, new_offset, base_offset;
34515569331642446be05292e3e1f8a51218827168cdclaireho
34525569331642446be05292e3e1f8a51218827168cdclaireho  HB_PosClassRule*  pcr;
34535569331642446be05292e3e1f8a51218827168cdclaireho
34545569331642446be05292e3e1f8a51218827168cdclaireho
34555569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
34565569331642446be05292e3e1f8a51218827168cdclaireho
34575569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
34585569331642446be05292e3e1f8a51218827168cdclaireho    return error;
34595569331642446be05292e3e1f8a51218827168cdclaireho
34605569331642446be05292e3e1f8a51218827168cdclaireho  count = pcs->PosClassRuleCount = GET_UShort();
34615569331642446be05292e3e1f8a51218827168cdclaireho
34625569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
34635569331642446be05292e3e1f8a51218827168cdclaireho
34645569331642446be05292e3e1f8a51218827168cdclaireho  pcs->PosClassRule = NULL;
34655569331642446be05292e3e1f8a51218827168cdclaireho
34665569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( pcs->PosClassRule, count, HB_PosClassRule ) )
34675569331642446be05292e3e1f8a51218827168cdclaireho    return error;
34685569331642446be05292e3e1f8a51218827168cdclaireho
34695569331642446be05292e3e1f8a51218827168cdclaireho  pcr = pcs->PosClassRule;
34705569331642446be05292e3e1f8a51218827168cdclaireho
34715569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
34725569331642446be05292e3e1f8a51218827168cdclaireho  {
34735569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
34745569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
34755569331642446be05292e3e1f8a51218827168cdclaireho
34765569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
34775569331642446be05292e3e1f8a51218827168cdclaireho
34785569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
34795569331642446be05292e3e1f8a51218827168cdclaireho
34805569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
34815569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
34825569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_PosClassRule( cpf2, &pcr[n],
34835569331642446be05292e3e1f8a51218827168cdclaireho				      stream ) ) != HB_Err_Ok )
34845569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
34855569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
34865569331642446be05292e3e1f8a51218827168cdclaireho  }
34875569331642446be05292e3e1f8a51218827168cdclaireho
34885569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
34895569331642446be05292e3e1f8a51218827168cdclaireho
34905569331642446be05292e3e1f8a51218827168cdclairehoFail:
34915569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
34925569331642446be05292e3e1f8a51218827168cdclaireho    Free_PosClassRule( &pcr[m] );
34935569331642446be05292e3e1f8a51218827168cdclaireho
34945569331642446be05292e3e1f8a51218827168cdclaireho  FREE( pcr );
34955569331642446be05292e3e1f8a51218827168cdclaireho  return error;
34965569331642446be05292e3e1f8a51218827168cdclaireho}
34975569331642446be05292e3e1f8a51218827168cdclaireho
34985569331642446be05292e3e1f8a51218827168cdclaireho
34995569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_PosClassSet( HB_PosClassSet*  pcs )
35005569331642446be05292e3e1f8a51218827168cdclaireho{
35015569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          n, count;
35025569331642446be05292e3e1f8a51218827168cdclaireho
35035569331642446be05292e3e1f8a51218827168cdclaireho  HB_PosClassRule*  pcr;
35045569331642446be05292e3e1f8a51218827168cdclaireho
35055569331642446be05292e3e1f8a51218827168cdclaireho
35065569331642446be05292e3e1f8a51218827168cdclaireho  if ( pcs->PosClassRule )
35075569331642446be05292e3e1f8a51218827168cdclaireho  {
35085569331642446be05292e3e1f8a51218827168cdclaireho    count = pcs->PosClassRuleCount;
35095569331642446be05292e3e1f8a51218827168cdclaireho    pcr   = pcs->PosClassRule;
35105569331642446be05292e3e1f8a51218827168cdclaireho
35115569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
35125569331642446be05292e3e1f8a51218827168cdclaireho      Free_PosClassRule( &pcr[n] );
35135569331642446be05292e3e1f8a51218827168cdclaireho
35145569331642446be05292e3e1f8a51218827168cdclaireho    FREE( pcr );
35155569331642446be05292e3e1f8a51218827168cdclaireho  }
35165569331642446be05292e3e1f8a51218827168cdclaireho}
35175569331642446be05292e3e1f8a51218827168cdclaireho
35185569331642446be05292e3e1f8a51218827168cdclaireho
35195569331642446be05292e3e1f8a51218827168cdclaireho/* ContextPosFormat2 */
35205569331642446be05292e3e1f8a51218827168cdclaireho
35215569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ContextPos2( HB_ContextPosFormat2*  cpf2,
35225569331642446be05292e3e1f8a51218827168cdclaireho				   HB_Stream               stream )
35235569331642446be05292e3e1f8a51218827168cdclaireho{
35245569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
35255569331642446be05292e3e1f8a51218827168cdclaireho
35265569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort         n, m, count;
35275569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt          cur_offset, new_offset, base_offset;
35285569331642446be05292e3e1f8a51218827168cdclaireho
35295569331642446be05292e3e1f8a51218827168cdclaireho  HB_PosClassSet*  pcs;
35305569331642446be05292e3e1f8a51218827168cdclaireho
35315569331642446be05292e3e1f8a51218827168cdclaireho
35325569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos() - 2;
35335569331642446be05292e3e1f8a51218827168cdclaireho
35345569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
35355569331642446be05292e3e1f8a51218827168cdclaireho    return error;
35365569331642446be05292e3e1f8a51218827168cdclaireho
35375569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
35385569331642446be05292e3e1f8a51218827168cdclaireho
35395569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
35405569331642446be05292e3e1f8a51218827168cdclaireho
35415569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
35425569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
35435569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_Coverage( &cpf2->Coverage, stream ) ) != HB_Err_Ok )
35445569331642446be05292e3e1f8a51218827168cdclaireho    return error;
35455569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
35465569331642446be05292e3e1f8a51218827168cdclaireho
35475569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 4L ) )
35485569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
35495569331642446be05292e3e1f8a51218827168cdclaireho
35505569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
35515569331642446be05292e3e1f8a51218827168cdclaireho
35525569331642446be05292e3e1f8a51218827168cdclaireho  /* `PosClassSetCount' is the upper limit for class values, thus we
35535569331642446be05292e3e1f8a51218827168cdclaireho     read it now to make an additional safety check.                 */
35545569331642446be05292e3e1f8a51218827168cdclaireho
35555569331642446be05292e3e1f8a51218827168cdclaireho  count = cpf2->PosClassSetCount = GET_UShort();
35565569331642446be05292e3e1f8a51218827168cdclaireho
35575569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
35585569331642446be05292e3e1f8a51218827168cdclaireho
35595569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
35605569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
35615569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_ClassDefinition( &cpf2->ClassDef, count,
35625569331642446be05292e3e1f8a51218827168cdclaireho				       stream ) ) != HB_Err_Ok )
35635569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
35645569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
35655569331642446be05292e3e1f8a51218827168cdclaireho
35665569331642446be05292e3e1f8a51218827168cdclaireho  cpf2->PosClassSet      = NULL;
35675569331642446be05292e3e1f8a51218827168cdclaireho  cpf2->MaxContextLength = 0;
35685569331642446be05292e3e1f8a51218827168cdclaireho
35695569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cpf2->PosClassSet, count, HB_PosClassSet ) )
35705569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
35715569331642446be05292e3e1f8a51218827168cdclaireho
35725569331642446be05292e3e1f8a51218827168cdclaireho  pcs = cpf2->PosClassSet;
35735569331642446be05292e3e1f8a51218827168cdclaireho
35745569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
35755569331642446be05292e3e1f8a51218827168cdclaireho  {
35765569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
35775569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
35785569331642446be05292e3e1f8a51218827168cdclaireho
35795569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
35805569331642446be05292e3e1f8a51218827168cdclaireho
35815569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
35825569331642446be05292e3e1f8a51218827168cdclaireho
35835569331642446be05292e3e1f8a51218827168cdclaireho    if ( new_offset != base_offset )      /* not a NULL offset */
35845569331642446be05292e3e1f8a51218827168cdclaireho    {
35855569331642446be05292e3e1f8a51218827168cdclaireho      cur_offset = FILE_Pos();
35865569331642446be05292e3e1f8a51218827168cdclaireho      if ( FILE_Seek( new_offset ) ||
35875569331642446be05292e3e1f8a51218827168cdclaireho	   ( error = Load_PosClassSet( cpf2, &pcs[n],
35885569331642446be05292e3e1f8a51218827168cdclaireho				       stream ) ) != HB_Err_Ok )
35895569331642446be05292e3e1f8a51218827168cdclaireho	goto Fail1;
35905569331642446be05292e3e1f8a51218827168cdclaireho      (void)FILE_Seek( cur_offset );
35915569331642446be05292e3e1f8a51218827168cdclaireho    }
35925569331642446be05292e3e1f8a51218827168cdclaireho    else
35935569331642446be05292e3e1f8a51218827168cdclaireho    {
35945569331642446be05292e3e1f8a51218827168cdclaireho      /* we create a PosClassSet table with no entries */
35955569331642446be05292e3e1f8a51218827168cdclaireho
35965569331642446be05292e3e1f8a51218827168cdclaireho      cpf2->PosClassSet[n].PosClassRuleCount = 0;
35975569331642446be05292e3e1f8a51218827168cdclaireho      cpf2->PosClassSet[n].PosClassRule      = NULL;
35985569331642446be05292e3e1f8a51218827168cdclaireho    }
35995569331642446be05292e3e1f8a51218827168cdclaireho  }
36005569331642446be05292e3e1f8a51218827168cdclaireho
36015569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
36025569331642446be05292e3e1f8a51218827168cdclaireho
36035569331642446be05292e3e1f8a51218827168cdclairehoFail1:
36045569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; n++ )
36055569331642446be05292e3e1f8a51218827168cdclaireho    Free_PosClassSet( &pcs[m] );
36065569331642446be05292e3e1f8a51218827168cdclaireho
36075569331642446be05292e3e1f8a51218827168cdclaireho  FREE( pcs );
36085569331642446be05292e3e1f8a51218827168cdclaireho
36095569331642446be05292e3e1f8a51218827168cdclairehoFail2:
36105569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_ClassDefinition( &cpf2->ClassDef );
36115569331642446be05292e3e1f8a51218827168cdclaireho
36125569331642446be05292e3e1f8a51218827168cdclairehoFail3:
36135569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &cpf2->Coverage );
36145569331642446be05292e3e1f8a51218827168cdclaireho  return error;
36155569331642446be05292e3e1f8a51218827168cdclaireho}
36165569331642446be05292e3e1f8a51218827168cdclaireho
36175569331642446be05292e3e1f8a51218827168cdclaireho
36185569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ContextPos2( HB_ContextPosFormat2*  cpf2 )
36195569331642446be05292e3e1f8a51218827168cdclaireho{
36205569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort         n, count;
36215569331642446be05292e3e1f8a51218827168cdclaireho
36225569331642446be05292e3e1f8a51218827168cdclaireho  HB_PosClassSet*  pcs;
36235569331642446be05292e3e1f8a51218827168cdclaireho
36245569331642446be05292e3e1f8a51218827168cdclaireho
36255569331642446be05292e3e1f8a51218827168cdclaireho  if ( cpf2->PosClassSet )
36265569331642446be05292e3e1f8a51218827168cdclaireho  {
36275569331642446be05292e3e1f8a51218827168cdclaireho    count = cpf2->PosClassSetCount;
36285569331642446be05292e3e1f8a51218827168cdclaireho    pcs   = cpf2->PosClassSet;
36295569331642446be05292e3e1f8a51218827168cdclaireho
36305569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
36315569331642446be05292e3e1f8a51218827168cdclaireho      Free_PosClassSet( &pcs[n] );
36325569331642446be05292e3e1f8a51218827168cdclaireho
36335569331642446be05292e3e1f8a51218827168cdclaireho    FREE( pcs );
36345569331642446be05292e3e1f8a51218827168cdclaireho  }
36355569331642446be05292e3e1f8a51218827168cdclaireho
36365569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_ClassDefinition( &cpf2->ClassDef );
36375569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &cpf2->Coverage );
36385569331642446be05292e3e1f8a51218827168cdclaireho}
36395569331642446be05292e3e1f8a51218827168cdclaireho
36405569331642446be05292e3e1f8a51218827168cdclaireho
36415569331642446be05292e3e1f8a51218827168cdclaireho/* ContextPosFormat3 */
36425569331642446be05292e3e1f8a51218827168cdclaireho
36435569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ContextPos3( HB_ContextPosFormat3*  cpf3,
36445569331642446be05292e3e1f8a51218827168cdclaireho				   HB_Stream               stream )
36455569331642446be05292e3e1f8a51218827168cdclaireho{
36465569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
36475569331642446be05292e3e1f8a51218827168cdclaireho
36485569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort             n, count;
36495569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt              cur_offset, new_offset, base_offset;
36505569331642446be05292e3e1f8a51218827168cdclaireho
36515569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*         c;
36525569331642446be05292e3e1f8a51218827168cdclaireho  HB_PosLookupRecord*  plr;
36535569331642446be05292e3e1f8a51218827168cdclaireho
36545569331642446be05292e3e1f8a51218827168cdclaireho
36555569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos() - 2L;
36565569331642446be05292e3e1f8a51218827168cdclaireho
36575569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 4L ) )
36585569331642446be05292e3e1f8a51218827168cdclaireho    return error;
36595569331642446be05292e3e1f8a51218827168cdclaireho
36605569331642446be05292e3e1f8a51218827168cdclaireho  cpf3->GlyphCount = GET_UShort();
36615569331642446be05292e3e1f8a51218827168cdclaireho  cpf3->PosCount   = GET_UShort();
36625569331642446be05292e3e1f8a51218827168cdclaireho
36635569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
36645569331642446be05292e3e1f8a51218827168cdclaireho
36655569331642446be05292e3e1f8a51218827168cdclaireho  cpf3->Coverage = NULL;
36665569331642446be05292e3e1f8a51218827168cdclaireho
36675569331642446be05292e3e1f8a51218827168cdclaireho  count = cpf3->GlyphCount;
36685569331642446be05292e3e1f8a51218827168cdclaireho
36695569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cpf3->Coverage, count, HB_Coverage ) )
36705569331642446be05292e3e1f8a51218827168cdclaireho    return error;
36715569331642446be05292e3e1f8a51218827168cdclaireho
36725569331642446be05292e3e1f8a51218827168cdclaireho  c = cpf3->Coverage;
36735569331642446be05292e3e1f8a51218827168cdclaireho
36745569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
36755569331642446be05292e3e1f8a51218827168cdclaireho  {
36765569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
36775569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail2;
36785569331642446be05292e3e1f8a51218827168cdclaireho
36795569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
36805569331642446be05292e3e1f8a51218827168cdclaireho
36815569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
36825569331642446be05292e3e1f8a51218827168cdclaireho
36835569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
36845569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
36855569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = _HB_OPEN_Load_Coverage( &c[n], stream ) ) != HB_Err_Ok )
36865569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail2;
36875569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
36885569331642446be05292e3e1f8a51218827168cdclaireho  }
36895569331642446be05292e3e1f8a51218827168cdclaireho
36905569331642446be05292e3e1f8a51218827168cdclaireho  cpf3->PosLookupRecord = NULL;
36915569331642446be05292e3e1f8a51218827168cdclaireho
36925569331642446be05292e3e1f8a51218827168cdclaireho  count = cpf3->PosCount;
36935569331642446be05292e3e1f8a51218827168cdclaireho
36945569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cpf3->PosLookupRecord, count, HB_PosLookupRecord ) )
36955569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
36965569331642446be05292e3e1f8a51218827168cdclaireho
36975569331642446be05292e3e1f8a51218827168cdclaireho  plr = cpf3->PosLookupRecord;
36985569331642446be05292e3e1f8a51218827168cdclaireho
36995569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 4L ) )
37005569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail1;
37015569331642446be05292e3e1f8a51218827168cdclaireho
37025569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
37035569331642446be05292e3e1f8a51218827168cdclaireho  {
37045569331642446be05292e3e1f8a51218827168cdclaireho    plr[n].SequenceIndex   = GET_UShort();
37055569331642446be05292e3e1f8a51218827168cdclaireho    plr[n].LookupListIndex = GET_UShort();
37065569331642446be05292e3e1f8a51218827168cdclaireho  }
37075569331642446be05292e3e1f8a51218827168cdclaireho
37085569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
37095569331642446be05292e3e1f8a51218827168cdclaireho
37105569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
37115569331642446be05292e3e1f8a51218827168cdclaireho
37125569331642446be05292e3e1f8a51218827168cdclairehoFail1:
37135569331642446be05292e3e1f8a51218827168cdclaireho  FREE( plr );
37145569331642446be05292e3e1f8a51218827168cdclaireho
37155569331642446be05292e3e1f8a51218827168cdclairehoFail2:
37165569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
37175569331642446be05292e3e1f8a51218827168cdclaireho    _HB_OPEN_Free_Coverage( &c[n] );
37185569331642446be05292e3e1f8a51218827168cdclaireho
37195569331642446be05292e3e1f8a51218827168cdclaireho  FREE( c );
37205569331642446be05292e3e1f8a51218827168cdclaireho  return error;
37215569331642446be05292e3e1f8a51218827168cdclaireho}
37225569331642446be05292e3e1f8a51218827168cdclaireho
37235569331642446be05292e3e1f8a51218827168cdclaireho
37245569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ContextPos3( HB_ContextPosFormat3*  cpf3 )
37255569331642446be05292e3e1f8a51218827168cdclaireho{
37265569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort      n, count;
37275569331642446be05292e3e1f8a51218827168cdclaireho
37285569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*  c;
37295569331642446be05292e3e1f8a51218827168cdclaireho
37305569331642446be05292e3e1f8a51218827168cdclaireho
37315569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cpf3->PosLookupRecord );
37325569331642446be05292e3e1f8a51218827168cdclaireho
37335569331642446be05292e3e1f8a51218827168cdclaireho  if ( cpf3->Coverage )
37345569331642446be05292e3e1f8a51218827168cdclaireho  {
37355569331642446be05292e3e1f8a51218827168cdclaireho    count = cpf3->GlyphCount;
37365569331642446be05292e3e1f8a51218827168cdclaireho    c     = cpf3->Coverage;
37375569331642446be05292e3e1f8a51218827168cdclaireho
37385569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
37395569331642446be05292e3e1f8a51218827168cdclaireho      _HB_OPEN_Free_Coverage( &c[n] );
37405569331642446be05292e3e1f8a51218827168cdclaireho
37415569331642446be05292e3e1f8a51218827168cdclaireho    FREE( c );
37425569331642446be05292e3e1f8a51218827168cdclaireho  }
37435569331642446be05292e3e1f8a51218827168cdclaireho}
37445569331642446be05292e3e1f8a51218827168cdclaireho
37455569331642446be05292e3e1f8a51218827168cdclaireho
37465569331642446be05292e3e1f8a51218827168cdclaireho/* ContextPos */
37475569331642446be05292e3e1f8a51218827168cdclaireho
37485569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ContextPos( HB_GPOS_SubTable* st,
37495569331642446be05292e3e1f8a51218827168cdclaireho				  HB_Stream        stream )
37505569331642446be05292e3e1f8a51218827168cdclaireho{
37515569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
37525569331642446be05292e3e1f8a51218827168cdclaireho  HB_ContextPos*   cp = &st->context;
37535569331642446be05292e3e1f8a51218827168cdclaireho
37545569331642446be05292e3e1f8a51218827168cdclaireho
37555569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
37565569331642446be05292e3e1f8a51218827168cdclaireho    return error;
37575569331642446be05292e3e1f8a51218827168cdclaireho
37585569331642446be05292e3e1f8a51218827168cdclaireho  cp->PosFormat = GET_UShort();
37595569331642446be05292e3e1f8a51218827168cdclaireho
37605569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
37615569331642446be05292e3e1f8a51218827168cdclaireho
37625569331642446be05292e3e1f8a51218827168cdclaireho  switch ( cp->PosFormat )
37635569331642446be05292e3e1f8a51218827168cdclaireho  {
37645569331642446be05292e3e1f8a51218827168cdclaireho  case 1:
37655569331642446be05292e3e1f8a51218827168cdclaireho    return Load_ContextPos1( &cp->cpf.cpf1, stream );
37665569331642446be05292e3e1f8a51218827168cdclaireho
37675569331642446be05292e3e1f8a51218827168cdclaireho  case 2:
37685569331642446be05292e3e1f8a51218827168cdclaireho    return Load_ContextPos2( &cp->cpf.cpf2, stream );
37695569331642446be05292e3e1f8a51218827168cdclaireho
37705569331642446be05292e3e1f8a51218827168cdclaireho  case 3:
37715569331642446be05292e3e1f8a51218827168cdclaireho    return Load_ContextPos3( &cp->cpf.cpf3, stream );
37725569331642446be05292e3e1f8a51218827168cdclaireho
37735569331642446be05292e3e1f8a51218827168cdclaireho  default:
37745569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable_Format);
37755569331642446be05292e3e1f8a51218827168cdclaireho  }
37765569331642446be05292e3e1f8a51218827168cdclaireho
37775569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;               /* never reached */
37785569331642446be05292e3e1f8a51218827168cdclaireho}
37795569331642446be05292e3e1f8a51218827168cdclaireho
37805569331642446be05292e3e1f8a51218827168cdclaireho
37815569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ContextPos( HB_GPOS_SubTable* st )
37825569331642446be05292e3e1f8a51218827168cdclaireho{
37835569331642446be05292e3e1f8a51218827168cdclaireho  HB_ContextPos*   cp = &st->context;
37845569331642446be05292e3e1f8a51218827168cdclaireho
37855569331642446be05292e3e1f8a51218827168cdclaireho  switch ( cp->PosFormat )
37865569331642446be05292e3e1f8a51218827168cdclaireho  {
37875569331642446be05292e3e1f8a51218827168cdclaireho  case 1:  Free_ContextPos1( &cp->cpf.cpf1 ); break;
37885569331642446be05292e3e1f8a51218827168cdclaireho  case 2:  Free_ContextPos2( &cp->cpf.cpf2 ); break;
37895569331642446be05292e3e1f8a51218827168cdclaireho  case 3:  Free_ContextPos3( &cp->cpf.cpf3 ); break;
37905569331642446be05292e3e1f8a51218827168cdclaireho  default:					      break;
37915569331642446be05292e3e1f8a51218827168cdclaireho  }
37925569331642446be05292e3e1f8a51218827168cdclaireho}
37935569331642446be05292e3e1f8a51218827168cdclaireho
37945569331642446be05292e3e1f8a51218827168cdclaireho
37955569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_ContextPos1( GPOS_Instance*          gpi,
37965569331642446be05292e3e1f8a51218827168cdclaireho				     HB_ContextPosFormat1*  cpf1,
37975569331642446be05292e3e1f8a51218827168cdclaireho				     HB_Buffer              buffer,
37985569331642446be05292e3e1f8a51218827168cdclaireho				     HB_UShort               flags,
37995569331642446be05292e3e1f8a51218827168cdclaireho				     HB_UShort               context_length,
38005569331642446be05292e3e1f8a51218827168cdclaireho				     int                     nesting_level )
38015569331642446be05292e3e1f8a51218827168cdclaireho{
38025569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        index, property;
38035569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        i, j, k, numpr;
38045569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error         error;
38055569331642446be05292e3e1f8a51218827168cdclaireho  HB_GPOSHeader*  gpos = gpi->gpos;
38065569331642446be05292e3e1f8a51218827168cdclaireho
38075569331642446be05292e3e1f8a51218827168cdclaireho  HB_PosRule*     pr;
38085569331642446be05292e3e1f8a51218827168cdclaireho  HB_GDEFHeader*  gdef;
38095569331642446be05292e3e1f8a51218827168cdclaireho
38105569331642446be05292e3e1f8a51218827168cdclaireho
38115569331642446be05292e3e1f8a51218827168cdclaireho  gdef = gpos->gdef;
38125569331642446be05292e3e1f8a51218827168cdclaireho
38135569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
38145569331642446be05292e3e1f8a51218827168cdclaireho    return error;
38155569331642446be05292e3e1f8a51218827168cdclaireho
38165569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Coverage_Index( &cpf1->Coverage, IN_CURGLYPH(), &index );
38175569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
38185569331642446be05292e3e1f8a51218827168cdclaireho    return error;
38195569331642446be05292e3e1f8a51218827168cdclaireho
38205569331642446be05292e3e1f8a51218827168cdclaireho  pr    = cpf1->PosRuleSet[index].PosRule;
38215569331642446be05292e3e1f8a51218827168cdclaireho  numpr = cpf1->PosRuleSet[index].PosRuleCount;
38225569331642446be05292e3e1f8a51218827168cdclaireho
38235569331642446be05292e3e1f8a51218827168cdclaireho  for ( k = 0; k < numpr; k++ )
38245569331642446be05292e3e1f8a51218827168cdclaireho  {
38255569331642446be05292e3e1f8a51218827168cdclaireho    if ( context_length != 0xFFFF && context_length < pr[k].GlyphCount )
38265569331642446be05292e3e1f8a51218827168cdclaireho      goto next_posrule;
38275569331642446be05292e3e1f8a51218827168cdclaireho
38285569331642446be05292e3e1f8a51218827168cdclaireho    if ( buffer->in_pos + pr[k].GlyphCount > buffer->in_length )
38295569331642446be05292e3e1f8a51218827168cdclaireho      goto next_posrule;                       /* context is too long */
38305569331642446be05292e3e1f8a51218827168cdclaireho
38315569331642446be05292e3e1f8a51218827168cdclaireho    for ( i = 1, j = buffer->in_pos + 1; i < pr[k].GlyphCount; i++, j++ )
38325569331642446be05292e3e1f8a51218827168cdclaireho    {
38335569331642446be05292e3e1f8a51218827168cdclaireho      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
38345569331642446be05292e3e1f8a51218827168cdclaireho      {
38355569331642446be05292e3e1f8a51218827168cdclaireho	if ( error && error != HB_Err_Not_Covered )
38365569331642446be05292e3e1f8a51218827168cdclaireho	  return error;
38375569331642446be05292e3e1f8a51218827168cdclaireho
38385569331642446be05292e3e1f8a51218827168cdclaireho	if ( j + pr[k].GlyphCount - i == (HB_Int)buffer->in_length )
38395569331642446be05292e3e1f8a51218827168cdclaireho	  goto next_posrule;
38405569331642446be05292e3e1f8a51218827168cdclaireho	j++;
38415569331642446be05292e3e1f8a51218827168cdclaireho      }
38425569331642446be05292e3e1f8a51218827168cdclaireho
38435569331642446be05292e3e1f8a51218827168cdclaireho      if ( IN_GLYPH( j ) != pr[k].Input[i - 1] )
38445569331642446be05292e3e1f8a51218827168cdclaireho	goto next_posrule;
38455569331642446be05292e3e1f8a51218827168cdclaireho    }
38465569331642446be05292e3e1f8a51218827168cdclaireho
38475569331642446be05292e3e1f8a51218827168cdclaireho    return Do_ContextPos( gpi, pr[k].GlyphCount,
38485569331642446be05292e3e1f8a51218827168cdclaireho			  pr[k].PosCount, pr[k].PosLookupRecord,
38495569331642446be05292e3e1f8a51218827168cdclaireho			  buffer,
38505569331642446be05292e3e1f8a51218827168cdclaireho			  nesting_level );
38515569331642446be05292e3e1f8a51218827168cdclaireho
38525569331642446be05292e3e1f8a51218827168cdclaireho    next_posrule:
38535569331642446be05292e3e1f8a51218827168cdclaireho      ;
38545569331642446be05292e3e1f8a51218827168cdclaireho  }
38555569331642446be05292e3e1f8a51218827168cdclaireho
38565569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Not_Covered;
38575569331642446be05292e3e1f8a51218827168cdclaireho}
38585569331642446be05292e3e1f8a51218827168cdclaireho
38595569331642446be05292e3e1f8a51218827168cdclaireho
38605569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_ContextPos2( GPOS_Instance*          gpi,
38615569331642446be05292e3e1f8a51218827168cdclaireho				     HB_ContextPosFormat2*  cpf2,
38625569331642446be05292e3e1f8a51218827168cdclaireho				     HB_Buffer              buffer,
38635569331642446be05292e3e1f8a51218827168cdclaireho				     HB_UShort               flags,
38645569331642446be05292e3e1f8a51218827168cdclaireho				     HB_UShort               context_length,
38655569331642446be05292e3e1f8a51218827168cdclaireho				     int                     nesting_level )
38665569331642446be05292e3e1f8a51218827168cdclaireho{
38675569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          index, property;
38685569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error           error;
38695569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          i, j, k, known_classes;
38705569331642446be05292e3e1f8a51218827168cdclaireho
38715569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*         classes;
38725569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*         cl;
38735569331642446be05292e3e1f8a51218827168cdclaireho  HB_GPOSHeader*    gpos = gpi->gpos;
38745569331642446be05292e3e1f8a51218827168cdclaireho
38755569331642446be05292e3e1f8a51218827168cdclaireho  HB_PosClassSet*   pcs;
38765569331642446be05292e3e1f8a51218827168cdclaireho  HB_PosClassRule*  pr;
38775569331642446be05292e3e1f8a51218827168cdclaireho  HB_GDEFHeader*    gdef;
38785569331642446be05292e3e1f8a51218827168cdclaireho
38795569331642446be05292e3e1f8a51218827168cdclaireho
38805569331642446be05292e3e1f8a51218827168cdclaireho  gdef = gpos->gdef;
38815569331642446be05292e3e1f8a51218827168cdclaireho
38825569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
38835569331642446be05292e3e1f8a51218827168cdclaireho    return error;
38845569331642446be05292e3e1f8a51218827168cdclaireho
38855569331642446be05292e3e1f8a51218827168cdclaireho  /* Note: The coverage table in format 2 doesn't give an index into
38865569331642446be05292e3e1f8a51218827168cdclaireho	   anything.  It just lets us know whether or not we need to
38875569331642446be05292e3e1f8a51218827168cdclaireho	   do any lookup at all.                                     */
38885569331642446be05292e3e1f8a51218827168cdclaireho
38895569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Coverage_Index( &cpf2->Coverage, IN_CURGLYPH(), &index );
38905569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
38915569331642446be05292e3e1f8a51218827168cdclaireho    return error;
38925569331642446be05292e3e1f8a51218827168cdclaireho
38935569331642446be05292e3e1f8a51218827168cdclaireho  if (cpf2->MaxContextLength < 1)
38945569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
38955569331642446be05292e3e1f8a51218827168cdclaireho
38965569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( classes, cpf2->MaxContextLength, HB_UShort ) )
38975569331642446be05292e3e1f8a51218827168cdclaireho    return error;
38985569331642446be05292e3e1f8a51218827168cdclaireho
38995569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Get_Class( &cpf2->ClassDef, IN_CURGLYPH(),
39005569331642446be05292e3e1f8a51218827168cdclaireho		     &classes[0], NULL );
39015569331642446be05292e3e1f8a51218827168cdclaireho  if ( error && error != HB_Err_Not_Covered )
39025569331642446be05292e3e1f8a51218827168cdclaireho    goto End;
39035569331642446be05292e3e1f8a51218827168cdclaireho  known_classes = 0;
39045569331642446be05292e3e1f8a51218827168cdclaireho
39055569331642446be05292e3e1f8a51218827168cdclaireho  pcs = &cpf2->PosClassSet[classes[0]];
39065569331642446be05292e3e1f8a51218827168cdclaireho  if ( !pcs )
39075569331642446be05292e3e1f8a51218827168cdclaireho  {
39085569331642446be05292e3e1f8a51218827168cdclaireho    error = ERR(HB_Err_Invalid_SubTable);
39095569331642446be05292e3e1f8a51218827168cdclaireho    goto End;
39105569331642446be05292e3e1f8a51218827168cdclaireho  }
39115569331642446be05292e3e1f8a51218827168cdclaireho
39125569331642446be05292e3e1f8a51218827168cdclaireho  for ( k = 0; k < pcs->PosClassRuleCount; k++ )
39135569331642446be05292e3e1f8a51218827168cdclaireho  {
39145569331642446be05292e3e1f8a51218827168cdclaireho    pr = &pcs->PosClassRule[k];
39155569331642446be05292e3e1f8a51218827168cdclaireho
39165569331642446be05292e3e1f8a51218827168cdclaireho    if ( context_length != 0xFFFF && context_length < pr->GlyphCount )
39175569331642446be05292e3e1f8a51218827168cdclaireho      goto next_posclassrule;
39185569331642446be05292e3e1f8a51218827168cdclaireho
39195569331642446be05292e3e1f8a51218827168cdclaireho    if ( buffer->in_pos + pr->GlyphCount > buffer->in_length )
39205569331642446be05292e3e1f8a51218827168cdclaireho      goto next_posclassrule;                /* context is too long */
39215569331642446be05292e3e1f8a51218827168cdclaireho
39225569331642446be05292e3e1f8a51218827168cdclaireho    cl   = pr->Class;
39235569331642446be05292e3e1f8a51218827168cdclaireho
39245569331642446be05292e3e1f8a51218827168cdclaireho    /* Start at 1 because [0] is implied */
39255569331642446be05292e3e1f8a51218827168cdclaireho
39265569331642446be05292e3e1f8a51218827168cdclaireho    for ( i = 1, j = buffer->in_pos + 1; i < pr->GlyphCount; i++, j++ )
39275569331642446be05292e3e1f8a51218827168cdclaireho    {
39285569331642446be05292e3e1f8a51218827168cdclaireho      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
39295569331642446be05292e3e1f8a51218827168cdclaireho      {
39305569331642446be05292e3e1f8a51218827168cdclaireho	if ( error && error != HB_Err_Not_Covered )
39315569331642446be05292e3e1f8a51218827168cdclaireho	  goto End;
39325569331642446be05292e3e1f8a51218827168cdclaireho
39335569331642446be05292e3e1f8a51218827168cdclaireho	if ( j + pr->GlyphCount - i == (HB_Int)buffer->in_length )
39345569331642446be05292e3e1f8a51218827168cdclaireho	  goto next_posclassrule;
39355569331642446be05292e3e1f8a51218827168cdclaireho	j++;
39365569331642446be05292e3e1f8a51218827168cdclaireho      }
39375569331642446be05292e3e1f8a51218827168cdclaireho
39385569331642446be05292e3e1f8a51218827168cdclaireho      if ( i > known_classes )
39395569331642446be05292e3e1f8a51218827168cdclaireho      {
39405569331642446be05292e3e1f8a51218827168cdclaireho	/* Keeps us from having to do this for each rule */
39415569331642446be05292e3e1f8a51218827168cdclaireho
39425569331642446be05292e3e1f8a51218827168cdclaireho	error = _HB_OPEN_Get_Class( &cpf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL );
39435569331642446be05292e3e1f8a51218827168cdclaireho	if ( error && error != HB_Err_Not_Covered )
39445569331642446be05292e3e1f8a51218827168cdclaireho	  goto End;
39455569331642446be05292e3e1f8a51218827168cdclaireho	known_classes = i;
39465569331642446be05292e3e1f8a51218827168cdclaireho      }
39475569331642446be05292e3e1f8a51218827168cdclaireho
39485569331642446be05292e3e1f8a51218827168cdclaireho      if ( cl[i - 1] != classes[i] )
39495569331642446be05292e3e1f8a51218827168cdclaireho	goto next_posclassrule;
39505569331642446be05292e3e1f8a51218827168cdclaireho    }
39515569331642446be05292e3e1f8a51218827168cdclaireho
39525569331642446be05292e3e1f8a51218827168cdclaireho    error = Do_ContextPos( gpi, pr->GlyphCount,
39535569331642446be05292e3e1f8a51218827168cdclaireho			   pr->PosCount, pr->PosLookupRecord,
39545569331642446be05292e3e1f8a51218827168cdclaireho			   buffer,
39555569331642446be05292e3e1f8a51218827168cdclaireho			   nesting_level );
39565569331642446be05292e3e1f8a51218827168cdclaireho    goto End;
39575569331642446be05292e3e1f8a51218827168cdclaireho
39585569331642446be05292e3e1f8a51218827168cdclaireho  next_posclassrule:
39595569331642446be05292e3e1f8a51218827168cdclaireho    ;
39605569331642446be05292e3e1f8a51218827168cdclaireho  }
39615569331642446be05292e3e1f8a51218827168cdclaireho
39625569331642446be05292e3e1f8a51218827168cdclaireho  error = HB_Err_Not_Covered;
39635569331642446be05292e3e1f8a51218827168cdclaireho
39645569331642446be05292e3e1f8a51218827168cdclairehoEnd:
39655569331642446be05292e3e1f8a51218827168cdclaireho  FREE( classes );
39665569331642446be05292e3e1f8a51218827168cdclaireho  return error;
39675569331642446be05292e3e1f8a51218827168cdclaireho}
39685569331642446be05292e3e1f8a51218827168cdclaireho
39695569331642446be05292e3e1f8a51218827168cdclaireho
39705569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_ContextPos3( GPOS_Instance*          gpi,
39715569331642446be05292e3e1f8a51218827168cdclaireho				     HB_ContextPosFormat3*  cpf3,
39725569331642446be05292e3e1f8a51218827168cdclaireho				     HB_Buffer              buffer,
39735569331642446be05292e3e1f8a51218827168cdclaireho				     HB_UShort               flags,
39745569331642446be05292e3e1f8a51218827168cdclaireho				     HB_UShort               context_length,
39755569331642446be05292e3e1f8a51218827168cdclaireho				     int                     nesting_level )
39765569331642446be05292e3e1f8a51218827168cdclaireho{
39775569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error         error;
39785569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        index, i, j, property;
39795569331642446be05292e3e1f8a51218827168cdclaireho  HB_GPOSHeader*  gpos = gpi->gpos;
39805569331642446be05292e3e1f8a51218827168cdclaireho
39815569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*    c;
39825569331642446be05292e3e1f8a51218827168cdclaireho  HB_GDEFHeader*  gdef;
39835569331642446be05292e3e1f8a51218827168cdclaireho
39845569331642446be05292e3e1f8a51218827168cdclaireho
39855569331642446be05292e3e1f8a51218827168cdclaireho  gdef = gpos->gdef;
39865569331642446be05292e3e1f8a51218827168cdclaireho
39875569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
39885569331642446be05292e3e1f8a51218827168cdclaireho    return error;
39895569331642446be05292e3e1f8a51218827168cdclaireho
39905569331642446be05292e3e1f8a51218827168cdclaireho  if ( context_length != 0xFFFF && context_length < cpf3->GlyphCount )
39915569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
39925569331642446be05292e3e1f8a51218827168cdclaireho
39935569331642446be05292e3e1f8a51218827168cdclaireho  if ( buffer->in_pos + cpf3->GlyphCount > buffer->in_length )
39945569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;         /* context is too long */
39955569331642446be05292e3e1f8a51218827168cdclaireho
39965569331642446be05292e3e1f8a51218827168cdclaireho  c    = cpf3->Coverage;
39975569331642446be05292e3e1f8a51218827168cdclaireho
39985569331642446be05292e3e1f8a51218827168cdclaireho  for ( i = 1, j = 1; i < cpf3->GlyphCount; i++, j++ )
39995569331642446be05292e3e1f8a51218827168cdclaireho  {
40005569331642446be05292e3e1f8a51218827168cdclaireho    while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
40015569331642446be05292e3e1f8a51218827168cdclaireho    {
40025569331642446be05292e3e1f8a51218827168cdclaireho      if ( error && error != HB_Err_Not_Covered )
40035569331642446be05292e3e1f8a51218827168cdclaireho	return error;
40045569331642446be05292e3e1f8a51218827168cdclaireho
40055569331642446be05292e3e1f8a51218827168cdclaireho      if ( j + cpf3->GlyphCount - i == (HB_Int)buffer->in_length )
40065569331642446be05292e3e1f8a51218827168cdclaireho	return HB_Err_Not_Covered;
40075569331642446be05292e3e1f8a51218827168cdclaireho      j++;
40085569331642446be05292e3e1f8a51218827168cdclaireho    }
40095569331642446be05292e3e1f8a51218827168cdclaireho
40105569331642446be05292e3e1f8a51218827168cdclaireho    error = _HB_OPEN_Coverage_Index( &c[i], IN_GLYPH( j ), &index );
40115569331642446be05292e3e1f8a51218827168cdclaireho    if ( error )
40125569331642446be05292e3e1f8a51218827168cdclaireho      return error;
40135569331642446be05292e3e1f8a51218827168cdclaireho  }
40145569331642446be05292e3e1f8a51218827168cdclaireho
40155569331642446be05292e3e1f8a51218827168cdclaireho  return Do_ContextPos( gpi, cpf3->GlyphCount,
40165569331642446be05292e3e1f8a51218827168cdclaireho			cpf3->PosCount, cpf3->PosLookupRecord,
40175569331642446be05292e3e1f8a51218827168cdclaireho			buffer,
40185569331642446be05292e3e1f8a51218827168cdclaireho			nesting_level );
40195569331642446be05292e3e1f8a51218827168cdclaireho}
40205569331642446be05292e3e1f8a51218827168cdclaireho
40215569331642446be05292e3e1f8a51218827168cdclaireho
40225569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_ContextPos( GPOS_Instance*    gpi,
40235569331642446be05292e3e1f8a51218827168cdclaireho				    HB_GPOS_SubTable* st,
40245569331642446be05292e3e1f8a51218827168cdclaireho				    HB_Buffer        buffer,
40255569331642446be05292e3e1f8a51218827168cdclaireho				    HB_UShort         flags,
40265569331642446be05292e3e1f8a51218827168cdclaireho				    HB_UShort         context_length,
40275569331642446be05292e3e1f8a51218827168cdclaireho				    int               nesting_level )
40285569331642446be05292e3e1f8a51218827168cdclaireho{
40295569331642446be05292e3e1f8a51218827168cdclaireho  HB_ContextPos*   cp = &st->context;
40305569331642446be05292e3e1f8a51218827168cdclaireho
40315569331642446be05292e3e1f8a51218827168cdclaireho  switch ( cp->PosFormat )
40325569331642446be05292e3e1f8a51218827168cdclaireho  {
40335569331642446be05292e3e1f8a51218827168cdclaireho  case 1:
40345569331642446be05292e3e1f8a51218827168cdclaireho    return Lookup_ContextPos1( gpi, &cp->cpf.cpf1, buffer,
40355569331642446be05292e3e1f8a51218827168cdclaireho			       flags, context_length, nesting_level );
40365569331642446be05292e3e1f8a51218827168cdclaireho
40375569331642446be05292e3e1f8a51218827168cdclaireho  case 2:
40385569331642446be05292e3e1f8a51218827168cdclaireho    return Lookup_ContextPos2( gpi, &cp->cpf.cpf2, buffer,
40395569331642446be05292e3e1f8a51218827168cdclaireho			       flags, context_length, nesting_level );
40405569331642446be05292e3e1f8a51218827168cdclaireho
40415569331642446be05292e3e1f8a51218827168cdclaireho  case 3:
40425569331642446be05292e3e1f8a51218827168cdclaireho    return Lookup_ContextPos3( gpi, &cp->cpf.cpf3, buffer,
40435569331642446be05292e3e1f8a51218827168cdclaireho			       flags, context_length, nesting_level );
40445569331642446be05292e3e1f8a51218827168cdclaireho
40455569331642446be05292e3e1f8a51218827168cdclaireho  default:
40465569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable_Format);
40475569331642446be05292e3e1f8a51218827168cdclaireho  }
40485569331642446be05292e3e1f8a51218827168cdclaireho
40495569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;               /* never reached */
40505569331642446be05292e3e1f8a51218827168cdclaireho}
40515569331642446be05292e3e1f8a51218827168cdclaireho
40525569331642446be05292e3e1f8a51218827168cdclaireho
40535569331642446be05292e3e1f8a51218827168cdclaireho/* LookupType 8 */
40545569331642446be05292e3e1f8a51218827168cdclaireho
40555569331642446be05292e3e1f8a51218827168cdclaireho/* ChainPosRule */
40565569331642446be05292e3e1f8a51218827168cdclaireho
40575569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ChainPosRule( HB_ChainPosRule*  cpr,
40585569331642446be05292e3e1f8a51218827168cdclaireho				    HB_Stream          stream )
40595569331642446be05292e3e1f8a51218827168cdclaireho{
40605569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
40615569331642446be05292e3e1f8a51218827168cdclaireho
40625569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort             n, count;
40635569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*            b;
40645569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*            i;
40655569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*            l;
40665569331642446be05292e3e1f8a51218827168cdclaireho
40675569331642446be05292e3e1f8a51218827168cdclaireho  HB_PosLookupRecord*  plr;
40685569331642446be05292e3e1f8a51218827168cdclaireho
40695569331642446be05292e3e1f8a51218827168cdclaireho
40705569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
40715569331642446be05292e3e1f8a51218827168cdclaireho    return error;
40725569331642446be05292e3e1f8a51218827168cdclaireho
40735569331642446be05292e3e1f8a51218827168cdclaireho  cpr->BacktrackGlyphCount = GET_UShort();
40745569331642446be05292e3e1f8a51218827168cdclaireho
40755569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
40765569331642446be05292e3e1f8a51218827168cdclaireho
40775569331642446be05292e3e1f8a51218827168cdclaireho  cpr->Backtrack = NULL;
40785569331642446be05292e3e1f8a51218827168cdclaireho
40795569331642446be05292e3e1f8a51218827168cdclaireho  count = cpr->BacktrackGlyphCount;
40805569331642446be05292e3e1f8a51218827168cdclaireho
40815569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cpr->Backtrack, count, HB_UShort ) )
40825569331642446be05292e3e1f8a51218827168cdclaireho    return error;
40835569331642446be05292e3e1f8a51218827168cdclaireho
40845569331642446be05292e3e1f8a51218827168cdclaireho  b = cpr->Backtrack;
40855569331642446be05292e3e1f8a51218827168cdclaireho
40865569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
40875569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
40885569331642446be05292e3e1f8a51218827168cdclaireho
40895569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
40905569331642446be05292e3e1f8a51218827168cdclaireho    b[n] = GET_UShort();
40915569331642446be05292e3e1f8a51218827168cdclaireho
40925569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
40935569331642446be05292e3e1f8a51218827168cdclaireho
40945569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
40955569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
40965569331642446be05292e3e1f8a51218827168cdclaireho
40975569331642446be05292e3e1f8a51218827168cdclaireho  cpr->InputGlyphCount = GET_UShort();
40985569331642446be05292e3e1f8a51218827168cdclaireho
40995569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
41005569331642446be05292e3e1f8a51218827168cdclaireho
41015569331642446be05292e3e1f8a51218827168cdclaireho  cpr->Input = NULL;
41025569331642446be05292e3e1f8a51218827168cdclaireho
41035569331642446be05292e3e1f8a51218827168cdclaireho  count = cpr->InputGlyphCount - 1;  /* only InputGlyphCount - 1 elements */
41045569331642446be05292e3e1f8a51218827168cdclaireho
41055569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cpr->Input, count, HB_UShort ) )
41065569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
41075569331642446be05292e3e1f8a51218827168cdclaireho
41085569331642446be05292e3e1f8a51218827168cdclaireho  i = cpr->Input;
41095569331642446be05292e3e1f8a51218827168cdclaireho
41105569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
41115569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
41125569331642446be05292e3e1f8a51218827168cdclaireho
41135569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
41145569331642446be05292e3e1f8a51218827168cdclaireho    i[n] = GET_UShort();
41155569331642446be05292e3e1f8a51218827168cdclaireho
41165569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
41175569331642446be05292e3e1f8a51218827168cdclaireho
41185569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
41195569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
41205569331642446be05292e3e1f8a51218827168cdclaireho
41215569331642446be05292e3e1f8a51218827168cdclaireho  cpr->LookaheadGlyphCount = GET_UShort();
41225569331642446be05292e3e1f8a51218827168cdclaireho
41235569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
41245569331642446be05292e3e1f8a51218827168cdclaireho
41255569331642446be05292e3e1f8a51218827168cdclaireho  cpr->Lookahead = NULL;
41265569331642446be05292e3e1f8a51218827168cdclaireho
41275569331642446be05292e3e1f8a51218827168cdclaireho  count = cpr->LookaheadGlyphCount;
41285569331642446be05292e3e1f8a51218827168cdclaireho
41295569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cpr->Lookahead, count, HB_UShort ) )
41305569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
41315569331642446be05292e3e1f8a51218827168cdclaireho
41325569331642446be05292e3e1f8a51218827168cdclaireho  l = cpr->Lookahead;
41335569331642446be05292e3e1f8a51218827168cdclaireho
41345569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
41355569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
41365569331642446be05292e3e1f8a51218827168cdclaireho
41375569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
41385569331642446be05292e3e1f8a51218827168cdclaireho    l[n] = GET_UShort();
41395569331642446be05292e3e1f8a51218827168cdclaireho
41405569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
41415569331642446be05292e3e1f8a51218827168cdclaireho
41425569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
41435569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
41445569331642446be05292e3e1f8a51218827168cdclaireho
41455569331642446be05292e3e1f8a51218827168cdclaireho  cpr->PosCount = GET_UShort();
41465569331642446be05292e3e1f8a51218827168cdclaireho
41475569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
41485569331642446be05292e3e1f8a51218827168cdclaireho
41495569331642446be05292e3e1f8a51218827168cdclaireho  cpr->PosLookupRecord = NULL;
41505569331642446be05292e3e1f8a51218827168cdclaireho
41515569331642446be05292e3e1f8a51218827168cdclaireho  count = cpr->PosCount;
41525569331642446be05292e3e1f8a51218827168cdclaireho
41535569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cpr->PosLookupRecord, count, HB_PosLookupRecord ) )
41545569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
41555569331642446be05292e3e1f8a51218827168cdclaireho
41565569331642446be05292e3e1f8a51218827168cdclaireho  plr = cpr->PosLookupRecord;
41575569331642446be05292e3e1f8a51218827168cdclaireho
41585569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 4L ) )
41595569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail1;
41605569331642446be05292e3e1f8a51218827168cdclaireho
41615569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
41625569331642446be05292e3e1f8a51218827168cdclaireho  {
41635569331642446be05292e3e1f8a51218827168cdclaireho    plr[n].SequenceIndex   = GET_UShort();
41645569331642446be05292e3e1f8a51218827168cdclaireho    plr[n].LookupListIndex = GET_UShort();
41655569331642446be05292e3e1f8a51218827168cdclaireho  }
41665569331642446be05292e3e1f8a51218827168cdclaireho
41675569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
41685569331642446be05292e3e1f8a51218827168cdclaireho
41695569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
41705569331642446be05292e3e1f8a51218827168cdclaireho
41715569331642446be05292e3e1f8a51218827168cdclairehoFail1:
41725569331642446be05292e3e1f8a51218827168cdclaireho  FREE( plr );
41735569331642446be05292e3e1f8a51218827168cdclaireho
41745569331642446be05292e3e1f8a51218827168cdclairehoFail2:
41755569331642446be05292e3e1f8a51218827168cdclaireho  FREE( l );
41765569331642446be05292e3e1f8a51218827168cdclaireho
41775569331642446be05292e3e1f8a51218827168cdclairehoFail3:
41785569331642446be05292e3e1f8a51218827168cdclaireho  FREE( i );
41795569331642446be05292e3e1f8a51218827168cdclaireho
41805569331642446be05292e3e1f8a51218827168cdclairehoFail4:
41815569331642446be05292e3e1f8a51218827168cdclaireho  FREE( b );
41825569331642446be05292e3e1f8a51218827168cdclaireho  return error;
41835569331642446be05292e3e1f8a51218827168cdclaireho}
41845569331642446be05292e3e1f8a51218827168cdclaireho
41855569331642446be05292e3e1f8a51218827168cdclaireho
41865569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ChainPosRule( HB_ChainPosRule*  cpr )
41875569331642446be05292e3e1f8a51218827168cdclaireho{
41885569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cpr->PosLookupRecord );
41895569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cpr->Lookahead );
41905569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cpr->Input );
41915569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cpr->Backtrack );
41925569331642446be05292e3e1f8a51218827168cdclaireho}
41935569331642446be05292e3e1f8a51218827168cdclaireho
41945569331642446be05292e3e1f8a51218827168cdclaireho
41955569331642446be05292e3e1f8a51218827168cdclaireho/* ChainPosRuleSet */
41965569331642446be05292e3e1f8a51218827168cdclaireho
41975569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ChainPosRuleSet( HB_ChainPosRuleSet*  cprs,
41985569331642446be05292e3e1f8a51218827168cdclaireho				       HB_Stream             stream )
41995569331642446be05292e3e1f8a51218827168cdclaireho{
42005569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
42015569331642446be05292e3e1f8a51218827168cdclaireho
42025569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          n, m, count;
42035569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt           cur_offset, new_offset, base_offset;
42045569331642446be05292e3e1f8a51218827168cdclaireho
42055569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainPosRule*  cpr;
42065569331642446be05292e3e1f8a51218827168cdclaireho
42075569331642446be05292e3e1f8a51218827168cdclaireho
42085569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
42095569331642446be05292e3e1f8a51218827168cdclaireho
42105569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
42115569331642446be05292e3e1f8a51218827168cdclaireho    return error;
42125569331642446be05292e3e1f8a51218827168cdclaireho
42135569331642446be05292e3e1f8a51218827168cdclaireho  count = cprs->ChainPosRuleCount = GET_UShort();
42145569331642446be05292e3e1f8a51218827168cdclaireho
42155569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
42165569331642446be05292e3e1f8a51218827168cdclaireho
42175569331642446be05292e3e1f8a51218827168cdclaireho  cprs->ChainPosRule = NULL;
42185569331642446be05292e3e1f8a51218827168cdclaireho
42195569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cprs->ChainPosRule, count, HB_ChainPosRule ) )
42205569331642446be05292e3e1f8a51218827168cdclaireho    return error;
42215569331642446be05292e3e1f8a51218827168cdclaireho
42225569331642446be05292e3e1f8a51218827168cdclaireho  cpr = cprs->ChainPosRule;
42235569331642446be05292e3e1f8a51218827168cdclaireho
42245569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
42255569331642446be05292e3e1f8a51218827168cdclaireho  {
42265569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
42275569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
42285569331642446be05292e3e1f8a51218827168cdclaireho
42295569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
42305569331642446be05292e3e1f8a51218827168cdclaireho
42315569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
42325569331642446be05292e3e1f8a51218827168cdclaireho
42335569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
42345569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
42355569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_ChainPosRule( &cpr[n], stream ) ) != HB_Err_Ok )
42365569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
42375569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
42385569331642446be05292e3e1f8a51218827168cdclaireho  }
42395569331642446be05292e3e1f8a51218827168cdclaireho
42405569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
42415569331642446be05292e3e1f8a51218827168cdclaireho
42425569331642446be05292e3e1f8a51218827168cdclairehoFail:
42435569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
42445569331642446be05292e3e1f8a51218827168cdclaireho    Free_ChainPosRule( &cpr[m] );
42455569331642446be05292e3e1f8a51218827168cdclaireho
42465569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cpr );
42475569331642446be05292e3e1f8a51218827168cdclaireho  return error;
42485569331642446be05292e3e1f8a51218827168cdclaireho}
42495569331642446be05292e3e1f8a51218827168cdclaireho
42505569331642446be05292e3e1f8a51218827168cdclaireho
42515569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ChainPosRuleSet( HB_ChainPosRuleSet*  cprs )
42525569331642446be05292e3e1f8a51218827168cdclaireho{
42535569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          n, count;
42545569331642446be05292e3e1f8a51218827168cdclaireho
42555569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainPosRule*  cpr;
42565569331642446be05292e3e1f8a51218827168cdclaireho
42575569331642446be05292e3e1f8a51218827168cdclaireho
42585569331642446be05292e3e1f8a51218827168cdclaireho  if ( cprs->ChainPosRule )
42595569331642446be05292e3e1f8a51218827168cdclaireho  {
42605569331642446be05292e3e1f8a51218827168cdclaireho    count = cprs->ChainPosRuleCount;
42615569331642446be05292e3e1f8a51218827168cdclaireho    cpr   = cprs->ChainPosRule;
42625569331642446be05292e3e1f8a51218827168cdclaireho
42635569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
42645569331642446be05292e3e1f8a51218827168cdclaireho      Free_ChainPosRule( &cpr[n] );
42655569331642446be05292e3e1f8a51218827168cdclaireho
42665569331642446be05292e3e1f8a51218827168cdclaireho    FREE( cpr );
42675569331642446be05292e3e1f8a51218827168cdclaireho  }
42685569331642446be05292e3e1f8a51218827168cdclaireho}
42695569331642446be05292e3e1f8a51218827168cdclaireho
42705569331642446be05292e3e1f8a51218827168cdclaireho
42715569331642446be05292e3e1f8a51218827168cdclaireho/* ChainContextPosFormat1 */
42725569331642446be05292e3e1f8a51218827168cdclaireho
42735569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ChainContextPos1( HB_ChainContextPosFormat1*  ccpf1,
42745569331642446be05292e3e1f8a51218827168cdclaireho					HB_Stream                    stream )
42755569331642446be05292e3e1f8a51218827168cdclaireho{
42765569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
42775569331642446be05292e3e1f8a51218827168cdclaireho
42785569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort             n, m, count;
42795569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt              cur_offset, new_offset, base_offset;
42805569331642446be05292e3e1f8a51218827168cdclaireho
42815569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainPosRuleSet*  cprs;
42825569331642446be05292e3e1f8a51218827168cdclaireho
42835569331642446be05292e3e1f8a51218827168cdclaireho
42845569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos() - 2L;
42855569331642446be05292e3e1f8a51218827168cdclaireho
42865569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
42875569331642446be05292e3e1f8a51218827168cdclaireho    return error;
42885569331642446be05292e3e1f8a51218827168cdclaireho
42895569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
42905569331642446be05292e3e1f8a51218827168cdclaireho
42915569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
42925569331642446be05292e3e1f8a51218827168cdclaireho
42935569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
42945569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
42955569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_Coverage( &ccpf1->Coverage, stream ) ) != HB_Err_Ok )
42965569331642446be05292e3e1f8a51218827168cdclaireho    return error;
42975569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
42985569331642446be05292e3e1f8a51218827168cdclaireho
42995569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
43005569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
43015569331642446be05292e3e1f8a51218827168cdclaireho
43025569331642446be05292e3e1f8a51218827168cdclaireho  count = ccpf1->ChainPosRuleSetCount = GET_UShort();
43035569331642446be05292e3e1f8a51218827168cdclaireho
43045569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
43055569331642446be05292e3e1f8a51218827168cdclaireho
43065569331642446be05292e3e1f8a51218827168cdclaireho  ccpf1->ChainPosRuleSet = NULL;
43075569331642446be05292e3e1f8a51218827168cdclaireho
43085569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ccpf1->ChainPosRuleSet, count, HB_ChainPosRuleSet ) )
43095569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
43105569331642446be05292e3e1f8a51218827168cdclaireho
43115569331642446be05292e3e1f8a51218827168cdclaireho  cprs = ccpf1->ChainPosRuleSet;
43125569331642446be05292e3e1f8a51218827168cdclaireho
43135569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
43145569331642446be05292e3e1f8a51218827168cdclaireho  {
43155569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
43165569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
43175569331642446be05292e3e1f8a51218827168cdclaireho
43185569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
43195569331642446be05292e3e1f8a51218827168cdclaireho
43205569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
43215569331642446be05292e3e1f8a51218827168cdclaireho
43225569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
43235569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
43245569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_ChainPosRuleSet( &cprs[n], stream ) ) != HB_Err_Ok )
43255569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
43265569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
43275569331642446be05292e3e1f8a51218827168cdclaireho  }
43285569331642446be05292e3e1f8a51218827168cdclaireho
43295569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
43305569331642446be05292e3e1f8a51218827168cdclaireho
43315569331642446be05292e3e1f8a51218827168cdclairehoFail1:
43325569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
43335569331642446be05292e3e1f8a51218827168cdclaireho    Free_ChainPosRuleSet( &cprs[m] );
43345569331642446be05292e3e1f8a51218827168cdclaireho
43355569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cprs );
43365569331642446be05292e3e1f8a51218827168cdclaireho
43375569331642446be05292e3e1f8a51218827168cdclairehoFail2:
43385569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &ccpf1->Coverage );
43395569331642446be05292e3e1f8a51218827168cdclaireho  return error;
43405569331642446be05292e3e1f8a51218827168cdclaireho}
43415569331642446be05292e3e1f8a51218827168cdclaireho
43425569331642446be05292e3e1f8a51218827168cdclaireho
43435569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ChainContextPos1( HB_ChainContextPosFormat1*  ccpf1 )
43445569331642446be05292e3e1f8a51218827168cdclaireho{
43455569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort             n, count;
43465569331642446be05292e3e1f8a51218827168cdclaireho
43475569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainPosRuleSet*  cprs;
43485569331642446be05292e3e1f8a51218827168cdclaireho
43495569331642446be05292e3e1f8a51218827168cdclaireho
43505569331642446be05292e3e1f8a51218827168cdclaireho  if ( ccpf1->ChainPosRuleSet )
43515569331642446be05292e3e1f8a51218827168cdclaireho  {
43525569331642446be05292e3e1f8a51218827168cdclaireho    count = ccpf1->ChainPosRuleSetCount;
43535569331642446be05292e3e1f8a51218827168cdclaireho    cprs  = ccpf1->ChainPosRuleSet;
43545569331642446be05292e3e1f8a51218827168cdclaireho
43555569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
43565569331642446be05292e3e1f8a51218827168cdclaireho      Free_ChainPosRuleSet( &cprs[n] );
43575569331642446be05292e3e1f8a51218827168cdclaireho
43585569331642446be05292e3e1f8a51218827168cdclaireho    FREE( cprs );
43595569331642446be05292e3e1f8a51218827168cdclaireho  }
43605569331642446be05292e3e1f8a51218827168cdclaireho
43615569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &ccpf1->Coverage );
43625569331642446be05292e3e1f8a51218827168cdclaireho}
43635569331642446be05292e3e1f8a51218827168cdclaireho
43645569331642446be05292e3e1f8a51218827168cdclaireho
43655569331642446be05292e3e1f8a51218827168cdclaireho/* ChainPosClassRule */
43665569331642446be05292e3e1f8a51218827168cdclaireho
43675569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ChainPosClassRule(
43685569331642446be05292e3e1f8a51218827168cdclaireho		   HB_ChainContextPosFormat2*  ccpf2,
43695569331642446be05292e3e1f8a51218827168cdclaireho		   HB_ChainPosClassRule*       cpcr,
43705569331642446be05292e3e1f8a51218827168cdclaireho		   HB_Stream                    stream )
43715569331642446be05292e3e1f8a51218827168cdclaireho{
43725569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
43735569331642446be05292e3e1f8a51218827168cdclaireho
43745569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort             n, count;
43755569331642446be05292e3e1f8a51218827168cdclaireho
43765569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*            b;
43775569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*            i;
43785569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*            l;
43795569331642446be05292e3e1f8a51218827168cdclaireho  HB_PosLookupRecord*  plr;
43805569331642446be05292e3e1f8a51218827168cdclaireho
43815569331642446be05292e3e1f8a51218827168cdclaireho
43825569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
43835569331642446be05292e3e1f8a51218827168cdclaireho    return error;
43845569331642446be05292e3e1f8a51218827168cdclaireho
43855569331642446be05292e3e1f8a51218827168cdclaireho  cpcr->BacktrackGlyphCount = GET_UShort();
43865569331642446be05292e3e1f8a51218827168cdclaireho
43875569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
43885569331642446be05292e3e1f8a51218827168cdclaireho
43895569331642446be05292e3e1f8a51218827168cdclaireho  if ( cpcr->BacktrackGlyphCount > ccpf2->MaxBacktrackLength )
43905569331642446be05292e3e1f8a51218827168cdclaireho    ccpf2->MaxBacktrackLength = cpcr->BacktrackGlyphCount;
43915569331642446be05292e3e1f8a51218827168cdclaireho
43925569331642446be05292e3e1f8a51218827168cdclaireho  cpcr->Backtrack = NULL;
43935569331642446be05292e3e1f8a51218827168cdclaireho
43945569331642446be05292e3e1f8a51218827168cdclaireho  count = cpcr->BacktrackGlyphCount;
43955569331642446be05292e3e1f8a51218827168cdclaireho
43965569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cpcr->Backtrack, count, HB_UShort ) )
43975569331642446be05292e3e1f8a51218827168cdclaireho    return error;
43985569331642446be05292e3e1f8a51218827168cdclaireho
43995569331642446be05292e3e1f8a51218827168cdclaireho  b = cpcr->Backtrack;
44005569331642446be05292e3e1f8a51218827168cdclaireho
44015569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
44025569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
44035569331642446be05292e3e1f8a51218827168cdclaireho
44045569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
44055569331642446be05292e3e1f8a51218827168cdclaireho    b[n] = GET_UShort();
44065569331642446be05292e3e1f8a51218827168cdclaireho
44075569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
44085569331642446be05292e3e1f8a51218827168cdclaireho
44095569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
44105569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
44115569331642446be05292e3e1f8a51218827168cdclaireho
44125569331642446be05292e3e1f8a51218827168cdclaireho  cpcr->InputGlyphCount = GET_UShort();
44135569331642446be05292e3e1f8a51218827168cdclaireho
44145569331642446be05292e3e1f8a51218827168cdclaireho  if ( cpcr->InputGlyphCount > ccpf2->MaxInputLength )
44155569331642446be05292e3e1f8a51218827168cdclaireho    ccpf2->MaxInputLength = cpcr->InputGlyphCount;
44165569331642446be05292e3e1f8a51218827168cdclaireho
44175569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
44185569331642446be05292e3e1f8a51218827168cdclaireho
44195569331642446be05292e3e1f8a51218827168cdclaireho  cpcr->Input = NULL;
44205569331642446be05292e3e1f8a51218827168cdclaireho
44215569331642446be05292e3e1f8a51218827168cdclaireho  count = cpcr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
44225569331642446be05292e3e1f8a51218827168cdclaireho
44235569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cpcr->Input, count, HB_UShort ) )
44245569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
44255569331642446be05292e3e1f8a51218827168cdclaireho
44265569331642446be05292e3e1f8a51218827168cdclaireho  i = cpcr->Input;
44275569331642446be05292e3e1f8a51218827168cdclaireho
44285569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
44295569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
44305569331642446be05292e3e1f8a51218827168cdclaireho
44315569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
44325569331642446be05292e3e1f8a51218827168cdclaireho    i[n] = GET_UShort();
44335569331642446be05292e3e1f8a51218827168cdclaireho
44345569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
44355569331642446be05292e3e1f8a51218827168cdclaireho
44365569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
44375569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
44385569331642446be05292e3e1f8a51218827168cdclaireho
44395569331642446be05292e3e1f8a51218827168cdclaireho  cpcr->LookaheadGlyphCount = GET_UShort();
44405569331642446be05292e3e1f8a51218827168cdclaireho
44415569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
44425569331642446be05292e3e1f8a51218827168cdclaireho
44435569331642446be05292e3e1f8a51218827168cdclaireho  if ( cpcr->LookaheadGlyphCount > ccpf2->MaxLookaheadLength )
44445569331642446be05292e3e1f8a51218827168cdclaireho    ccpf2->MaxLookaheadLength = cpcr->LookaheadGlyphCount;
44455569331642446be05292e3e1f8a51218827168cdclaireho
44465569331642446be05292e3e1f8a51218827168cdclaireho  cpcr->Lookahead = NULL;
44475569331642446be05292e3e1f8a51218827168cdclaireho
44485569331642446be05292e3e1f8a51218827168cdclaireho  count = cpcr->LookaheadGlyphCount;
44495569331642446be05292e3e1f8a51218827168cdclaireho
44505569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cpcr->Lookahead, count, HB_UShort ) )
44515569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
44525569331642446be05292e3e1f8a51218827168cdclaireho
44535569331642446be05292e3e1f8a51218827168cdclaireho  l = cpcr->Lookahead;
44545569331642446be05292e3e1f8a51218827168cdclaireho
44555569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
44565569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
44575569331642446be05292e3e1f8a51218827168cdclaireho
44585569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
44595569331642446be05292e3e1f8a51218827168cdclaireho    l[n] = GET_UShort();
44605569331642446be05292e3e1f8a51218827168cdclaireho
44615569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
44625569331642446be05292e3e1f8a51218827168cdclaireho
44635569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
44645569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
44655569331642446be05292e3e1f8a51218827168cdclaireho
44665569331642446be05292e3e1f8a51218827168cdclaireho  cpcr->PosCount = GET_UShort();
44675569331642446be05292e3e1f8a51218827168cdclaireho
44685569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
44695569331642446be05292e3e1f8a51218827168cdclaireho
44705569331642446be05292e3e1f8a51218827168cdclaireho  cpcr->PosLookupRecord = NULL;
44715569331642446be05292e3e1f8a51218827168cdclaireho
44725569331642446be05292e3e1f8a51218827168cdclaireho  count = cpcr->PosCount;
44735569331642446be05292e3e1f8a51218827168cdclaireho
44745569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cpcr->PosLookupRecord, count, HB_PosLookupRecord ) )
44755569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
44765569331642446be05292e3e1f8a51218827168cdclaireho
44775569331642446be05292e3e1f8a51218827168cdclaireho  plr = cpcr->PosLookupRecord;
44785569331642446be05292e3e1f8a51218827168cdclaireho
44795569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 4L ) )
44805569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail1;
44815569331642446be05292e3e1f8a51218827168cdclaireho
44825569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
44835569331642446be05292e3e1f8a51218827168cdclaireho  {
44845569331642446be05292e3e1f8a51218827168cdclaireho    plr[n].SequenceIndex   = GET_UShort();
44855569331642446be05292e3e1f8a51218827168cdclaireho    plr[n].LookupListIndex = GET_UShort();
44865569331642446be05292e3e1f8a51218827168cdclaireho  }
44875569331642446be05292e3e1f8a51218827168cdclaireho
44885569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
44895569331642446be05292e3e1f8a51218827168cdclaireho
44905569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
44915569331642446be05292e3e1f8a51218827168cdclaireho
44925569331642446be05292e3e1f8a51218827168cdclairehoFail1:
44935569331642446be05292e3e1f8a51218827168cdclaireho  FREE( plr );
44945569331642446be05292e3e1f8a51218827168cdclaireho
44955569331642446be05292e3e1f8a51218827168cdclairehoFail2:
44965569331642446be05292e3e1f8a51218827168cdclaireho  FREE( l );
44975569331642446be05292e3e1f8a51218827168cdclaireho
44985569331642446be05292e3e1f8a51218827168cdclairehoFail3:
44995569331642446be05292e3e1f8a51218827168cdclaireho  FREE( i );
45005569331642446be05292e3e1f8a51218827168cdclaireho
45015569331642446be05292e3e1f8a51218827168cdclairehoFail4:
45025569331642446be05292e3e1f8a51218827168cdclaireho  FREE( b );
45035569331642446be05292e3e1f8a51218827168cdclaireho  return error;
45045569331642446be05292e3e1f8a51218827168cdclaireho}
45055569331642446be05292e3e1f8a51218827168cdclaireho
45065569331642446be05292e3e1f8a51218827168cdclaireho
45075569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ChainPosClassRule( HB_ChainPosClassRule*  cpcr )
45085569331642446be05292e3e1f8a51218827168cdclaireho{
45095569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cpcr->PosLookupRecord );
45105569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cpcr->Lookahead );
45115569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cpcr->Input );
45125569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cpcr->Backtrack );
45135569331642446be05292e3e1f8a51218827168cdclaireho}
45145569331642446be05292e3e1f8a51218827168cdclaireho
45155569331642446be05292e3e1f8a51218827168cdclaireho
45165569331642446be05292e3e1f8a51218827168cdclaireho/* PosClassSet */
45175569331642446be05292e3e1f8a51218827168cdclaireho
45185569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ChainPosClassSet(
45195569331642446be05292e3e1f8a51218827168cdclaireho		   HB_ChainContextPosFormat2*  ccpf2,
45205569331642446be05292e3e1f8a51218827168cdclaireho		   HB_ChainPosClassSet*        cpcs,
45215569331642446be05292e3e1f8a51218827168cdclaireho		   HB_Stream                    stream )
45225569331642446be05292e3e1f8a51218827168cdclaireho{
45235569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
45245569331642446be05292e3e1f8a51218827168cdclaireho
45255569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort               n, m, count;
45265569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt                cur_offset, new_offset, base_offset;
45275569331642446be05292e3e1f8a51218827168cdclaireho
45285569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainPosClassRule*  cpcr;
45295569331642446be05292e3e1f8a51218827168cdclaireho
45305569331642446be05292e3e1f8a51218827168cdclaireho
45315569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
45325569331642446be05292e3e1f8a51218827168cdclaireho
45335569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
45345569331642446be05292e3e1f8a51218827168cdclaireho    return error;
45355569331642446be05292e3e1f8a51218827168cdclaireho
45365569331642446be05292e3e1f8a51218827168cdclaireho  count = cpcs->ChainPosClassRuleCount = GET_UShort();
45375569331642446be05292e3e1f8a51218827168cdclaireho
45385569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
45395569331642446be05292e3e1f8a51218827168cdclaireho
45405569331642446be05292e3e1f8a51218827168cdclaireho  cpcs->ChainPosClassRule = NULL;
45415569331642446be05292e3e1f8a51218827168cdclaireho
45425569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cpcs->ChainPosClassRule, count,
45435569331642446be05292e3e1f8a51218827168cdclaireho		    HB_ChainPosClassRule ) )
45445569331642446be05292e3e1f8a51218827168cdclaireho    return error;
45455569331642446be05292e3e1f8a51218827168cdclaireho
45465569331642446be05292e3e1f8a51218827168cdclaireho  cpcr = cpcs->ChainPosClassRule;
45475569331642446be05292e3e1f8a51218827168cdclaireho
45485569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
45495569331642446be05292e3e1f8a51218827168cdclaireho  {
45505569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
45515569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
45525569331642446be05292e3e1f8a51218827168cdclaireho
45535569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
45545569331642446be05292e3e1f8a51218827168cdclaireho
45555569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
45565569331642446be05292e3e1f8a51218827168cdclaireho
45575569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
45585569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
45595569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_ChainPosClassRule( ccpf2, &cpcr[n],
45605569331642446be05292e3e1f8a51218827168cdclaireho					   stream ) ) != HB_Err_Ok )
45615569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
45625569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
45635569331642446be05292e3e1f8a51218827168cdclaireho  }
45645569331642446be05292e3e1f8a51218827168cdclaireho
45655569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
45665569331642446be05292e3e1f8a51218827168cdclaireho
45675569331642446be05292e3e1f8a51218827168cdclairehoFail:
45685569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
45695569331642446be05292e3e1f8a51218827168cdclaireho    Free_ChainPosClassRule( &cpcr[m] );
45705569331642446be05292e3e1f8a51218827168cdclaireho
45715569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cpcr );
45725569331642446be05292e3e1f8a51218827168cdclaireho  return error;
45735569331642446be05292e3e1f8a51218827168cdclaireho}
45745569331642446be05292e3e1f8a51218827168cdclaireho
45755569331642446be05292e3e1f8a51218827168cdclaireho
45765569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ChainPosClassSet( HB_ChainPosClassSet*  cpcs )
45775569331642446be05292e3e1f8a51218827168cdclaireho{
45785569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort               n, count;
45795569331642446be05292e3e1f8a51218827168cdclaireho
45805569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainPosClassRule*  cpcr;
45815569331642446be05292e3e1f8a51218827168cdclaireho
45825569331642446be05292e3e1f8a51218827168cdclaireho
45835569331642446be05292e3e1f8a51218827168cdclaireho  if ( cpcs->ChainPosClassRule )
45845569331642446be05292e3e1f8a51218827168cdclaireho  {
45855569331642446be05292e3e1f8a51218827168cdclaireho    count = cpcs->ChainPosClassRuleCount;
45865569331642446be05292e3e1f8a51218827168cdclaireho    cpcr  = cpcs->ChainPosClassRule;
45875569331642446be05292e3e1f8a51218827168cdclaireho
45885569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
45895569331642446be05292e3e1f8a51218827168cdclaireho      Free_ChainPosClassRule( &cpcr[n] );
45905569331642446be05292e3e1f8a51218827168cdclaireho
45915569331642446be05292e3e1f8a51218827168cdclaireho    FREE( cpcr );
45925569331642446be05292e3e1f8a51218827168cdclaireho  }
45935569331642446be05292e3e1f8a51218827168cdclaireho}
45945569331642446be05292e3e1f8a51218827168cdclaireho
45955569331642446be05292e3e1f8a51218827168cdclaireho
45965569331642446be05292e3e1f8a51218827168cdclaireho/* ChainContextPosFormat2 */
45975569331642446be05292e3e1f8a51218827168cdclaireho
45985569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ChainContextPos2( HB_ChainContextPosFormat2*  ccpf2,
45995569331642446be05292e3e1f8a51218827168cdclaireho					HB_Stream                    stream )
46005569331642446be05292e3e1f8a51218827168cdclaireho{
46015569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
46025569331642446be05292e3e1f8a51218827168cdclaireho
46035569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort              n, m, count;
46045569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt               cur_offset, new_offset, base_offset;
46055569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt               backtrack_offset, input_offset, lookahead_offset;
46065569331642446be05292e3e1f8a51218827168cdclaireho
46075569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainPosClassSet*  cpcs;
46085569331642446be05292e3e1f8a51218827168cdclaireho
46095569331642446be05292e3e1f8a51218827168cdclaireho
46105569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos() - 2;
46115569331642446be05292e3e1f8a51218827168cdclaireho
46125569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
46135569331642446be05292e3e1f8a51218827168cdclaireho    return error;
46145569331642446be05292e3e1f8a51218827168cdclaireho
46155569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
46165569331642446be05292e3e1f8a51218827168cdclaireho
46175569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
46185569331642446be05292e3e1f8a51218827168cdclaireho
46195569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
46205569331642446be05292e3e1f8a51218827168cdclaireho  if ( FILE_Seek( new_offset ) ||
46215569331642446be05292e3e1f8a51218827168cdclaireho       ( error = _HB_OPEN_Load_Coverage( &ccpf2->Coverage, stream ) ) != HB_Err_Ok )
46225569331642446be05292e3e1f8a51218827168cdclaireho    return error;
46235569331642446be05292e3e1f8a51218827168cdclaireho  (void)FILE_Seek( cur_offset );
46245569331642446be05292e3e1f8a51218827168cdclaireho
46255569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 8L ) )
46265569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail5;
46275569331642446be05292e3e1f8a51218827168cdclaireho
46285569331642446be05292e3e1f8a51218827168cdclaireho  backtrack_offset = GET_UShort();
46295569331642446be05292e3e1f8a51218827168cdclaireho  input_offset     = GET_UShort();
46305569331642446be05292e3e1f8a51218827168cdclaireho  lookahead_offset = GET_UShort();
46315569331642446be05292e3e1f8a51218827168cdclaireho
46325569331642446be05292e3e1f8a51218827168cdclaireho  /* `ChainPosClassSetCount' is the upper limit for input class values,
46335569331642446be05292e3e1f8a51218827168cdclaireho     thus we read it now to make an additional safety check. No limit
46345569331642446be05292e3e1f8a51218827168cdclaireho     is known or needed for the other two class definitions          */
46355569331642446be05292e3e1f8a51218827168cdclaireho
46365569331642446be05292e3e1f8a51218827168cdclaireho  count = ccpf2->ChainPosClassSetCount = GET_UShort();
46375569331642446be05292e3e1f8a51218827168cdclaireho
46385569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
46395569331642446be05292e3e1f8a51218827168cdclaireho
46405569331642446be05292e3e1f8a51218827168cdclaireho  if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccpf2->BacktrackClassDef, 65535,
46415569331642446be05292e3e1f8a51218827168cdclaireho						       backtrack_offset, base_offset,
46425569331642446be05292e3e1f8a51218827168cdclaireho						       stream ) ) != HB_Err_Ok )
46435569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail5;
46445569331642446be05292e3e1f8a51218827168cdclaireho  if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccpf2->InputClassDef, count,
46455569331642446be05292e3e1f8a51218827168cdclaireho						       input_offset, base_offset,
46465569331642446be05292e3e1f8a51218827168cdclaireho						       stream ) ) != HB_Err_Ok )
46475569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
46485569331642446be05292e3e1f8a51218827168cdclaireho  if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccpf2->LookaheadClassDef, 65535,
46495569331642446be05292e3e1f8a51218827168cdclaireho						       lookahead_offset, base_offset,
46505569331642446be05292e3e1f8a51218827168cdclaireho						       stream ) ) != HB_Err_Ok )
46515569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
46525569331642446be05292e3e1f8a51218827168cdclaireho
46535569331642446be05292e3e1f8a51218827168cdclaireho  ccpf2->ChainPosClassSet   = NULL;
46545569331642446be05292e3e1f8a51218827168cdclaireho  ccpf2->MaxBacktrackLength = 0;
46555569331642446be05292e3e1f8a51218827168cdclaireho  ccpf2->MaxInputLength     = 0;
46565569331642446be05292e3e1f8a51218827168cdclaireho  ccpf2->MaxLookaheadLength = 0;
46575569331642446be05292e3e1f8a51218827168cdclaireho
46585569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ccpf2->ChainPosClassSet, count, HB_ChainPosClassSet ) )
46595569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
46605569331642446be05292e3e1f8a51218827168cdclaireho
46615569331642446be05292e3e1f8a51218827168cdclaireho  cpcs = ccpf2->ChainPosClassSet;
46625569331642446be05292e3e1f8a51218827168cdclaireho
46635569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
46645569331642446be05292e3e1f8a51218827168cdclaireho  {
46655569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
46665569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
46675569331642446be05292e3e1f8a51218827168cdclaireho
46685569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
46695569331642446be05292e3e1f8a51218827168cdclaireho
46705569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
46715569331642446be05292e3e1f8a51218827168cdclaireho
46725569331642446be05292e3e1f8a51218827168cdclaireho    if ( new_offset != base_offset )      /* not a NULL offset */
46735569331642446be05292e3e1f8a51218827168cdclaireho    {
46745569331642446be05292e3e1f8a51218827168cdclaireho      cur_offset = FILE_Pos();
46755569331642446be05292e3e1f8a51218827168cdclaireho      if ( FILE_Seek( new_offset ) ||
46765569331642446be05292e3e1f8a51218827168cdclaireho	   ( error = Load_ChainPosClassSet( ccpf2, &cpcs[n],
46775569331642446be05292e3e1f8a51218827168cdclaireho					    stream ) ) != HB_Err_Ok )
46785569331642446be05292e3e1f8a51218827168cdclaireho	goto Fail1;
46795569331642446be05292e3e1f8a51218827168cdclaireho      (void)FILE_Seek( cur_offset );
46805569331642446be05292e3e1f8a51218827168cdclaireho    }
46815569331642446be05292e3e1f8a51218827168cdclaireho    else
46825569331642446be05292e3e1f8a51218827168cdclaireho    {
46835569331642446be05292e3e1f8a51218827168cdclaireho      /* we create a ChainPosClassSet table with no entries */
46845569331642446be05292e3e1f8a51218827168cdclaireho
46855569331642446be05292e3e1f8a51218827168cdclaireho      ccpf2->ChainPosClassSet[n].ChainPosClassRuleCount = 0;
46865569331642446be05292e3e1f8a51218827168cdclaireho      ccpf2->ChainPosClassSet[n].ChainPosClassRule      = NULL;
46875569331642446be05292e3e1f8a51218827168cdclaireho    }
46885569331642446be05292e3e1f8a51218827168cdclaireho  }
46895569331642446be05292e3e1f8a51218827168cdclaireho
46905569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
46915569331642446be05292e3e1f8a51218827168cdclaireho
46925569331642446be05292e3e1f8a51218827168cdclairehoFail1:
46935569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
46945569331642446be05292e3e1f8a51218827168cdclaireho    Free_ChainPosClassSet( &cpcs[m] );
46955569331642446be05292e3e1f8a51218827168cdclaireho
46965569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cpcs );
46975569331642446be05292e3e1f8a51218827168cdclaireho
46985569331642446be05292e3e1f8a51218827168cdclairehoFail2:
46995569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_ClassDefinition( &ccpf2->LookaheadClassDef );
47005569331642446be05292e3e1f8a51218827168cdclaireho
47015569331642446be05292e3e1f8a51218827168cdclairehoFail3:
47025569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_ClassDefinition( &ccpf2->InputClassDef );
47035569331642446be05292e3e1f8a51218827168cdclaireho
47045569331642446be05292e3e1f8a51218827168cdclairehoFail4:
47055569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_ClassDefinition( &ccpf2->BacktrackClassDef );
47065569331642446be05292e3e1f8a51218827168cdclaireho
47075569331642446be05292e3e1f8a51218827168cdclairehoFail5:
47085569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &ccpf2->Coverage );
47095569331642446be05292e3e1f8a51218827168cdclaireho  return error;
47105569331642446be05292e3e1f8a51218827168cdclaireho}
47115569331642446be05292e3e1f8a51218827168cdclaireho
47125569331642446be05292e3e1f8a51218827168cdclaireho
47135569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ChainContextPos2( HB_ChainContextPosFormat2*  ccpf2 )
47145569331642446be05292e3e1f8a51218827168cdclaireho{
47155569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort              n, count;
47165569331642446be05292e3e1f8a51218827168cdclaireho
47175569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainPosClassSet*  cpcs;
47185569331642446be05292e3e1f8a51218827168cdclaireho
47195569331642446be05292e3e1f8a51218827168cdclaireho
47205569331642446be05292e3e1f8a51218827168cdclaireho  if ( ccpf2->ChainPosClassSet )
47215569331642446be05292e3e1f8a51218827168cdclaireho  {
47225569331642446be05292e3e1f8a51218827168cdclaireho    count = ccpf2->ChainPosClassSetCount;
47235569331642446be05292e3e1f8a51218827168cdclaireho    cpcs  = ccpf2->ChainPosClassSet;
47245569331642446be05292e3e1f8a51218827168cdclaireho
47255569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
47265569331642446be05292e3e1f8a51218827168cdclaireho      Free_ChainPosClassSet( &cpcs[n] );
47275569331642446be05292e3e1f8a51218827168cdclaireho
47285569331642446be05292e3e1f8a51218827168cdclaireho    FREE( cpcs );
47295569331642446be05292e3e1f8a51218827168cdclaireho  }
47305569331642446be05292e3e1f8a51218827168cdclaireho
47315569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_ClassDefinition( &ccpf2->LookaheadClassDef );
47325569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_ClassDefinition( &ccpf2->InputClassDef );
47335569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_ClassDefinition( &ccpf2->BacktrackClassDef );
47345569331642446be05292e3e1f8a51218827168cdclaireho
47355569331642446be05292e3e1f8a51218827168cdclaireho  _HB_OPEN_Free_Coverage( &ccpf2->Coverage );
47365569331642446be05292e3e1f8a51218827168cdclaireho}
47375569331642446be05292e3e1f8a51218827168cdclaireho
47385569331642446be05292e3e1f8a51218827168cdclaireho
47395569331642446be05292e3e1f8a51218827168cdclaireho/* ChainContextPosFormat3 */
47405569331642446be05292e3e1f8a51218827168cdclaireho
47415569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ChainContextPos3( HB_ChainContextPosFormat3*  ccpf3,
47425569331642446be05292e3e1f8a51218827168cdclaireho					HB_Stream                    stream )
47435569331642446be05292e3e1f8a51218827168cdclaireho{
47445569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
47455569331642446be05292e3e1f8a51218827168cdclaireho
47465569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort             n, nb, ni, nl, m, count;
47475569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort             backtrack_count, input_count, lookahead_count;
47485569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt              cur_offset, new_offset, base_offset;
47495569331642446be05292e3e1f8a51218827168cdclaireho
47505569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*         b;
47515569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*         i;
47525569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*         l;
47535569331642446be05292e3e1f8a51218827168cdclaireho  HB_PosLookupRecord*  plr;
47545569331642446be05292e3e1f8a51218827168cdclaireho
47555569331642446be05292e3e1f8a51218827168cdclaireho
47565569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos() - 2L;
47575569331642446be05292e3e1f8a51218827168cdclaireho
47585569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
47595569331642446be05292e3e1f8a51218827168cdclaireho    return error;
47605569331642446be05292e3e1f8a51218827168cdclaireho
47615569331642446be05292e3e1f8a51218827168cdclaireho  ccpf3->BacktrackGlyphCount = GET_UShort();
47625569331642446be05292e3e1f8a51218827168cdclaireho
47635569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
47645569331642446be05292e3e1f8a51218827168cdclaireho
47655569331642446be05292e3e1f8a51218827168cdclaireho  ccpf3->BacktrackCoverage = NULL;
47665569331642446be05292e3e1f8a51218827168cdclaireho
47675569331642446be05292e3e1f8a51218827168cdclaireho  backtrack_count = ccpf3->BacktrackGlyphCount;
47685569331642446be05292e3e1f8a51218827168cdclaireho
47695569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ccpf3->BacktrackCoverage, backtrack_count,
47705569331642446be05292e3e1f8a51218827168cdclaireho		    HB_Coverage ) )
47715569331642446be05292e3e1f8a51218827168cdclaireho    return error;
47725569331642446be05292e3e1f8a51218827168cdclaireho
47735569331642446be05292e3e1f8a51218827168cdclaireho  b = ccpf3->BacktrackCoverage;
47745569331642446be05292e3e1f8a51218827168cdclaireho
47755569331642446be05292e3e1f8a51218827168cdclaireho  for ( nb = 0; nb < backtrack_count; nb++ )
47765569331642446be05292e3e1f8a51218827168cdclaireho  {
47775569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
47785569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail4;
47795569331642446be05292e3e1f8a51218827168cdclaireho
47805569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
47815569331642446be05292e3e1f8a51218827168cdclaireho
47825569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
47835569331642446be05292e3e1f8a51218827168cdclaireho
47845569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
47855569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
47865569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != HB_Err_Ok )
47875569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail4;
47885569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
47895569331642446be05292e3e1f8a51218827168cdclaireho  }
47905569331642446be05292e3e1f8a51218827168cdclaireho
47915569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
47925569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
47935569331642446be05292e3e1f8a51218827168cdclaireho
47945569331642446be05292e3e1f8a51218827168cdclaireho  ccpf3->InputGlyphCount = GET_UShort();
47955569331642446be05292e3e1f8a51218827168cdclaireho
47965569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
47975569331642446be05292e3e1f8a51218827168cdclaireho
47985569331642446be05292e3e1f8a51218827168cdclaireho  ccpf3->InputCoverage = NULL;
47995569331642446be05292e3e1f8a51218827168cdclaireho
48005569331642446be05292e3e1f8a51218827168cdclaireho  input_count = ccpf3->InputGlyphCount;
48015569331642446be05292e3e1f8a51218827168cdclaireho
48025569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ccpf3->InputCoverage, input_count, HB_Coverage ) )
48035569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail4;
48045569331642446be05292e3e1f8a51218827168cdclaireho
48055569331642446be05292e3e1f8a51218827168cdclaireho  i = ccpf3->InputCoverage;
48065569331642446be05292e3e1f8a51218827168cdclaireho
48075569331642446be05292e3e1f8a51218827168cdclaireho  for ( ni = 0; ni < input_count; ni++ )
48085569331642446be05292e3e1f8a51218827168cdclaireho  {
48095569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
48105569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail3;
48115569331642446be05292e3e1f8a51218827168cdclaireho
48125569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
48135569331642446be05292e3e1f8a51218827168cdclaireho
48145569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
48155569331642446be05292e3e1f8a51218827168cdclaireho
48165569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
48175569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
48185569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = _HB_OPEN_Load_Coverage( &i[ni], stream ) ) != HB_Err_Ok )
48195569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail3;
48205569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
48215569331642446be05292e3e1f8a51218827168cdclaireho  }
48225569331642446be05292e3e1f8a51218827168cdclaireho
48235569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
48245569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
48255569331642446be05292e3e1f8a51218827168cdclaireho
48265569331642446be05292e3e1f8a51218827168cdclaireho  ccpf3->LookaheadGlyphCount = GET_UShort();
48275569331642446be05292e3e1f8a51218827168cdclaireho
48285569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
48295569331642446be05292e3e1f8a51218827168cdclaireho
48305569331642446be05292e3e1f8a51218827168cdclaireho  ccpf3->LookaheadCoverage = NULL;
48315569331642446be05292e3e1f8a51218827168cdclaireho
48325569331642446be05292e3e1f8a51218827168cdclaireho  lookahead_count = ccpf3->LookaheadGlyphCount;
48335569331642446be05292e3e1f8a51218827168cdclaireho
48345569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ccpf3->LookaheadCoverage, lookahead_count,
48355569331642446be05292e3e1f8a51218827168cdclaireho		    HB_Coverage ) )
48365569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail3;
48375569331642446be05292e3e1f8a51218827168cdclaireho
48385569331642446be05292e3e1f8a51218827168cdclaireho  l = ccpf3->LookaheadCoverage;
48395569331642446be05292e3e1f8a51218827168cdclaireho
48405569331642446be05292e3e1f8a51218827168cdclaireho  for ( nl = 0; nl < lookahead_count; nl++ )
48415569331642446be05292e3e1f8a51218827168cdclaireho  {
48425569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
48435569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail2;
48445569331642446be05292e3e1f8a51218827168cdclaireho
48455569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
48465569331642446be05292e3e1f8a51218827168cdclaireho
48475569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
48485569331642446be05292e3e1f8a51218827168cdclaireho
48495569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
48505569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
48515569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != HB_Err_Ok )
48525569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail2;
48535569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
48545569331642446be05292e3e1f8a51218827168cdclaireho  }
48555569331642446be05292e3e1f8a51218827168cdclaireho
48565569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
48575569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
48585569331642446be05292e3e1f8a51218827168cdclaireho
48595569331642446be05292e3e1f8a51218827168cdclaireho  ccpf3->PosCount = GET_UShort();
48605569331642446be05292e3e1f8a51218827168cdclaireho
48615569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
48625569331642446be05292e3e1f8a51218827168cdclaireho
48635569331642446be05292e3e1f8a51218827168cdclaireho  ccpf3->PosLookupRecord = NULL;
48645569331642446be05292e3e1f8a51218827168cdclaireho
48655569331642446be05292e3e1f8a51218827168cdclaireho  count = ccpf3->PosCount;
48665569331642446be05292e3e1f8a51218827168cdclaireho
48675569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ccpf3->PosLookupRecord, count, HB_PosLookupRecord ) )
48685569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
48695569331642446be05292e3e1f8a51218827168cdclaireho
48705569331642446be05292e3e1f8a51218827168cdclaireho  plr = ccpf3->PosLookupRecord;
48715569331642446be05292e3e1f8a51218827168cdclaireho
48725569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 4L ) )
48735569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail1;
48745569331642446be05292e3e1f8a51218827168cdclaireho
48755569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
48765569331642446be05292e3e1f8a51218827168cdclaireho  {
48775569331642446be05292e3e1f8a51218827168cdclaireho    plr[n].SequenceIndex   = GET_UShort();
48785569331642446be05292e3e1f8a51218827168cdclaireho    plr[n].LookupListIndex = GET_UShort();
48795569331642446be05292e3e1f8a51218827168cdclaireho  }
48805569331642446be05292e3e1f8a51218827168cdclaireho
48815569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
48825569331642446be05292e3e1f8a51218827168cdclaireho
48835569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
48845569331642446be05292e3e1f8a51218827168cdclaireho
48855569331642446be05292e3e1f8a51218827168cdclairehoFail1:
48865569331642446be05292e3e1f8a51218827168cdclaireho  FREE( plr );
48875569331642446be05292e3e1f8a51218827168cdclaireho
48885569331642446be05292e3e1f8a51218827168cdclairehoFail2:
48895569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < nl; m++ )
48905569331642446be05292e3e1f8a51218827168cdclaireho    _HB_OPEN_Free_Coverage( &l[m] );
48915569331642446be05292e3e1f8a51218827168cdclaireho
48925569331642446be05292e3e1f8a51218827168cdclaireho  FREE( l );
48935569331642446be05292e3e1f8a51218827168cdclaireho
48945569331642446be05292e3e1f8a51218827168cdclairehoFail3:
48955569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < ni; m++ )
48965569331642446be05292e3e1f8a51218827168cdclaireho    _HB_OPEN_Free_Coverage( &i[m] );
48975569331642446be05292e3e1f8a51218827168cdclaireho
48985569331642446be05292e3e1f8a51218827168cdclaireho  FREE( i );
48995569331642446be05292e3e1f8a51218827168cdclaireho
49005569331642446be05292e3e1f8a51218827168cdclairehoFail4:
49015569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < nb; m++ )
49025569331642446be05292e3e1f8a51218827168cdclaireho    _HB_OPEN_Free_Coverage( &b[m] );
49035569331642446be05292e3e1f8a51218827168cdclaireho
49045569331642446be05292e3e1f8a51218827168cdclaireho  FREE( b );
49055569331642446be05292e3e1f8a51218827168cdclaireho  return error;
49065569331642446be05292e3e1f8a51218827168cdclaireho}
49075569331642446be05292e3e1f8a51218827168cdclaireho
49085569331642446be05292e3e1f8a51218827168cdclaireho
49095569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ChainContextPos3( HB_ChainContextPosFormat3*  ccpf3 )
49105569331642446be05292e3e1f8a51218827168cdclaireho{
49115569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort      n, count;
49125569331642446be05292e3e1f8a51218827168cdclaireho
49135569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*  c;
49145569331642446be05292e3e1f8a51218827168cdclaireho
49155569331642446be05292e3e1f8a51218827168cdclaireho
49165569331642446be05292e3e1f8a51218827168cdclaireho  FREE( ccpf3->PosLookupRecord );
49175569331642446be05292e3e1f8a51218827168cdclaireho
49185569331642446be05292e3e1f8a51218827168cdclaireho  if ( ccpf3->LookaheadCoverage )
49195569331642446be05292e3e1f8a51218827168cdclaireho  {
49205569331642446be05292e3e1f8a51218827168cdclaireho    count = ccpf3->LookaheadGlyphCount;
49215569331642446be05292e3e1f8a51218827168cdclaireho    c     = ccpf3->LookaheadCoverage;
49225569331642446be05292e3e1f8a51218827168cdclaireho
49235569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
49245569331642446be05292e3e1f8a51218827168cdclaireho      _HB_OPEN_Free_Coverage( &c[n] );
49255569331642446be05292e3e1f8a51218827168cdclaireho
49265569331642446be05292e3e1f8a51218827168cdclaireho    FREE( c );
49275569331642446be05292e3e1f8a51218827168cdclaireho  }
49285569331642446be05292e3e1f8a51218827168cdclaireho
49295569331642446be05292e3e1f8a51218827168cdclaireho  if ( ccpf3->InputCoverage )
49305569331642446be05292e3e1f8a51218827168cdclaireho  {
49315569331642446be05292e3e1f8a51218827168cdclaireho    count = ccpf3->InputGlyphCount;
49325569331642446be05292e3e1f8a51218827168cdclaireho    c     = ccpf3->InputCoverage;
49335569331642446be05292e3e1f8a51218827168cdclaireho
49345569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
49355569331642446be05292e3e1f8a51218827168cdclaireho      _HB_OPEN_Free_Coverage( &c[n] );
49365569331642446be05292e3e1f8a51218827168cdclaireho
49375569331642446be05292e3e1f8a51218827168cdclaireho    FREE( c );
49385569331642446be05292e3e1f8a51218827168cdclaireho  }
49395569331642446be05292e3e1f8a51218827168cdclaireho
49405569331642446be05292e3e1f8a51218827168cdclaireho  if ( ccpf3->BacktrackCoverage )
49415569331642446be05292e3e1f8a51218827168cdclaireho  {
49425569331642446be05292e3e1f8a51218827168cdclaireho    count = ccpf3->BacktrackGlyphCount;
49435569331642446be05292e3e1f8a51218827168cdclaireho    c     = ccpf3->BacktrackCoverage;
49445569331642446be05292e3e1f8a51218827168cdclaireho
49455569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
49465569331642446be05292e3e1f8a51218827168cdclaireho      _HB_OPEN_Free_Coverage( &c[n] );
49475569331642446be05292e3e1f8a51218827168cdclaireho
49485569331642446be05292e3e1f8a51218827168cdclaireho    FREE( c );
49495569331642446be05292e3e1f8a51218827168cdclaireho  }
49505569331642446be05292e3e1f8a51218827168cdclaireho}
49515569331642446be05292e3e1f8a51218827168cdclaireho
49525569331642446be05292e3e1f8a51218827168cdclaireho
49535569331642446be05292e3e1f8a51218827168cdclaireho/* ChainContextPos */
49545569331642446be05292e3e1f8a51218827168cdclaireho
49555569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ChainContextPos( HB_GPOS_SubTable* st,
49565569331642446be05292e3e1f8a51218827168cdclaireho				       HB_Stream             stream )
49575569331642446be05292e3e1f8a51218827168cdclaireho{
49585569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error  error;
49595569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainContextPos*  ccp = &st->chain;
49605569331642446be05292e3e1f8a51218827168cdclaireho
49615569331642446be05292e3e1f8a51218827168cdclaireho
49625569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
49635569331642446be05292e3e1f8a51218827168cdclaireho    return error;
49645569331642446be05292e3e1f8a51218827168cdclaireho
49655569331642446be05292e3e1f8a51218827168cdclaireho  ccp->PosFormat = GET_UShort();
49665569331642446be05292e3e1f8a51218827168cdclaireho
49675569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
49685569331642446be05292e3e1f8a51218827168cdclaireho
49695569331642446be05292e3e1f8a51218827168cdclaireho  switch ( ccp->PosFormat )
49705569331642446be05292e3e1f8a51218827168cdclaireho  {
49715569331642446be05292e3e1f8a51218827168cdclaireho  case 1:
49725569331642446be05292e3e1f8a51218827168cdclaireho    return Load_ChainContextPos1( &ccp->ccpf.ccpf1, stream );
49735569331642446be05292e3e1f8a51218827168cdclaireho
49745569331642446be05292e3e1f8a51218827168cdclaireho  case 2:
49755569331642446be05292e3e1f8a51218827168cdclaireho    return Load_ChainContextPos2( &ccp->ccpf.ccpf2, stream );
49765569331642446be05292e3e1f8a51218827168cdclaireho
49775569331642446be05292e3e1f8a51218827168cdclaireho  case 3:
49785569331642446be05292e3e1f8a51218827168cdclaireho    return Load_ChainContextPos3( &ccp->ccpf.ccpf3, stream );
49795569331642446be05292e3e1f8a51218827168cdclaireho
49805569331642446be05292e3e1f8a51218827168cdclaireho  default:
49815569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable_Format);
49825569331642446be05292e3e1f8a51218827168cdclaireho  }
49835569331642446be05292e3e1f8a51218827168cdclaireho
49845569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;               /* never reached */
49855569331642446be05292e3e1f8a51218827168cdclaireho}
49865569331642446be05292e3e1f8a51218827168cdclaireho
49875569331642446be05292e3e1f8a51218827168cdclaireho
49885569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ChainContextPos( HB_GPOS_SubTable* st )
49895569331642446be05292e3e1f8a51218827168cdclaireho{
49905569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainContextPos*  ccp = &st->chain;
49915569331642446be05292e3e1f8a51218827168cdclaireho
49925569331642446be05292e3e1f8a51218827168cdclaireho  switch ( ccp->PosFormat )
49935569331642446be05292e3e1f8a51218827168cdclaireho  {
49945569331642446be05292e3e1f8a51218827168cdclaireho  case 1:  Free_ChainContextPos1( &ccp->ccpf.ccpf1 ); break;
49955569331642446be05292e3e1f8a51218827168cdclaireho  case 2:  Free_ChainContextPos2( &ccp->ccpf.ccpf2 ); break;
49965569331642446be05292e3e1f8a51218827168cdclaireho  case 3:  Free_ChainContextPos3( &ccp->ccpf.ccpf3 ); break;
49975569331642446be05292e3e1f8a51218827168cdclaireho  default:						      break;
49985569331642446be05292e3e1f8a51218827168cdclaireho  }
49995569331642446be05292e3e1f8a51218827168cdclaireho}
50005569331642446be05292e3e1f8a51218827168cdclaireho
50015569331642446be05292e3e1f8a51218827168cdclaireho
50025569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_ChainContextPos1(
50035569331642446be05292e3e1f8a51218827168cdclaireho		   GPOS_Instance*               gpi,
50045569331642446be05292e3e1f8a51218827168cdclaireho		   HB_ChainContextPosFormat1*  ccpf1,
50055569331642446be05292e3e1f8a51218827168cdclaireho		   HB_Buffer                   buffer,
50065569331642446be05292e3e1f8a51218827168cdclaireho		   HB_UShort                    flags,
50075569331642446be05292e3e1f8a51218827168cdclaireho		   HB_UShort                    context_length,
50085569331642446be05292e3e1f8a51218827168cdclaireho		   int                          nesting_level )
50095569331642446be05292e3e1f8a51218827168cdclaireho{
50105569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          index, property;
50115569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          i, j, k, num_cpr;
50125569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          bgc, igc, lgc;
50135569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error           error;
50145569331642446be05292e3e1f8a51218827168cdclaireho  HB_GPOSHeader*    gpos = gpi->gpos;
50155569331642446be05292e3e1f8a51218827168cdclaireho
50165569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainPosRule*  cpr;
50175569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainPosRule   curr_cpr;
50185569331642446be05292e3e1f8a51218827168cdclaireho  HB_GDEFHeader*    gdef;
50195569331642446be05292e3e1f8a51218827168cdclaireho
50205569331642446be05292e3e1f8a51218827168cdclaireho
50215569331642446be05292e3e1f8a51218827168cdclaireho  gdef = gpos->gdef;
50225569331642446be05292e3e1f8a51218827168cdclaireho
50235569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
50245569331642446be05292e3e1f8a51218827168cdclaireho    return error;
50255569331642446be05292e3e1f8a51218827168cdclaireho
50265569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Coverage_Index( &ccpf1->Coverage, IN_CURGLYPH(), &index );
50275569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
50285569331642446be05292e3e1f8a51218827168cdclaireho    return error;
50295569331642446be05292e3e1f8a51218827168cdclaireho
50305569331642446be05292e3e1f8a51218827168cdclaireho  cpr     = ccpf1->ChainPosRuleSet[index].ChainPosRule;
50315569331642446be05292e3e1f8a51218827168cdclaireho  num_cpr = ccpf1->ChainPosRuleSet[index].ChainPosRuleCount;
50325569331642446be05292e3e1f8a51218827168cdclaireho
50335569331642446be05292e3e1f8a51218827168cdclaireho  for ( k = 0; k < num_cpr; k++ )
50345569331642446be05292e3e1f8a51218827168cdclaireho  {
50355569331642446be05292e3e1f8a51218827168cdclaireho    curr_cpr = cpr[k];
50365569331642446be05292e3e1f8a51218827168cdclaireho    bgc      = curr_cpr.BacktrackGlyphCount;
50375569331642446be05292e3e1f8a51218827168cdclaireho    igc      = curr_cpr.InputGlyphCount;
50385569331642446be05292e3e1f8a51218827168cdclaireho    lgc      = curr_cpr.LookaheadGlyphCount;
50395569331642446be05292e3e1f8a51218827168cdclaireho
50405569331642446be05292e3e1f8a51218827168cdclaireho    if ( context_length != 0xFFFF && context_length < igc )
50415569331642446be05292e3e1f8a51218827168cdclaireho      goto next_chainposrule;
50425569331642446be05292e3e1f8a51218827168cdclaireho
50435569331642446be05292e3e1f8a51218827168cdclaireho    /* check whether context is too long; it is a first guess only */
50445569331642446be05292e3e1f8a51218827168cdclaireho
50455569331642446be05292e3e1f8a51218827168cdclaireho    if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
50465569331642446be05292e3e1f8a51218827168cdclaireho      goto next_chainposrule;
50475569331642446be05292e3e1f8a51218827168cdclaireho
50485569331642446be05292e3e1f8a51218827168cdclaireho    if ( bgc )
50495569331642446be05292e3e1f8a51218827168cdclaireho    {
50505569331642446be05292e3e1f8a51218827168cdclaireho      /* Since we don't know in advance the number of glyphs to inspect,
50515569331642446be05292e3e1f8a51218827168cdclaireho	 we search backwards for matches in the backtrack glyph array    */
50525569331642446be05292e3e1f8a51218827168cdclaireho
50535569331642446be05292e3e1f8a51218827168cdclaireho      for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
50545569331642446be05292e3e1f8a51218827168cdclaireho      {
50555569331642446be05292e3e1f8a51218827168cdclaireho	while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
50565569331642446be05292e3e1f8a51218827168cdclaireho	{
50575569331642446be05292e3e1f8a51218827168cdclaireho	  if ( error && error != HB_Err_Not_Covered )
50585569331642446be05292e3e1f8a51218827168cdclaireho	    return error;
50595569331642446be05292e3e1f8a51218827168cdclaireho
50605569331642446be05292e3e1f8a51218827168cdclaireho	  if ( j + 1 == bgc - i )
50615569331642446be05292e3e1f8a51218827168cdclaireho	    goto next_chainposrule;
50625569331642446be05292e3e1f8a51218827168cdclaireho	  j--;
50635569331642446be05292e3e1f8a51218827168cdclaireho	}
50645569331642446be05292e3e1f8a51218827168cdclaireho
50655569331642446be05292e3e1f8a51218827168cdclaireho	/* In OpenType 1.3, it is undefined whether the offsets of
50665569331642446be05292e3e1f8a51218827168cdclaireho	   backtrack glyphs is in logical order or not.  Version 1.4
50675569331642446be05292e3e1f8a51218827168cdclaireho	   will clarify this:
50685569331642446be05292e3e1f8a51218827168cdclaireho
50695569331642446be05292e3e1f8a51218827168cdclaireho	     Logical order -      a  b  c  d  e  f  g  h  i  j
50705569331642446be05292e3e1f8a51218827168cdclaireho					      i
50715569331642446be05292e3e1f8a51218827168cdclaireho	     Input offsets -                  0  1
50725569331642446be05292e3e1f8a51218827168cdclaireho	     Backtrack offsets -  3  2  1  0
50735569331642446be05292e3e1f8a51218827168cdclaireho	     Lookahead offsets -                    0  1  2  3           */
50745569331642446be05292e3e1f8a51218827168cdclaireho
50755569331642446be05292e3e1f8a51218827168cdclaireho	if ( IN_GLYPH( j ) != curr_cpr.Backtrack[i] )
50765569331642446be05292e3e1f8a51218827168cdclaireho	  goto next_chainposrule;
50775569331642446be05292e3e1f8a51218827168cdclaireho      }
50785569331642446be05292e3e1f8a51218827168cdclaireho    }
50795569331642446be05292e3e1f8a51218827168cdclaireho
50805569331642446be05292e3e1f8a51218827168cdclaireho    /* Start at 1 because [0] is implied */
50815569331642446be05292e3e1f8a51218827168cdclaireho
50825569331642446be05292e3e1f8a51218827168cdclaireho    for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
50835569331642446be05292e3e1f8a51218827168cdclaireho    {
50845569331642446be05292e3e1f8a51218827168cdclaireho      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
50855569331642446be05292e3e1f8a51218827168cdclaireho      {
50865569331642446be05292e3e1f8a51218827168cdclaireho	if ( error && error != HB_Err_Not_Covered )
50875569331642446be05292e3e1f8a51218827168cdclaireho	  return error;
50885569331642446be05292e3e1f8a51218827168cdclaireho
50895569331642446be05292e3e1f8a51218827168cdclaireho	if ( j + igc - i + lgc == (HB_Int)buffer->in_length )
50905569331642446be05292e3e1f8a51218827168cdclaireho	  goto next_chainposrule;
50915569331642446be05292e3e1f8a51218827168cdclaireho	j++;
50925569331642446be05292e3e1f8a51218827168cdclaireho      }
50935569331642446be05292e3e1f8a51218827168cdclaireho
50945569331642446be05292e3e1f8a51218827168cdclaireho      if ( IN_GLYPH( j ) != curr_cpr.Input[i - 1] )
50955569331642446be05292e3e1f8a51218827168cdclaireho	goto next_chainposrule;
50965569331642446be05292e3e1f8a51218827168cdclaireho    }
50975569331642446be05292e3e1f8a51218827168cdclaireho
50985569331642446be05292e3e1f8a51218827168cdclaireho    /* we are starting to check for lookahead glyphs right after the
50995569331642446be05292e3e1f8a51218827168cdclaireho       last context glyph                                            */
51005569331642446be05292e3e1f8a51218827168cdclaireho
51015569331642446be05292e3e1f8a51218827168cdclaireho    for ( i = 0; i < lgc; i++, j++ )
51025569331642446be05292e3e1f8a51218827168cdclaireho    {
51035569331642446be05292e3e1f8a51218827168cdclaireho      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
51045569331642446be05292e3e1f8a51218827168cdclaireho      {
51055569331642446be05292e3e1f8a51218827168cdclaireho	if ( error && error != HB_Err_Not_Covered )
51065569331642446be05292e3e1f8a51218827168cdclaireho	  return error;
51075569331642446be05292e3e1f8a51218827168cdclaireho
51085569331642446be05292e3e1f8a51218827168cdclaireho	if ( j + lgc - i == (HB_Int)buffer->in_length )
51095569331642446be05292e3e1f8a51218827168cdclaireho	  goto next_chainposrule;
51105569331642446be05292e3e1f8a51218827168cdclaireho	j++;
51115569331642446be05292e3e1f8a51218827168cdclaireho      }
51125569331642446be05292e3e1f8a51218827168cdclaireho
51135569331642446be05292e3e1f8a51218827168cdclaireho      if ( IN_GLYPH( j ) != curr_cpr.Lookahead[i] )
51145569331642446be05292e3e1f8a51218827168cdclaireho	goto next_chainposrule;
51155569331642446be05292e3e1f8a51218827168cdclaireho    }
51165569331642446be05292e3e1f8a51218827168cdclaireho
51175569331642446be05292e3e1f8a51218827168cdclaireho    return Do_ContextPos( gpi, igc,
51185569331642446be05292e3e1f8a51218827168cdclaireho			  curr_cpr.PosCount,
51195569331642446be05292e3e1f8a51218827168cdclaireho			  curr_cpr.PosLookupRecord,
51205569331642446be05292e3e1f8a51218827168cdclaireho			  buffer,
51215569331642446be05292e3e1f8a51218827168cdclaireho			  nesting_level );
51225569331642446be05292e3e1f8a51218827168cdclaireho
51235569331642446be05292e3e1f8a51218827168cdclaireho  next_chainposrule:
51245569331642446be05292e3e1f8a51218827168cdclaireho    ;
51255569331642446be05292e3e1f8a51218827168cdclaireho  }
51265569331642446be05292e3e1f8a51218827168cdclaireho
51275569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Not_Covered;
51285569331642446be05292e3e1f8a51218827168cdclaireho}
51295569331642446be05292e3e1f8a51218827168cdclaireho
51305569331642446be05292e3e1f8a51218827168cdclaireho
51315569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_ChainContextPos2(
51325569331642446be05292e3e1f8a51218827168cdclaireho		   GPOS_Instance*               gpi,
51335569331642446be05292e3e1f8a51218827168cdclaireho		   HB_ChainContextPosFormat2*  ccpf2,
51345569331642446be05292e3e1f8a51218827168cdclaireho		   HB_Buffer                   buffer,
51355569331642446be05292e3e1f8a51218827168cdclaireho		   HB_UShort                    flags,
51365569331642446be05292e3e1f8a51218827168cdclaireho		   HB_UShort                    context_length,
51375569331642446be05292e3e1f8a51218827168cdclaireho		   int                          nesting_level )
51385569331642446be05292e3e1f8a51218827168cdclaireho{
51395569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort              index, property;
51405569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error               error;
51415569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort              i, j, k;
51425569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort              bgc, igc, lgc;
51435569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort              known_backtrack_classes,
51445569331642446be05292e3e1f8a51218827168cdclaireho			 known_input_classes,
51455569331642446be05292e3e1f8a51218827168cdclaireho			 known_lookahead_classes;
51465569331642446be05292e3e1f8a51218827168cdclaireho
51475569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*             backtrack_classes;
51485569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*             input_classes;
51495569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*             lookahead_classes;
51505569331642446be05292e3e1f8a51218827168cdclaireho
51515569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*             bc;
51525569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*             ic;
51535569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*             lc;
51545569331642446be05292e3e1f8a51218827168cdclaireho  HB_GPOSHeader*        gpos = gpi->gpos;
51555569331642446be05292e3e1f8a51218827168cdclaireho
51565569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainPosClassSet*  cpcs;
51575569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainPosClassRule  cpcr;
51585569331642446be05292e3e1f8a51218827168cdclaireho  HB_GDEFHeader*        gdef;
51595569331642446be05292e3e1f8a51218827168cdclaireho
51605569331642446be05292e3e1f8a51218827168cdclaireho
51615569331642446be05292e3e1f8a51218827168cdclaireho  gdef = gpos->gdef;
51625569331642446be05292e3e1f8a51218827168cdclaireho
51635569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
51645569331642446be05292e3e1f8a51218827168cdclaireho    return error;
51655569331642446be05292e3e1f8a51218827168cdclaireho
51665569331642446be05292e3e1f8a51218827168cdclaireho  /* Note: The coverage table in format 2 doesn't give an index into
51675569331642446be05292e3e1f8a51218827168cdclaireho	   anything.  It just lets us know whether or not we need to
51685569331642446be05292e3e1f8a51218827168cdclaireho	   do any lookup at all.                                     */
51695569331642446be05292e3e1f8a51218827168cdclaireho
51705569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Coverage_Index( &ccpf2->Coverage, IN_CURGLYPH(), &index );
51715569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
51725569331642446be05292e3e1f8a51218827168cdclaireho    return error;
51735569331642446be05292e3e1f8a51218827168cdclaireho
5174d124f9692dc8dad8f5f77c293fe6d4ec1a0c02eaRaph Levien  if (ccpf2->MaxInputLength < 1)
5175d124f9692dc8dad8f5f77c293fe6d4ec1a0c02eaRaph Levien    return HB_Err_Not_Covered;
5176d124f9692dc8dad8f5f77c293fe6d4ec1a0c02eaRaph Levien
51775569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( backtrack_classes, ccpf2->MaxBacktrackLength, HB_UShort ) )
51785569331642446be05292e3e1f8a51218827168cdclaireho    return error;
51795569331642446be05292e3e1f8a51218827168cdclaireho  known_backtrack_classes = 0;
51805569331642446be05292e3e1f8a51218827168cdclaireho
51815569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( input_classes, ccpf2->MaxInputLength, HB_UShort ) )
51825569331642446be05292e3e1f8a51218827168cdclaireho    goto End3;
51835569331642446be05292e3e1f8a51218827168cdclaireho  known_input_classes = 1;
51845569331642446be05292e3e1f8a51218827168cdclaireho
51855569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( lookahead_classes, ccpf2->MaxLookaheadLength, HB_UShort ) )
51865569331642446be05292e3e1f8a51218827168cdclaireho    goto End2;
51875569331642446be05292e3e1f8a51218827168cdclaireho  known_lookahead_classes = 0;
51885569331642446be05292e3e1f8a51218827168cdclaireho
51895569331642446be05292e3e1f8a51218827168cdclaireho  error = _HB_OPEN_Get_Class( &ccpf2->InputClassDef, IN_CURGLYPH(),
51905569331642446be05292e3e1f8a51218827168cdclaireho		     &input_classes[0], NULL );
51915569331642446be05292e3e1f8a51218827168cdclaireho  if ( error && error != HB_Err_Not_Covered )
51925569331642446be05292e3e1f8a51218827168cdclaireho    goto End1;
51935569331642446be05292e3e1f8a51218827168cdclaireho
51945569331642446be05292e3e1f8a51218827168cdclaireho  cpcs = &ccpf2->ChainPosClassSet[input_classes[0]];
51955569331642446be05292e3e1f8a51218827168cdclaireho  if ( !cpcs )
51965569331642446be05292e3e1f8a51218827168cdclaireho  {
51975569331642446be05292e3e1f8a51218827168cdclaireho    error = ERR(HB_Err_Invalid_SubTable);
51985569331642446be05292e3e1f8a51218827168cdclaireho    goto End1;
51995569331642446be05292e3e1f8a51218827168cdclaireho  }
52005569331642446be05292e3e1f8a51218827168cdclaireho
52015569331642446be05292e3e1f8a51218827168cdclaireho  for ( k = 0; k < cpcs->ChainPosClassRuleCount; k++ )
52025569331642446be05292e3e1f8a51218827168cdclaireho  {
52035569331642446be05292e3e1f8a51218827168cdclaireho    cpcr = cpcs->ChainPosClassRule[k];
52045569331642446be05292e3e1f8a51218827168cdclaireho    bgc  = cpcr.BacktrackGlyphCount;
52055569331642446be05292e3e1f8a51218827168cdclaireho    igc  = cpcr.InputGlyphCount;
52065569331642446be05292e3e1f8a51218827168cdclaireho    lgc  = cpcr.LookaheadGlyphCount;
52075569331642446be05292e3e1f8a51218827168cdclaireho
52085569331642446be05292e3e1f8a51218827168cdclaireho    if ( context_length != 0xFFFF && context_length < igc )
52095569331642446be05292e3e1f8a51218827168cdclaireho      goto next_chainposclassrule;
52105569331642446be05292e3e1f8a51218827168cdclaireho
52115569331642446be05292e3e1f8a51218827168cdclaireho    /* check whether context is too long; it is a first guess only */
52125569331642446be05292e3e1f8a51218827168cdclaireho
52135569331642446be05292e3e1f8a51218827168cdclaireho    if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
52145569331642446be05292e3e1f8a51218827168cdclaireho      goto next_chainposclassrule;
52155569331642446be05292e3e1f8a51218827168cdclaireho
52165569331642446be05292e3e1f8a51218827168cdclaireho    if ( bgc )
52175569331642446be05292e3e1f8a51218827168cdclaireho    {
52185569331642446be05292e3e1f8a51218827168cdclaireho      /* Since we don't know in advance the number of glyphs to inspect,
52195569331642446be05292e3e1f8a51218827168cdclaireho	 we search backwards for matches in the backtrack glyph array.
52205569331642446be05292e3e1f8a51218827168cdclaireho	 Note that `known_backtrack_classes' starts at index 0.         */
52215569331642446be05292e3e1f8a51218827168cdclaireho
52225569331642446be05292e3e1f8a51218827168cdclaireho      bc       = cpcr.Backtrack;
52235569331642446be05292e3e1f8a51218827168cdclaireho
52245569331642446be05292e3e1f8a51218827168cdclaireho      for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
52255569331642446be05292e3e1f8a51218827168cdclaireho      {
52265569331642446be05292e3e1f8a51218827168cdclaireho	while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
52275569331642446be05292e3e1f8a51218827168cdclaireho	{
52285569331642446be05292e3e1f8a51218827168cdclaireho	  if ( error && error != HB_Err_Not_Covered )
52295569331642446be05292e3e1f8a51218827168cdclaireho	    goto End1;
52305569331642446be05292e3e1f8a51218827168cdclaireho
52315569331642446be05292e3e1f8a51218827168cdclaireho	  if ( j + 1 == bgc - i )
52325569331642446be05292e3e1f8a51218827168cdclaireho	    goto next_chainposclassrule;
52335569331642446be05292e3e1f8a51218827168cdclaireho	  j++;
52345569331642446be05292e3e1f8a51218827168cdclaireho	}
52355569331642446be05292e3e1f8a51218827168cdclaireho
52365569331642446be05292e3e1f8a51218827168cdclaireho	if ( i >= known_backtrack_classes )
52375569331642446be05292e3e1f8a51218827168cdclaireho	{
52385569331642446be05292e3e1f8a51218827168cdclaireho	  /* Keeps us from having to do this for each rule */
52395569331642446be05292e3e1f8a51218827168cdclaireho
52405569331642446be05292e3e1f8a51218827168cdclaireho	  error = _HB_OPEN_Get_Class( &ccpf2->BacktrackClassDef, IN_GLYPH( j ),
52415569331642446be05292e3e1f8a51218827168cdclaireho			     &backtrack_classes[i], NULL );
52425569331642446be05292e3e1f8a51218827168cdclaireho	  if ( error && error != HB_Err_Not_Covered )
52435569331642446be05292e3e1f8a51218827168cdclaireho	    goto End1;
52445569331642446be05292e3e1f8a51218827168cdclaireho	  known_backtrack_classes = i;
52455569331642446be05292e3e1f8a51218827168cdclaireho	}
52465569331642446be05292e3e1f8a51218827168cdclaireho
52475569331642446be05292e3e1f8a51218827168cdclaireho	if ( bc[i] != backtrack_classes[i] )
52485569331642446be05292e3e1f8a51218827168cdclaireho	  goto next_chainposclassrule;
52495569331642446be05292e3e1f8a51218827168cdclaireho      }
52505569331642446be05292e3e1f8a51218827168cdclaireho    }
52515569331642446be05292e3e1f8a51218827168cdclaireho
52525569331642446be05292e3e1f8a51218827168cdclaireho    ic       = cpcr.Input;
52535569331642446be05292e3e1f8a51218827168cdclaireho
52545569331642446be05292e3e1f8a51218827168cdclaireho    /* Start at 1 because [0] is implied */
52555569331642446be05292e3e1f8a51218827168cdclaireho
52565569331642446be05292e3e1f8a51218827168cdclaireho    for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
52575569331642446be05292e3e1f8a51218827168cdclaireho    {
52585569331642446be05292e3e1f8a51218827168cdclaireho      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
52595569331642446be05292e3e1f8a51218827168cdclaireho      {
52605569331642446be05292e3e1f8a51218827168cdclaireho	if ( error && error != HB_Err_Not_Covered )
52615569331642446be05292e3e1f8a51218827168cdclaireho	  goto End1;
52625569331642446be05292e3e1f8a51218827168cdclaireho
52635569331642446be05292e3e1f8a51218827168cdclaireho	if ( j + igc - i + lgc == (HB_Int)buffer->in_length )
52645569331642446be05292e3e1f8a51218827168cdclaireho	  goto next_chainposclassrule;
52655569331642446be05292e3e1f8a51218827168cdclaireho	j++;
52665569331642446be05292e3e1f8a51218827168cdclaireho      }
52675569331642446be05292e3e1f8a51218827168cdclaireho
52685569331642446be05292e3e1f8a51218827168cdclaireho      if ( i >= known_input_classes )
52695569331642446be05292e3e1f8a51218827168cdclaireho      {
52705569331642446be05292e3e1f8a51218827168cdclaireho	error = _HB_OPEN_Get_Class( &ccpf2->InputClassDef, IN_GLYPH( j ),
52715569331642446be05292e3e1f8a51218827168cdclaireho			   &input_classes[i], NULL );
52725569331642446be05292e3e1f8a51218827168cdclaireho	if ( error && error != HB_Err_Not_Covered )
52735569331642446be05292e3e1f8a51218827168cdclaireho	  goto End1;
52745569331642446be05292e3e1f8a51218827168cdclaireho	known_input_classes = i;
52755569331642446be05292e3e1f8a51218827168cdclaireho      }
52765569331642446be05292e3e1f8a51218827168cdclaireho
52775569331642446be05292e3e1f8a51218827168cdclaireho      if ( ic[i - 1] != input_classes[i] )
52785569331642446be05292e3e1f8a51218827168cdclaireho	goto next_chainposclassrule;
52795569331642446be05292e3e1f8a51218827168cdclaireho    }
52805569331642446be05292e3e1f8a51218827168cdclaireho
52815569331642446be05292e3e1f8a51218827168cdclaireho    /* we are starting to check for lookahead glyphs right after the
52825569331642446be05292e3e1f8a51218827168cdclaireho       last context glyph                                            */
52835569331642446be05292e3e1f8a51218827168cdclaireho
52845569331642446be05292e3e1f8a51218827168cdclaireho    lc       = cpcr.Lookahead;
52855569331642446be05292e3e1f8a51218827168cdclaireho
52865569331642446be05292e3e1f8a51218827168cdclaireho    for ( i = 0; i < lgc; i++, j++ )
52875569331642446be05292e3e1f8a51218827168cdclaireho    {
52885569331642446be05292e3e1f8a51218827168cdclaireho      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
52895569331642446be05292e3e1f8a51218827168cdclaireho      {
52905569331642446be05292e3e1f8a51218827168cdclaireho	if ( error && error != HB_Err_Not_Covered )
52915569331642446be05292e3e1f8a51218827168cdclaireho	  goto End1;
52925569331642446be05292e3e1f8a51218827168cdclaireho
52935569331642446be05292e3e1f8a51218827168cdclaireho	if ( j + lgc - i == (HB_Int)buffer->in_length )
52945569331642446be05292e3e1f8a51218827168cdclaireho	  goto next_chainposclassrule;
52955569331642446be05292e3e1f8a51218827168cdclaireho	j++;
52965569331642446be05292e3e1f8a51218827168cdclaireho      }
52975569331642446be05292e3e1f8a51218827168cdclaireho
52985569331642446be05292e3e1f8a51218827168cdclaireho      if ( i >= known_lookahead_classes )
52995569331642446be05292e3e1f8a51218827168cdclaireho      {
53005569331642446be05292e3e1f8a51218827168cdclaireho	error = _HB_OPEN_Get_Class( &ccpf2->LookaheadClassDef, IN_GLYPH( j ),
53015569331642446be05292e3e1f8a51218827168cdclaireho			   &lookahead_classes[i], NULL );
53025569331642446be05292e3e1f8a51218827168cdclaireho	if ( error && error != HB_Err_Not_Covered )
53035569331642446be05292e3e1f8a51218827168cdclaireho	  goto End1;
53045569331642446be05292e3e1f8a51218827168cdclaireho	known_lookahead_classes = i;
53055569331642446be05292e3e1f8a51218827168cdclaireho      }
53065569331642446be05292e3e1f8a51218827168cdclaireho
53075569331642446be05292e3e1f8a51218827168cdclaireho      if ( lc[i] != lookahead_classes[i] )
53085569331642446be05292e3e1f8a51218827168cdclaireho	goto next_chainposclassrule;
53095569331642446be05292e3e1f8a51218827168cdclaireho    }
53105569331642446be05292e3e1f8a51218827168cdclaireho
53115569331642446be05292e3e1f8a51218827168cdclaireho    error = Do_ContextPos( gpi, igc,
53125569331642446be05292e3e1f8a51218827168cdclaireho			   cpcr.PosCount,
53135569331642446be05292e3e1f8a51218827168cdclaireho			   cpcr.PosLookupRecord,
53145569331642446be05292e3e1f8a51218827168cdclaireho			   buffer,
53155569331642446be05292e3e1f8a51218827168cdclaireho			   nesting_level );
53165569331642446be05292e3e1f8a51218827168cdclaireho    goto End1;
53175569331642446be05292e3e1f8a51218827168cdclaireho
53185569331642446be05292e3e1f8a51218827168cdclaireho  next_chainposclassrule:
53195569331642446be05292e3e1f8a51218827168cdclaireho    ;
53205569331642446be05292e3e1f8a51218827168cdclaireho  }
53215569331642446be05292e3e1f8a51218827168cdclaireho
53225569331642446be05292e3e1f8a51218827168cdclaireho  error = HB_Err_Not_Covered;
53235569331642446be05292e3e1f8a51218827168cdclaireho
53245569331642446be05292e3e1f8a51218827168cdclairehoEnd1:
53255569331642446be05292e3e1f8a51218827168cdclaireho  FREE( lookahead_classes );
53265569331642446be05292e3e1f8a51218827168cdclaireho
53275569331642446be05292e3e1f8a51218827168cdclairehoEnd2:
53285569331642446be05292e3e1f8a51218827168cdclaireho  FREE( input_classes );
53295569331642446be05292e3e1f8a51218827168cdclaireho
53305569331642446be05292e3e1f8a51218827168cdclairehoEnd3:
53315569331642446be05292e3e1f8a51218827168cdclaireho  FREE( backtrack_classes );
53325569331642446be05292e3e1f8a51218827168cdclaireho  return error;
53335569331642446be05292e3e1f8a51218827168cdclaireho}
53345569331642446be05292e3e1f8a51218827168cdclaireho
53355569331642446be05292e3e1f8a51218827168cdclaireho
53365569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_ChainContextPos3(
53375569331642446be05292e3e1f8a51218827168cdclaireho		   GPOS_Instance*               gpi,
53385569331642446be05292e3e1f8a51218827168cdclaireho		   HB_ChainContextPosFormat3*  ccpf3,
53395569331642446be05292e3e1f8a51218827168cdclaireho		   HB_Buffer                   buffer,
53405569331642446be05292e3e1f8a51218827168cdclaireho		   HB_UShort                    flags,
53415569331642446be05292e3e1f8a51218827168cdclaireho		   HB_UShort                    context_length,
53425569331642446be05292e3e1f8a51218827168cdclaireho		   int                          nesting_level )
53435569331642446be05292e3e1f8a51218827168cdclaireho{
53445569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        index, i, j, property;
53455569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort        bgc, igc, lgc;
53465569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error         error;
53475569331642446be05292e3e1f8a51218827168cdclaireho  HB_GPOSHeader*  gpos = gpi->gpos;
53485569331642446be05292e3e1f8a51218827168cdclaireho
53495569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*    bc;
53505569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*    ic;
53515569331642446be05292e3e1f8a51218827168cdclaireho  HB_Coverage*    lc;
53525569331642446be05292e3e1f8a51218827168cdclaireho  HB_GDEFHeader*  gdef;
53535569331642446be05292e3e1f8a51218827168cdclaireho
53545569331642446be05292e3e1f8a51218827168cdclaireho
53555569331642446be05292e3e1f8a51218827168cdclaireho  gdef = gpos->gdef;
53565569331642446be05292e3e1f8a51218827168cdclaireho
53575569331642446be05292e3e1f8a51218827168cdclaireho  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
53585569331642446be05292e3e1f8a51218827168cdclaireho    return error;
53595569331642446be05292e3e1f8a51218827168cdclaireho
53605569331642446be05292e3e1f8a51218827168cdclaireho  bgc = ccpf3->BacktrackGlyphCount;
53615569331642446be05292e3e1f8a51218827168cdclaireho  igc = ccpf3->InputGlyphCount;
53625569331642446be05292e3e1f8a51218827168cdclaireho  lgc = ccpf3->LookaheadGlyphCount;
53635569331642446be05292e3e1f8a51218827168cdclaireho
53645569331642446be05292e3e1f8a51218827168cdclaireho  if ( context_length != 0xFFFF && context_length < igc )
53655569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
53665569331642446be05292e3e1f8a51218827168cdclaireho
53675569331642446be05292e3e1f8a51218827168cdclaireho  /* check whether context is too long; it is a first guess only */
53685569331642446be05292e3e1f8a51218827168cdclaireho
53695569331642446be05292e3e1f8a51218827168cdclaireho  if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
53705569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
53715569331642446be05292e3e1f8a51218827168cdclaireho
53725569331642446be05292e3e1f8a51218827168cdclaireho  if ( bgc )
53735569331642446be05292e3e1f8a51218827168cdclaireho  {
53745569331642446be05292e3e1f8a51218827168cdclaireho    /* Since we don't know in advance the number of glyphs to inspect,
53755569331642446be05292e3e1f8a51218827168cdclaireho       we search backwards for matches in the backtrack glyph array    */
53765569331642446be05292e3e1f8a51218827168cdclaireho
53775569331642446be05292e3e1f8a51218827168cdclaireho    bc       = ccpf3->BacktrackCoverage;
53785569331642446be05292e3e1f8a51218827168cdclaireho
53795569331642446be05292e3e1f8a51218827168cdclaireho    for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
53805569331642446be05292e3e1f8a51218827168cdclaireho    {
53815569331642446be05292e3e1f8a51218827168cdclaireho      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
53825569331642446be05292e3e1f8a51218827168cdclaireho      {
53835569331642446be05292e3e1f8a51218827168cdclaireho	if ( error && error != HB_Err_Not_Covered )
53845569331642446be05292e3e1f8a51218827168cdclaireho	  return error;
53855569331642446be05292e3e1f8a51218827168cdclaireho
53865569331642446be05292e3e1f8a51218827168cdclaireho	if ( j + 1 == bgc - i )
53875569331642446be05292e3e1f8a51218827168cdclaireho	  return HB_Err_Not_Covered;
53885569331642446be05292e3e1f8a51218827168cdclaireho	j--;
53895569331642446be05292e3e1f8a51218827168cdclaireho      }
53905569331642446be05292e3e1f8a51218827168cdclaireho
53915569331642446be05292e3e1f8a51218827168cdclaireho      error = _HB_OPEN_Coverage_Index( &bc[i], IN_GLYPH( j ), &index );
53925569331642446be05292e3e1f8a51218827168cdclaireho      if ( error )
53935569331642446be05292e3e1f8a51218827168cdclaireho	return error;
53945569331642446be05292e3e1f8a51218827168cdclaireho    }
53955569331642446be05292e3e1f8a51218827168cdclaireho  }
53965569331642446be05292e3e1f8a51218827168cdclaireho
53975569331642446be05292e3e1f8a51218827168cdclaireho  ic       = ccpf3->InputCoverage;
53985569331642446be05292e3e1f8a51218827168cdclaireho
53995569331642446be05292e3e1f8a51218827168cdclaireho  for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ )
54005569331642446be05292e3e1f8a51218827168cdclaireho  {
54015569331642446be05292e3e1f8a51218827168cdclaireho    /* We already called CHECK_Property for IN_GLYPH ( buffer->in_pos ) */
54025569331642446be05292e3e1f8a51218827168cdclaireho    while ( j > buffer->in_pos && CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
54035569331642446be05292e3e1f8a51218827168cdclaireho    {
54045569331642446be05292e3e1f8a51218827168cdclaireho      if ( error && error != HB_Err_Not_Covered )
54055569331642446be05292e3e1f8a51218827168cdclaireho	return error;
54065569331642446be05292e3e1f8a51218827168cdclaireho
54075569331642446be05292e3e1f8a51218827168cdclaireho      if ( j + igc - i + lgc == (HB_Int)buffer->in_length )
54085569331642446be05292e3e1f8a51218827168cdclaireho	return HB_Err_Not_Covered;
54095569331642446be05292e3e1f8a51218827168cdclaireho      j++;
54105569331642446be05292e3e1f8a51218827168cdclaireho    }
54115569331642446be05292e3e1f8a51218827168cdclaireho
54125569331642446be05292e3e1f8a51218827168cdclaireho    error = _HB_OPEN_Coverage_Index( &ic[i], IN_GLYPH( j ), &index );
54135569331642446be05292e3e1f8a51218827168cdclaireho    if ( error )
54145569331642446be05292e3e1f8a51218827168cdclaireho      return error;
54155569331642446be05292e3e1f8a51218827168cdclaireho  }
54165569331642446be05292e3e1f8a51218827168cdclaireho
54175569331642446be05292e3e1f8a51218827168cdclaireho  /* we are starting to check for lookahead glyphs right after the
54185569331642446be05292e3e1f8a51218827168cdclaireho     last context glyph                                            */
54195569331642446be05292e3e1f8a51218827168cdclaireho
54205569331642446be05292e3e1f8a51218827168cdclaireho  lc       = ccpf3->LookaheadCoverage;
54215569331642446be05292e3e1f8a51218827168cdclaireho
54225569331642446be05292e3e1f8a51218827168cdclaireho  for ( i = 0; i < lgc; i++, j++ )
54235569331642446be05292e3e1f8a51218827168cdclaireho  {
54245569331642446be05292e3e1f8a51218827168cdclaireho    while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
54255569331642446be05292e3e1f8a51218827168cdclaireho    {
54265569331642446be05292e3e1f8a51218827168cdclaireho      if ( error && error != HB_Err_Not_Covered )
54275569331642446be05292e3e1f8a51218827168cdclaireho	return error;
54285569331642446be05292e3e1f8a51218827168cdclaireho
54295569331642446be05292e3e1f8a51218827168cdclaireho      if ( j + lgc - i == (HB_Int)buffer->in_length )
54305569331642446be05292e3e1f8a51218827168cdclaireho	return HB_Err_Not_Covered;
54315569331642446be05292e3e1f8a51218827168cdclaireho      j++;
54325569331642446be05292e3e1f8a51218827168cdclaireho    }
54335569331642446be05292e3e1f8a51218827168cdclaireho
54345569331642446be05292e3e1f8a51218827168cdclaireho    error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index );
54355569331642446be05292e3e1f8a51218827168cdclaireho    if ( error )
54365569331642446be05292e3e1f8a51218827168cdclaireho      return error;
54375569331642446be05292e3e1f8a51218827168cdclaireho  }
54385569331642446be05292e3e1f8a51218827168cdclaireho
54395569331642446be05292e3e1f8a51218827168cdclaireho  return Do_ContextPos( gpi, igc,
54405569331642446be05292e3e1f8a51218827168cdclaireho			ccpf3->PosCount,
54415569331642446be05292e3e1f8a51218827168cdclaireho			ccpf3->PosLookupRecord,
54425569331642446be05292e3e1f8a51218827168cdclaireho			buffer,
54435569331642446be05292e3e1f8a51218827168cdclaireho			nesting_level );
54445569331642446be05292e3e1f8a51218827168cdclaireho}
54455569331642446be05292e3e1f8a51218827168cdclaireho
54465569331642446be05292e3e1f8a51218827168cdclaireho
54475569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Lookup_ChainContextPos(
54485569331642446be05292e3e1f8a51218827168cdclaireho		   GPOS_Instance*        gpi,
54495569331642446be05292e3e1f8a51218827168cdclaireho		   HB_GPOS_SubTable* st,
54505569331642446be05292e3e1f8a51218827168cdclaireho		   HB_Buffer            buffer,
54515569331642446be05292e3e1f8a51218827168cdclaireho		   HB_UShort             flags,
54525569331642446be05292e3e1f8a51218827168cdclaireho		   HB_UShort             context_length,
54535569331642446be05292e3e1f8a51218827168cdclaireho		   int                   nesting_level )
54545569331642446be05292e3e1f8a51218827168cdclaireho{
54555569331642446be05292e3e1f8a51218827168cdclaireho  HB_ChainContextPos*  ccp = &st->chain;
54565569331642446be05292e3e1f8a51218827168cdclaireho
54575569331642446be05292e3e1f8a51218827168cdclaireho  switch ( ccp->PosFormat )
54585569331642446be05292e3e1f8a51218827168cdclaireho  {
54595569331642446be05292e3e1f8a51218827168cdclaireho  case 1:
54605569331642446be05292e3e1f8a51218827168cdclaireho    return Lookup_ChainContextPos1( gpi, &ccp->ccpf.ccpf1, buffer,
54615569331642446be05292e3e1f8a51218827168cdclaireho				    flags, context_length,
54625569331642446be05292e3e1f8a51218827168cdclaireho				    nesting_level );
54635569331642446be05292e3e1f8a51218827168cdclaireho
54645569331642446be05292e3e1f8a51218827168cdclaireho  case 2:
54655569331642446be05292e3e1f8a51218827168cdclaireho    return Lookup_ChainContextPos2( gpi, &ccp->ccpf.ccpf2, buffer,
54665569331642446be05292e3e1f8a51218827168cdclaireho				    flags, context_length,
54675569331642446be05292e3e1f8a51218827168cdclaireho				    nesting_level );
54685569331642446be05292e3e1f8a51218827168cdclaireho
54695569331642446be05292e3e1f8a51218827168cdclaireho  case 3:
54705569331642446be05292e3e1f8a51218827168cdclaireho    return Lookup_ChainContextPos3( gpi, &ccp->ccpf.ccpf3, buffer,
54715569331642446be05292e3e1f8a51218827168cdclaireho				    flags, context_length,
54725569331642446be05292e3e1f8a51218827168cdclaireho				    nesting_level );
54735569331642446be05292e3e1f8a51218827168cdclaireho
54745569331642446be05292e3e1f8a51218827168cdclaireho  default:
54755569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable_Format);
54765569331642446be05292e3e1f8a51218827168cdclaireho  }
54775569331642446be05292e3e1f8a51218827168cdclaireho
54785569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;               /* never reached */
54795569331642446be05292e3e1f8a51218827168cdclaireho}
54805569331642446be05292e3e1f8a51218827168cdclaireho
54815569331642446be05292e3e1f8a51218827168cdclaireho
54825569331642446be05292e3e1f8a51218827168cdclaireho
54835569331642446be05292e3e1f8a51218827168cdclaireho/***********
54845569331642446be05292e3e1f8a51218827168cdclaireho * GPOS API
54855569331642446be05292e3e1f8a51218827168cdclaireho ***********/
54865569331642446be05292e3e1f8a51218827168cdclaireho
54875569331642446be05292e3e1f8a51218827168cdclaireho
54885569331642446be05292e3e1f8a51218827168cdclaireho
54895569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_GPOS_Select_Script( HB_GPOSHeader*  gpos,
54905569331642446be05292e3e1f8a51218827168cdclaireho				 HB_UInt         script_tag,
54915569331642446be05292e3e1f8a51218827168cdclaireho				 HB_UShort*       script_index )
54925569331642446be05292e3e1f8a51218827168cdclaireho{
54935569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          n;
54945569331642446be05292e3e1f8a51218827168cdclaireho
54955569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptList*    sl;
54965569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptRecord*  sr;
54975569331642446be05292e3e1f8a51218827168cdclaireho
54985569331642446be05292e3e1f8a51218827168cdclaireho
54995569331642446be05292e3e1f8a51218827168cdclaireho  if ( !gpos || !script_index )
55005569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
55015569331642446be05292e3e1f8a51218827168cdclaireho
55025569331642446be05292e3e1f8a51218827168cdclaireho  sl = &gpos->ScriptList;
55035569331642446be05292e3e1f8a51218827168cdclaireho  sr = sl->ScriptRecord;
55045569331642446be05292e3e1f8a51218827168cdclaireho
55055569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < sl->ScriptCount; n++ )
55065569331642446be05292e3e1f8a51218827168cdclaireho    if ( script_tag == sr[n].ScriptTag )
55075569331642446be05292e3e1f8a51218827168cdclaireho    {
55085569331642446be05292e3e1f8a51218827168cdclaireho      *script_index = n;
55095569331642446be05292e3e1f8a51218827168cdclaireho
55105569331642446be05292e3e1f8a51218827168cdclaireho      return HB_Err_Ok;
55115569331642446be05292e3e1f8a51218827168cdclaireho    }
55125569331642446be05292e3e1f8a51218827168cdclaireho
55135569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Not_Covered;
55145569331642446be05292e3e1f8a51218827168cdclaireho}
55155569331642446be05292e3e1f8a51218827168cdclaireho
55165569331642446be05292e3e1f8a51218827168cdclaireho
55175569331642446be05292e3e1f8a51218827168cdclaireho
55185569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_GPOS_Select_Language( HB_GPOSHeader*  gpos,
55195569331642446be05292e3e1f8a51218827168cdclaireho				   HB_UInt         language_tag,
55205569331642446be05292e3e1f8a51218827168cdclaireho				   HB_UShort        script_index,
55215569331642446be05292e3e1f8a51218827168cdclaireho				   HB_UShort*       language_index,
55225569331642446be05292e3e1f8a51218827168cdclaireho				   HB_UShort*       req_feature_index )
55235569331642446be05292e3e1f8a51218827168cdclaireho{
55245569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort           n;
55255569331642446be05292e3e1f8a51218827168cdclaireho
55265569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptList*     sl;
55275569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptRecord*   sr;
55285569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptTable*         s;
55295569331642446be05292e3e1f8a51218827168cdclaireho  HB_LangSysRecord*  lsr;
55305569331642446be05292e3e1f8a51218827168cdclaireho
55315569331642446be05292e3e1f8a51218827168cdclaireho
55325569331642446be05292e3e1f8a51218827168cdclaireho  if ( !gpos || !language_index || !req_feature_index )
55335569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
55345569331642446be05292e3e1f8a51218827168cdclaireho
55355569331642446be05292e3e1f8a51218827168cdclaireho  sl = &gpos->ScriptList;
55365569331642446be05292e3e1f8a51218827168cdclaireho  sr = sl->ScriptRecord;
55375569331642446be05292e3e1f8a51218827168cdclaireho
55385569331642446be05292e3e1f8a51218827168cdclaireho  if ( script_index >= sl->ScriptCount )
55395569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
55405569331642446be05292e3e1f8a51218827168cdclaireho
55415569331642446be05292e3e1f8a51218827168cdclaireho  s   = &sr[script_index].Script;
55425569331642446be05292e3e1f8a51218827168cdclaireho  lsr = s->LangSysRecord;
55435569331642446be05292e3e1f8a51218827168cdclaireho
55445569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < s->LangSysCount; n++ )
55455569331642446be05292e3e1f8a51218827168cdclaireho    if ( language_tag == lsr[n].LangSysTag )
55465569331642446be05292e3e1f8a51218827168cdclaireho    {
55475569331642446be05292e3e1f8a51218827168cdclaireho      *language_index = n;
55485569331642446be05292e3e1f8a51218827168cdclaireho      *req_feature_index = lsr[n].LangSys.ReqFeatureIndex;
55495569331642446be05292e3e1f8a51218827168cdclaireho
55505569331642446be05292e3e1f8a51218827168cdclaireho      return HB_Err_Ok;
55515569331642446be05292e3e1f8a51218827168cdclaireho    }
55525569331642446be05292e3e1f8a51218827168cdclaireho
55535569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Not_Covered;
55545569331642446be05292e3e1f8a51218827168cdclaireho}
55555569331642446be05292e3e1f8a51218827168cdclaireho
55565569331642446be05292e3e1f8a51218827168cdclaireho
55575569331642446be05292e3e1f8a51218827168cdclaireho/* selecting 0xFFFF for language_index asks for the values of the
55585569331642446be05292e3e1f8a51218827168cdclaireho   default language (DefaultLangSys)                              */
55595569331642446be05292e3e1f8a51218827168cdclaireho
55605569331642446be05292e3e1f8a51218827168cdclaireho
55615569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_GPOS_Select_Feature( HB_GPOSHeader*  gpos,
55625569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UInt         feature_tag,
55635569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort        script_index,
55645569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort        language_index,
55655569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort*       feature_index )
55665569331642446be05292e3e1f8a51218827168cdclaireho{
55675569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort           n;
55685569331642446be05292e3e1f8a51218827168cdclaireho
55695569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptList*     sl;
55705569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptRecord*   sr;
55715569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptTable*         s;
55725569331642446be05292e3e1f8a51218827168cdclaireho  HB_LangSysRecord*  lsr;
55735569331642446be05292e3e1f8a51218827168cdclaireho  HB_LangSys*        ls;
55745569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*          fi;
55755569331642446be05292e3e1f8a51218827168cdclaireho
55765569331642446be05292e3e1f8a51218827168cdclaireho  HB_FeatureList*    fl;
55775569331642446be05292e3e1f8a51218827168cdclaireho  HB_FeatureRecord*  fr;
55785569331642446be05292e3e1f8a51218827168cdclaireho
55795569331642446be05292e3e1f8a51218827168cdclaireho
55805569331642446be05292e3e1f8a51218827168cdclaireho  if ( !gpos || !feature_index )
55815569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
55825569331642446be05292e3e1f8a51218827168cdclaireho
55835569331642446be05292e3e1f8a51218827168cdclaireho  sl = &gpos->ScriptList;
55845569331642446be05292e3e1f8a51218827168cdclaireho  sr = sl->ScriptRecord;
55855569331642446be05292e3e1f8a51218827168cdclaireho
55865569331642446be05292e3e1f8a51218827168cdclaireho  fl = &gpos->FeatureList;
55875569331642446be05292e3e1f8a51218827168cdclaireho  fr = fl->FeatureRecord;
55885569331642446be05292e3e1f8a51218827168cdclaireho
55895569331642446be05292e3e1f8a51218827168cdclaireho  if ( script_index >= sl->ScriptCount )
55905569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
55915569331642446be05292e3e1f8a51218827168cdclaireho
55925569331642446be05292e3e1f8a51218827168cdclaireho  s   = &sr[script_index].Script;
55935569331642446be05292e3e1f8a51218827168cdclaireho  lsr = s->LangSysRecord;
55945569331642446be05292e3e1f8a51218827168cdclaireho
55955569331642446be05292e3e1f8a51218827168cdclaireho  if ( language_index == 0xFFFF )
55965569331642446be05292e3e1f8a51218827168cdclaireho    ls = &s->DefaultLangSys;
55975569331642446be05292e3e1f8a51218827168cdclaireho  else
55985569331642446be05292e3e1f8a51218827168cdclaireho  {
55995569331642446be05292e3e1f8a51218827168cdclaireho    if ( language_index >= s->LangSysCount )
56005569331642446be05292e3e1f8a51218827168cdclaireho      return ERR(HB_Err_Invalid_Argument);
56015569331642446be05292e3e1f8a51218827168cdclaireho
56025569331642446be05292e3e1f8a51218827168cdclaireho    ls = &lsr[language_index].LangSys;
56035569331642446be05292e3e1f8a51218827168cdclaireho  }
56045569331642446be05292e3e1f8a51218827168cdclaireho
56055569331642446be05292e3e1f8a51218827168cdclaireho  fi = ls->FeatureIndex;
56065569331642446be05292e3e1f8a51218827168cdclaireho
56075569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < ls->FeatureCount; n++ )
56085569331642446be05292e3e1f8a51218827168cdclaireho  {
56095569331642446be05292e3e1f8a51218827168cdclaireho    if ( fi[n] >= fl->FeatureCount )
56105569331642446be05292e3e1f8a51218827168cdclaireho      return ERR(HB_Err_Invalid_SubTable_Format);
56115569331642446be05292e3e1f8a51218827168cdclaireho
56125569331642446be05292e3e1f8a51218827168cdclaireho    if ( feature_tag == fr[fi[n]].FeatureTag )
56135569331642446be05292e3e1f8a51218827168cdclaireho    {
56145569331642446be05292e3e1f8a51218827168cdclaireho      *feature_index = fi[n];
56155569331642446be05292e3e1f8a51218827168cdclaireho
56165569331642446be05292e3e1f8a51218827168cdclaireho      return HB_Err_Ok;
56175569331642446be05292e3e1f8a51218827168cdclaireho    }
56185569331642446be05292e3e1f8a51218827168cdclaireho  }
56195569331642446be05292e3e1f8a51218827168cdclaireho
56205569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Not_Covered;
56215569331642446be05292e3e1f8a51218827168cdclaireho}
56225569331642446be05292e3e1f8a51218827168cdclaireho
56235569331642446be05292e3e1f8a51218827168cdclaireho
56245569331642446be05292e3e1f8a51218827168cdclaireho/* The next three functions return a null-terminated list */
56255569331642446be05292e3e1f8a51218827168cdclaireho
56265569331642446be05292e3e1f8a51218827168cdclaireho
56275569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_GPOS_Query_Scripts( HB_GPOSHeader*  gpos,
56285569331642446be05292e3e1f8a51218827168cdclaireho				 HB_UInt**       script_tag_list )
56295569331642446be05292e3e1f8a51218827168cdclaireho{
56305569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error           error;
56315569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          n;
56325569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt*          stl;
56335569331642446be05292e3e1f8a51218827168cdclaireho
56345569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptList*    sl;
56355569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptRecord*  sr;
56365569331642446be05292e3e1f8a51218827168cdclaireho
56375569331642446be05292e3e1f8a51218827168cdclaireho
56385569331642446be05292e3e1f8a51218827168cdclaireho  if ( !gpos || !script_tag_list )
56395569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
56405569331642446be05292e3e1f8a51218827168cdclaireho
56415569331642446be05292e3e1f8a51218827168cdclaireho  sl = &gpos->ScriptList;
56425569331642446be05292e3e1f8a51218827168cdclaireho  sr = sl->ScriptRecord;
56435569331642446be05292e3e1f8a51218827168cdclaireho
56445569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( stl, sl->ScriptCount + 1, HB_UInt ) )
56455569331642446be05292e3e1f8a51218827168cdclaireho    return error;
56465569331642446be05292e3e1f8a51218827168cdclaireho
56475569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < sl->ScriptCount; n++ )
56485569331642446be05292e3e1f8a51218827168cdclaireho    stl[n] = sr[n].ScriptTag;
56495569331642446be05292e3e1f8a51218827168cdclaireho  stl[n] = 0;
56505569331642446be05292e3e1f8a51218827168cdclaireho
56515569331642446be05292e3e1f8a51218827168cdclaireho  *script_tag_list = stl;
56525569331642446be05292e3e1f8a51218827168cdclaireho
56535569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
56545569331642446be05292e3e1f8a51218827168cdclaireho}
56555569331642446be05292e3e1f8a51218827168cdclaireho
56565569331642446be05292e3e1f8a51218827168cdclaireho
56575569331642446be05292e3e1f8a51218827168cdclaireho
56585569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_GPOS_Query_Languages( HB_GPOSHeader*  gpos,
56595569331642446be05292e3e1f8a51218827168cdclaireho				   HB_UShort        script_index,
56605569331642446be05292e3e1f8a51218827168cdclaireho				   HB_UInt**       language_tag_list )
56615569331642446be05292e3e1f8a51218827168cdclaireho{
56625569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error            error;
56635569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort           n;
56645569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt*           ltl;
56655569331642446be05292e3e1f8a51218827168cdclaireho
56665569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptList*     sl;
56675569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptRecord*   sr;
56685569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptTable*    s;
56695569331642446be05292e3e1f8a51218827168cdclaireho  HB_LangSysRecord*  lsr;
56705569331642446be05292e3e1f8a51218827168cdclaireho
56715569331642446be05292e3e1f8a51218827168cdclaireho
56725569331642446be05292e3e1f8a51218827168cdclaireho  if ( !gpos || !language_tag_list )
56735569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
56745569331642446be05292e3e1f8a51218827168cdclaireho
56755569331642446be05292e3e1f8a51218827168cdclaireho  sl = &gpos->ScriptList;
56765569331642446be05292e3e1f8a51218827168cdclaireho  sr = sl->ScriptRecord;
56775569331642446be05292e3e1f8a51218827168cdclaireho
56785569331642446be05292e3e1f8a51218827168cdclaireho  if ( script_index >= sl->ScriptCount )
56795569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
56805569331642446be05292e3e1f8a51218827168cdclaireho
56815569331642446be05292e3e1f8a51218827168cdclaireho  s   = &sr[script_index].Script;
56825569331642446be05292e3e1f8a51218827168cdclaireho  lsr = s->LangSysRecord;
56835569331642446be05292e3e1f8a51218827168cdclaireho
56845569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ltl, s->LangSysCount + 1, HB_UInt ) )
56855569331642446be05292e3e1f8a51218827168cdclaireho    return error;
56865569331642446be05292e3e1f8a51218827168cdclaireho
56875569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < s->LangSysCount; n++ )
56885569331642446be05292e3e1f8a51218827168cdclaireho    ltl[n] = lsr[n].LangSysTag;
56895569331642446be05292e3e1f8a51218827168cdclaireho  ltl[n] = 0;
56905569331642446be05292e3e1f8a51218827168cdclaireho
56915569331642446be05292e3e1f8a51218827168cdclaireho  *language_tag_list = ltl;
56925569331642446be05292e3e1f8a51218827168cdclaireho
56935569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
56945569331642446be05292e3e1f8a51218827168cdclaireho}
56955569331642446be05292e3e1f8a51218827168cdclaireho
56965569331642446be05292e3e1f8a51218827168cdclaireho
56975569331642446be05292e3e1f8a51218827168cdclaireho/* selecting 0xFFFF for language_index asks for the values of the
56985569331642446be05292e3e1f8a51218827168cdclaireho   default language (DefaultLangSys)                              */
56995569331642446be05292e3e1f8a51218827168cdclaireho
57005569331642446be05292e3e1f8a51218827168cdclaireho
57015569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_GPOS_Query_Features( HB_GPOSHeader*  gpos,
57025569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort        script_index,
57035569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort        language_index,
57045569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UInt**       feature_tag_list )
57055569331642446be05292e3e1f8a51218827168cdclaireho{
57065569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort           n;
57075569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error            error;
57085569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt*           ftl;
57095569331642446be05292e3e1f8a51218827168cdclaireho
57105569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptList*     sl;
57115569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptRecord*   sr;
57125569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptTable*    s;
57135569331642446be05292e3e1f8a51218827168cdclaireho  HB_LangSysRecord*  lsr;
57145569331642446be05292e3e1f8a51218827168cdclaireho  HB_LangSys*        ls;
57155569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*          fi;
57165569331642446be05292e3e1f8a51218827168cdclaireho
57175569331642446be05292e3e1f8a51218827168cdclaireho  HB_FeatureList*    fl;
57185569331642446be05292e3e1f8a51218827168cdclaireho  HB_FeatureRecord*  fr;
57195569331642446be05292e3e1f8a51218827168cdclaireho
57205569331642446be05292e3e1f8a51218827168cdclaireho
57215569331642446be05292e3e1f8a51218827168cdclaireho  if ( !gpos || !feature_tag_list )
57225569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
57235569331642446be05292e3e1f8a51218827168cdclaireho
57245569331642446be05292e3e1f8a51218827168cdclaireho  sl = &gpos->ScriptList;
57255569331642446be05292e3e1f8a51218827168cdclaireho  sr = sl->ScriptRecord;
57265569331642446be05292e3e1f8a51218827168cdclaireho
57275569331642446be05292e3e1f8a51218827168cdclaireho  fl = &gpos->FeatureList;
57285569331642446be05292e3e1f8a51218827168cdclaireho  fr = fl->FeatureRecord;
57295569331642446be05292e3e1f8a51218827168cdclaireho
57305569331642446be05292e3e1f8a51218827168cdclaireho  if ( script_index >= sl->ScriptCount )
57315569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
57325569331642446be05292e3e1f8a51218827168cdclaireho
57335569331642446be05292e3e1f8a51218827168cdclaireho  s   = &sr[script_index].Script;
57345569331642446be05292e3e1f8a51218827168cdclaireho  lsr = s->LangSysRecord;
57355569331642446be05292e3e1f8a51218827168cdclaireho
57365569331642446be05292e3e1f8a51218827168cdclaireho  if ( language_index == 0xFFFF )
57375569331642446be05292e3e1f8a51218827168cdclaireho    ls = &s->DefaultLangSys;
57385569331642446be05292e3e1f8a51218827168cdclaireho  else
57395569331642446be05292e3e1f8a51218827168cdclaireho  {
57405569331642446be05292e3e1f8a51218827168cdclaireho    if ( language_index >= s->LangSysCount )
57415569331642446be05292e3e1f8a51218827168cdclaireho      return ERR(HB_Err_Invalid_Argument);
57425569331642446be05292e3e1f8a51218827168cdclaireho
57435569331642446be05292e3e1f8a51218827168cdclaireho    ls = &lsr[language_index].LangSys;
57445569331642446be05292e3e1f8a51218827168cdclaireho  }
57455569331642446be05292e3e1f8a51218827168cdclaireho
57465569331642446be05292e3e1f8a51218827168cdclaireho  fi = ls->FeatureIndex;
57475569331642446be05292e3e1f8a51218827168cdclaireho
57485569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ftl, ls->FeatureCount + 1, HB_UInt ) )
57495569331642446be05292e3e1f8a51218827168cdclaireho    return error;
57505569331642446be05292e3e1f8a51218827168cdclaireho
57515569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < ls->FeatureCount; n++ )
57525569331642446be05292e3e1f8a51218827168cdclaireho  {
57535569331642446be05292e3e1f8a51218827168cdclaireho    if ( fi[n] >= fl->FeatureCount )
57545569331642446be05292e3e1f8a51218827168cdclaireho    {
57555569331642446be05292e3e1f8a51218827168cdclaireho      FREE( ftl );
57565569331642446be05292e3e1f8a51218827168cdclaireho      return ERR(HB_Err_Invalid_SubTable_Format);
57575569331642446be05292e3e1f8a51218827168cdclaireho    }
57585569331642446be05292e3e1f8a51218827168cdclaireho    ftl[n] = fr[fi[n]].FeatureTag;
57595569331642446be05292e3e1f8a51218827168cdclaireho  }
57605569331642446be05292e3e1f8a51218827168cdclaireho  ftl[n] = 0;
57615569331642446be05292e3e1f8a51218827168cdclaireho
57625569331642446be05292e3e1f8a51218827168cdclaireho  *feature_tag_list = ftl;
57635569331642446be05292e3e1f8a51218827168cdclaireho
57645569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
57655569331642446be05292e3e1f8a51218827168cdclaireho}
57665569331642446be05292e3e1f8a51218827168cdclaireho
57675569331642446be05292e3e1f8a51218827168cdclaireho
57685569331642446be05292e3e1f8a51218827168cdclaireho/* Do an individual subtable lookup.  Returns HB_Err_Ok if positioning
57695569331642446be05292e3e1f8a51218827168cdclaireho   has been done, or HB_Err_Not_Covered if not.                        */
57705569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  GPOS_Do_Glyph_Lookup( GPOS_Instance*    gpi,
57715569331642446be05292e3e1f8a51218827168cdclaireho				       HB_UShort         lookup_index,
57725569331642446be05292e3e1f8a51218827168cdclaireho				       HB_Buffer        buffer,
57735569331642446be05292e3e1f8a51218827168cdclaireho				       HB_UShort         context_length,
57745569331642446be05292e3e1f8a51218827168cdclaireho				       int               nesting_level )
57755569331642446be05292e3e1f8a51218827168cdclaireho{
57765569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error             error = HB_Err_Not_Covered;
57775569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort            i, flags, lookup_count;
57785569331642446be05292e3e1f8a51218827168cdclaireho  HB_GPOSHeader*       gpos = gpi->gpos;
57795569331642446be05292e3e1f8a51218827168cdclaireho  HB_Lookup*           lo;
57805569331642446be05292e3e1f8a51218827168cdclaireho  int		       lookup_type;
57815569331642446be05292e3e1f8a51218827168cdclaireho
57825569331642446be05292e3e1f8a51218827168cdclaireho
57835569331642446be05292e3e1f8a51218827168cdclaireho  nesting_level++;
57845569331642446be05292e3e1f8a51218827168cdclaireho
57855569331642446be05292e3e1f8a51218827168cdclaireho  if ( nesting_level > HB_MAX_NESTING_LEVEL )
57865569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Not_Covered); /* ERR() call intended */
57875569331642446be05292e3e1f8a51218827168cdclaireho
57885569331642446be05292e3e1f8a51218827168cdclaireho  lookup_count = gpos->LookupList.LookupCount;
57895569331642446be05292e3e1f8a51218827168cdclaireho  if (lookup_index >= lookup_count)
57905569331642446be05292e3e1f8a51218827168cdclaireho    return error;
57915569331642446be05292e3e1f8a51218827168cdclaireho
57925569331642446be05292e3e1f8a51218827168cdclaireho  lo    = &gpos->LookupList.Lookup[lookup_index];
57935569331642446be05292e3e1f8a51218827168cdclaireho  flags = lo->LookupFlag;
57945569331642446be05292e3e1f8a51218827168cdclaireho  lookup_type = lo->LookupType;
57955569331642446be05292e3e1f8a51218827168cdclaireho
57965569331642446be05292e3e1f8a51218827168cdclaireho  for ( i = 0; i < lo->SubTableCount; i++ )
57975569331642446be05292e3e1f8a51218827168cdclaireho  {
57985569331642446be05292e3e1f8a51218827168cdclaireho    HB_GPOS_SubTable *st = &lo->SubTable[i].st.gpos;
57995569331642446be05292e3e1f8a51218827168cdclaireho
58005569331642446be05292e3e1f8a51218827168cdclaireho    switch (lookup_type) {
58015569331642446be05292e3e1f8a51218827168cdclaireho      case HB_GPOS_LOOKUP_SINGLE:
58025569331642446be05292e3e1f8a51218827168cdclaireho        error = Lookup_SinglePos	( gpi, st, buffer, flags, context_length, nesting_level ); break;
58035569331642446be05292e3e1f8a51218827168cdclaireho      case HB_GPOS_LOOKUP_PAIR:
58045569331642446be05292e3e1f8a51218827168cdclaireho	error = Lookup_PairPos		( gpi, st, buffer, flags, context_length, nesting_level ); break;
58055569331642446be05292e3e1f8a51218827168cdclaireho      case HB_GPOS_LOOKUP_CURSIVE:
58065569331642446be05292e3e1f8a51218827168cdclaireho	error = Lookup_CursivePos	( gpi, st, buffer, flags, context_length, nesting_level ); break;
58075569331642446be05292e3e1f8a51218827168cdclaireho      case HB_GPOS_LOOKUP_MARKBASE:
58085569331642446be05292e3e1f8a51218827168cdclaireho	error = Lookup_MarkBasePos	( gpi, st, buffer, flags, context_length, nesting_level ); break;
58095569331642446be05292e3e1f8a51218827168cdclaireho      case HB_GPOS_LOOKUP_MARKLIG:
58105569331642446be05292e3e1f8a51218827168cdclaireho	error = Lookup_MarkLigPos	( gpi, st, buffer, flags, context_length, nesting_level ); break;
58115569331642446be05292e3e1f8a51218827168cdclaireho      case HB_GPOS_LOOKUP_MARKMARK:
58125569331642446be05292e3e1f8a51218827168cdclaireho	error = Lookup_MarkMarkPos	( gpi, st, buffer, flags, context_length, nesting_level ); break;
58135569331642446be05292e3e1f8a51218827168cdclaireho      case HB_GPOS_LOOKUP_CONTEXT:
58145569331642446be05292e3e1f8a51218827168cdclaireho	error = Lookup_ContextPos	( gpi, st, buffer, flags, context_length, nesting_level ); break;
58155569331642446be05292e3e1f8a51218827168cdclaireho      case HB_GPOS_LOOKUP_CHAIN:
58165569331642446be05292e3e1f8a51218827168cdclaireho	error = Lookup_ChainContextPos	( gpi, st, buffer, flags, context_length, nesting_level ); break;
58175569331642446be05292e3e1f8a51218827168cdclaireho    /*case HB_GPOS_LOOKUP_EXTENSION:
58185569331642446be05292e3e1f8a51218827168cdclaireho	error = Lookup_ExtensionPos	( gpi, st, buffer, flags, context_length, nesting_level ); break;*/
58195569331642446be05292e3e1f8a51218827168cdclaireho      default:
58205569331642446be05292e3e1f8a51218827168cdclaireho	error = HB_Err_Not_Covered;
58215569331642446be05292e3e1f8a51218827168cdclaireho    }
58225569331642446be05292e3e1f8a51218827168cdclaireho
58235569331642446be05292e3e1f8a51218827168cdclaireho    /* Check whether we have a successful positioning or an error other
58245569331642446be05292e3e1f8a51218827168cdclaireho       than HB_Err_Not_Covered                                         */
58255569331642446be05292e3e1f8a51218827168cdclaireho    if ( error != HB_Err_Not_Covered )
58265569331642446be05292e3e1f8a51218827168cdclaireho      return error;
58275569331642446be05292e3e1f8a51218827168cdclaireho  }
58285569331642446be05292e3e1f8a51218827168cdclaireho
58295569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Not_Covered;
58305569331642446be05292e3e1f8a51218827168cdclaireho}
58315569331642446be05292e3e1f8a51218827168cdclaireho
58325569331642446be05292e3e1f8a51218827168cdclaireho
58335569331642446be05292e3e1f8a51218827168cdclairehoHB_INTERNAL HB_Error
58345569331642446be05292e3e1f8a51218827168cdclaireho_HB_GPOS_Load_SubTable( HB_GPOS_SubTable* st,
58355569331642446be05292e3e1f8a51218827168cdclaireho			HB_Stream         stream,
58365569331642446be05292e3e1f8a51218827168cdclaireho			HB_UShort         lookup_type )
58375569331642446be05292e3e1f8a51218827168cdclaireho{
58385569331642446be05292e3e1f8a51218827168cdclaireho  switch ( lookup_type ) {
58395569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GPOS_LOOKUP_SINGLE:		return Load_SinglePos		( st, stream );
58405569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GPOS_LOOKUP_PAIR:		return Load_PairPos		( st, stream );
58415569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GPOS_LOOKUP_CURSIVE:	return Load_CursivePos		( st, stream );
58425569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GPOS_LOOKUP_MARKBASE:	return Load_MarkBasePos		( st, stream );
58435569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GPOS_LOOKUP_MARKLIG:	return Load_MarkLigPos		( st, stream );
58445569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GPOS_LOOKUP_MARKMARK:	return Load_MarkMarkPos		( st, stream );
58455569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GPOS_LOOKUP_CONTEXT:	return Load_ContextPos		( st, stream );
58465569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GPOS_LOOKUP_CHAIN:		return Load_ChainContextPos	( st, stream );
58475569331642446be05292e3e1f8a51218827168cdclaireho  /*case HB_GPOS_LOOKUP_EXTENSION:	return Load_ExtensionPos	( st, stream );*/
58485569331642446be05292e3e1f8a51218827168cdclaireho    default:				return ERR(HB_Err_Invalid_SubTable_Format);
58495569331642446be05292e3e1f8a51218827168cdclaireho  }
58505569331642446be05292e3e1f8a51218827168cdclaireho}
58515569331642446be05292e3e1f8a51218827168cdclaireho
58525569331642446be05292e3e1f8a51218827168cdclaireho
58535569331642446be05292e3e1f8a51218827168cdclairehoHB_INTERNAL void
58545569331642446be05292e3e1f8a51218827168cdclaireho_HB_GPOS_Free_SubTable( HB_GPOS_SubTable* st,
58555569331642446be05292e3e1f8a51218827168cdclaireho			HB_UShort         lookup_type )
58565569331642446be05292e3e1f8a51218827168cdclaireho{
58575569331642446be05292e3e1f8a51218827168cdclaireho  switch ( lookup_type ) {
58585569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GPOS_LOOKUP_SINGLE:		Free_SinglePos		( st ); return;
58595569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GPOS_LOOKUP_PAIR:		Free_PairPos		( st ); return;
58605569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GPOS_LOOKUP_CURSIVE:	Free_CursivePos		( st ); return;
58615569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GPOS_LOOKUP_MARKBASE:	Free_MarkBasePos	( st ); return;
58625569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GPOS_LOOKUP_MARKLIG:	Free_MarkLigPos		( st ); return;
58635569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GPOS_LOOKUP_MARKMARK:	Free_MarkMarkPos	( st ); return;
58645569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GPOS_LOOKUP_CONTEXT:	Free_ContextPos		( st ); return;
58655569331642446be05292e3e1f8a51218827168cdclaireho    case HB_GPOS_LOOKUP_CHAIN:		Free_ChainContextPos	( st ); return;
58665569331642446be05292e3e1f8a51218827168cdclaireho  /*case HB_GPOS_LOOKUP_EXTENSION:	Free_ExtensionPos	( st ); return;*/
58675569331642446be05292e3e1f8a51218827168cdclaireho    default:									return;
58685569331642446be05292e3e1f8a51218827168cdclaireho  }
58695569331642446be05292e3e1f8a51218827168cdclaireho}
58705569331642446be05292e3e1f8a51218827168cdclaireho
58715569331642446be05292e3e1f8a51218827168cdclaireho
58725569331642446be05292e3e1f8a51218827168cdclaireho/* apply one lookup to the input string object */
58735569331642446be05292e3e1f8a51218827168cdclaireho
58745569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  GPOS_Do_String_Lookup( GPOS_Instance*    gpi,
58755569331642446be05292e3e1f8a51218827168cdclaireho				   HB_UShort         lookup_index,
58765569331642446be05292e3e1f8a51218827168cdclaireho				   HB_Buffer        buffer )
58775569331642446be05292e3e1f8a51218827168cdclaireho{
58785569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error         error, retError = HB_Err_Not_Covered;
58795569331642446be05292e3e1f8a51218827168cdclaireho  HB_GPOSHeader*  gpos = gpi->gpos;
58805569331642446be05292e3e1f8a51218827168cdclaireho
58815569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt*  properties = gpos->LookupList.Properties;
58825569331642446be05292e3e1f8a51218827168cdclaireho
58835569331642446be05292e3e1f8a51218827168cdclaireho  const int       nesting_level = 0;
58845569331642446be05292e3e1f8a51218827168cdclaireho  /* 0xFFFF indicates that we don't have a context length yet */
58855569331642446be05292e3e1f8a51218827168cdclaireho  const HB_UShort context_length = 0xFFFF;
58865569331642446be05292e3e1f8a51218827168cdclaireho
58875569331642446be05292e3e1f8a51218827168cdclaireho
58885569331642446be05292e3e1f8a51218827168cdclaireho  gpi->last  = 0xFFFF;     /* no last valid glyph for cursive pos. */
58895569331642446be05292e3e1f8a51218827168cdclaireho
58905569331642446be05292e3e1f8a51218827168cdclaireho  buffer->in_pos = 0;
58915569331642446be05292e3e1f8a51218827168cdclaireho  while ( buffer->in_pos < buffer->in_length )
58925569331642446be05292e3e1f8a51218827168cdclaireho  {
58935569331642446be05292e3e1f8a51218827168cdclaireho    if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
58945569331642446be05292e3e1f8a51218827168cdclaireho    {
58955569331642446be05292e3e1f8a51218827168cdclaireho      /* Note that the connection between mark and base glyphs hold
58965569331642446be05292e3e1f8a51218827168cdclaireho	 exactly one (string) lookup.  For example, it would be possible
58975569331642446be05292e3e1f8a51218827168cdclaireho	 that in the first lookup, mark glyph X is attached to base
58985569331642446be05292e3e1f8a51218827168cdclaireho	 glyph A, and in the next lookup it is attached to base glyph B.
58995569331642446be05292e3e1f8a51218827168cdclaireho	 It is up to the font designer to provide meaningful lookups and
59005569331642446be05292e3e1f8a51218827168cdclaireho	 lookup order.                                                   */
59015569331642446be05292e3e1f8a51218827168cdclaireho
59025569331642446be05292e3e1f8a51218827168cdclaireho      error = GPOS_Do_Glyph_Lookup( gpi, lookup_index, buffer, context_length, nesting_level );
59035569331642446be05292e3e1f8a51218827168cdclaireho      if ( error && error != HB_Err_Not_Covered )
59045569331642446be05292e3e1f8a51218827168cdclaireho	return error;
59055569331642446be05292e3e1f8a51218827168cdclaireho    }
59065569331642446be05292e3e1f8a51218827168cdclaireho    else
59075569331642446be05292e3e1f8a51218827168cdclaireho    {
59085569331642446be05292e3e1f8a51218827168cdclaireho      /* Contrary to properties defined in GDEF, user-defined properties
59095569331642446be05292e3e1f8a51218827168cdclaireho	 will always stop a possible cursive positioning.                */
59105569331642446be05292e3e1f8a51218827168cdclaireho      gpi->last = 0xFFFF;
59115569331642446be05292e3e1f8a51218827168cdclaireho
59125569331642446be05292e3e1f8a51218827168cdclaireho      error = HB_Err_Not_Covered;
59135569331642446be05292e3e1f8a51218827168cdclaireho    }
59145569331642446be05292e3e1f8a51218827168cdclaireho
59155569331642446be05292e3e1f8a51218827168cdclaireho    if ( error == HB_Err_Not_Covered )
59165569331642446be05292e3e1f8a51218827168cdclaireho      (buffer->in_pos)++;
59175569331642446be05292e3e1f8a51218827168cdclaireho    else
59185569331642446be05292e3e1f8a51218827168cdclaireho      retError = error;
59195569331642446be05292e3e1f8a51218827168cdclaireho  }
59205569331642446be05292e3e1f8a51218827168cdclaireho
59215569331642446be05292e3e1f8a51218827168cdclaireho  return retError;
59225569331642446be05292e3e1f8a51218827168cdclaireho}
59235569331642446be05292e3e1f8a51218827168cdclaireho
59245569331642446be05292e3e1f8a51218827168cdclaireho
59255569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Position_CursiveChain ( HB_Buffer     buffer )
59265569331642446be05292e3e1f8a51218827168cdclaireho{
59275569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt   i, j;
59285569331642446be05292e3e1f8a51218827168cdclaireho  HB_Position positions = buffer->positions;
59295569331642446be05292e3e1f8a51218827168cdclaireho
59305569331642446be05292e3e1f8a51218827168cdclaireho  /* First handle all left-to-right connections */
59315569331642446be05292e3e1f8a51218827168cdclaireho  for (j = 0; j < buffer->in_length; j++)
59325569331642446be05292e3e1f8a51218827168cdclaireho  {
59335569331642446be05292e3e1f8a51218827168cdclaireho    if (positions[j].cursive_chain > 0)
59345569331642446be05292e3e1f8a51218827168cdclaireho      positions[j].y_pos += positions[j - positions[j].cursive_chain].y_pos;
59355569331642446be05292e3e1f8a51218827168cdclaireho  }
59365569331642446be05292e3e1f8a51218827168cdclaireho
59375569331642446be05292e3e1f8a51218827168cdclaireho  /* Then handle all right-to-left connections */
59385569331642446be05292e3e1f8a51218827168cdclaireho  for (i = buffer->in_length; i > 0; i--)
59395569331642446be05292e3e1f8a51218827168cdclaireho  {
59405569331642446be05292e3e1f8a51218827168cdclaireho    j = i - 1;
59415569331642446be05292e3e1f8a51218827168cdclaireho
59425569331642446be05292e3e1f8a51218827168cdclaireho    if (positions[j].cursive_chain < 0)
59435569331642446be05292e3e1f8a51218827168cdclaireho      positions[j].y_pos += positions[j - positions[j].cursive_chain].y_pos;
59445569331642446be05292e3e1f8a51218827168cdclaireho  }
59455569331642446be05292e3e1f8a51218827168cdclaireho
59465569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
59475569331642446be05292e3e1f8a51218827168cdclaireho}
59485569331642446be05292e3e1f8a51218827168cdclaireho
59495569331642446be05292e3e1f8a51218827168cdclaireho
59505569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_GPOS_Add_Feature( HB_GPOSHeader*  gpos,
59515569331642446be05292e3e1f8a51218827168cdclaireho			       HB_UShort        feature_index,
59525569331642446be05292e3e1f8a51218827168cdclaireho			       HB_UInt          property )
59535569331642446be05292e3e1f8a51218827168cdclaireho{
59545569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort    i;
59555569331642446be05292e3e1f8a51218827168cdclaireho
59565569331642446be05292e3e1f8a51218827168cdclaireho  HB_Feature  feature;
59575569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt*     properties;
59585569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*   index;
59595569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort    lookup_count;
59605569331642446be05292e3e1f8a51218827168cdclaireho
59615569331642446be05292e3e1f8a51218827168cdclaireho  /* Each feature can only be added once */
59625569331642446be05292e3e1f8a51218827168cdclaireho
59635569331642446be05292e3e1f8a51218827168cdclaireho  if ( !gpos ||
59645569331642446be05292e3e1f8a51218827168cdclaireho       feature_index >= gpos->FeatureList.FeatureCount ||
59655569331642446be05292e3e1f8a51218827168cdclaireho       gpos->FeatureList.ApplyCount == gpos->FeatureList.FeatureCount )
59665569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
59675569331642446be05292e3e1f8a51218827168cdclaireho
59685569331642446be05292e3e1f8a51218827168cdclaireho  gpos->FeatureList.ApplyOrder[gpos->FeatureList.ApplyCount++] = feature_index;
59695569331642446be05292e3e1f8a51218827168cdclaireho
59705569331642446be05292e3e1f8a51218827168cdclaireho  properties = gpos->LookupList.Properties;
59715569331642446be05292e3e1f8a51218827168cdclaireho
59725569331642446be05292e3e1f8a51218827168cdclaireho  feature = gpos->FeatureList.FeatureRecord[feature_index].Feature;
59735569331642446be05292e3e1f8a51218827168cdclaireho  index   = feature.LookupListIndex;
59745569331642446be05292e3e1f8a51218827168cdclaireho  lookup_count = gpos->LookupList.LookupCount;
59755569331642446be05292e3e1f8a51218827168cdclaireho
59765569331642446be05292e3e1f8a51218827168cdclaireho  for ( i = 0; i < feature.LookupListCount; i++ )
59775569331642446be05292e3e1f8a51218827168cdclaireho  {
59785569331642446be05292e3e1f8a51218827168cdclaireho    HB_UShort lookup_index = index[i];
59795569331642446be05292e3e1f8a51218827168cdclaireho    if (lookup_index < lookup_count)
59805569331642446be05292e3e1f8a51218827168cdclaireho      properties[lookup_index] |= property;
59815569331642446be05292e3e1f8a51218827168cdclaireho  }
59825569331642446be05292e3e1f8a51218827168cdclaireho
59835569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
59845569331642446be05292e3e1f8a51218827168cdclaireho}
59855569331642446be05292e3e1f8a51218827168cdclaireho
59865569331642446be05292e3e1f8a51218827168cdclaireho
59875569331642446be05292e3e1f8a51218827168cdclaireho
59885569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_GPOS_Clear_Features( HB_GPOSHeader*  gpos )
59895569331642446be05292e3e1f8a51218827168cdclaireho{
59905569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort i;
59915569331642446be05292e3e1f8a51218827168cdclaireho
59925569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt*  properties;
59935569331642446be05292e3e1f8a51218827168cdclaireho
59945569331642446be05292e3e1f8a51218827168cdclaireho
59955569331642446be05292e3e1f8a51218827168cdclaireho  if ( !gpos )
59965569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
59975569331642446be05292e3e1f8a51218827168cdclaireho
59985569331642446be05292e3e1f8a51218827168cdclaireho  gpos->FeatureList.ApplyCount = 0;
59995569331642446be05292e3e1f8a51218827168cdclaireho
60005569331642446be05292e3e1f8a51218827168cdclaireho  properties = gpos->LookupList.Properties;
60015569331642446be05292e3e1f8a51218827168cdclaireho
60025569331642446be05292e3e1f8a51218827168cdclaireho  for ( i = 0; i < gpos->LookupList.LookupCount; i++ )
60035569331642446be05292e3e1f8a51218827168cdclaireho    properties[i] = 0;
60045569331642446be05292e3e1f8a51218827168cdclaireho
60055569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
60065569331642446be05292e3e1f8a51218827168cdclaireho}
60075569331642446be05292e3e1f8a51218827168cdclaireho
600857e6107a9d66a9a97b146def0ef38c010f954be6claireho#ifdef HB_SUPPORT_MULTIPLE_MASTER
60095569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_GPOS_Register_MM_Function( HB_GPOSHeader*  gpos,
60105569331642446be05292e3e1f8a51218827168cdclaireho					HB_MMFunction   mmfunc,
60115569331642446be05292e3e1f8a51218827168cdclaireho					void*            data )
60125569331642446be05292e3e1f8a51218827168cdclaireho{
60135569331642446be05292e3e1f8a51218827168cdclaireho  if ( !gpos )
60145569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
60155569331642446be05292e3e1f8a51218827168cdclaireho
60165569331642446be05292e3e1f8a51218827168cdclaireho  gpos->mmfunc = mmfunc;
60175569331642446be05292e3e1f8a51218827168cdclaireho  gpos->data   = data;
60185569331642446be05292e3e1f8a51218827168cdclaireho
60195569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
60205569331642446be05292e3e1f8a51218827168cdclaireho}
602157e6107a9d66a9a97b146def0ef38c010f954be6claireho#endif
60225569331642446be05292e3e1f8a51218827168cdclaireho
60235569331642446be05292e3e1f8a51218827168cdclaireho/* If `dvi' is TRUE, glyph contour points for anchor points and device
60245569331642446be05292e3e1f8a51218827168cdclaireho   tables are ignored -- you will get device independent values.         */
60255569331642446be05292e3e1f8a51218827168cdclaireho
60265569331642446be05292e3e1f8a51218827168cdclaireho
60275569331642446be05292e3e1f8a51218827168cdclairehoHB_Error  HB_GPOS_Apply_String( HB_Font            font,
60285569331642446be05292e3e1f8a51218827168cdclaireho				HB_GPOSHeader*    gpos,
60295569331642446be05292e3e1f8a51218827168cdclaireho				HB_UShort          load_flags,
60305569331642446be05292e3e1f8a51218827168cdclaireho				HB_Buffer         buffer,
60315569331642446be05292e3e1f8a51218827168cdclaireho				HB_Bool            dvi,
60325569331642446be05292e3e1f8a51218827168cdclaireho				HB_Bool            r2l )
60335569331642446be05292e3e1f8a51218827168cdclaireho{
60345569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error       error, retError = HB_Err_Not_Covered;
60355569331642446be05292e3e1f8a51218827168cdclaireho  GPOS_Instance  gpi;
60365569331642446be05292e3e1f8a51218827168cdclaireho  int            i, j, lookup_count, num_features;
60375569331642446be05292e3e1f8a51218827168cdclaireho
60385569331642446be05292e3e1f8a51218827168cdclaireho  if ( !font || !gpos || !buffer )
60395569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_Argument);
60405569331642446be05292e3e1f8a51218827168cdclaireho
60415569331642446be05292e3e1f8a51218827168cdclaireho  if ( buffer->in_length == 0 )
60425569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
60435569331642446be05292e3e1f8a51218827168cdclaireho
60445569331642446be05292e3e1f8a51218827168cdclaireho  gpi.font       = font;
60455569331642446be05292e3e1f8a51218827168cdclaireho  gpi.gpos       = gpos;
60465569331642446be05292e3e1f8a51218827168cdclaireho  gpi.load_flags = load_flags;
60475569331642446be05292e3e1f8a51218827168cdclaireho  gpi.r2l        = r2l;
60485569331642446be05292e3e1f8a51218827168cdclaireho  gpi.dvi        = dvi;
60495569331642446be05292e3e1f8a51218827168cdclaireho
60505569331642446be05292e3e1f8a51218827168cdclaireho  lookup_count = gpos->LookupList.LookupCount;
60515569331642446be05292e3e1f8a51218827168cdclaireho  num_features = gpos->FeatureList.ApplyCount;
60525569331642446be05292e3e1f8a51218827168cdclaireho
60535569331642446be05292e3e1f8a51218827168cdclaireho  if ( num_features )
60545569331642446be05292e3e1f8a51218827168cdclaireho    {
60555569331642446be05292e3e1f8a51218827168cdclaireho      error = _hb_buffer_clear_positions( buffer );
60565569331642446be05292e3e1f8a51218827168cdclaireho      if ( error )
60575569331642446be05292e3e1f8a51218827168cdclaireho	return error;
60585569331642446be05292e3e1f8a51218827168cdclaireho    }
60595569331642446be05292e3e1f8a51218827168cdclaireho
60605569331642446be05292e3e1f8a51218827168cdclaireho  for ( i = 0; i < num_features; i++ )
60615569331642446be05292e3e1f8a51218827168cdclaireho  {
60625569331642446be05292e3e1f8a51218827168cdclaireho    HB_UShort  feature_index = gpos->FeatureList.ApplyOrder[i];
60635569331642446be05292e3e1f8a51218827168cdclaireho    HB_Feature feature = gpos->FeatureList.FeatureRecord[feature_index].Feature;
60645569331642446be05292e3e1f8a51218827168cdclaireho
60655569331642446be05292e3e1f8a51218827168cdclaireho    for ( j = 0; j < feature.LookupListCount; j++ )
60665569331642446be05292e3e1f8a51218827168cdclaireho    {
60675569331642446be05292e3e1f8a51218827168cdclaireho      HB_UShort lookup_index = feature.LookupListIndex[j];
60685569331642446be05292e3e1f8a51218827168cdclaireho
60695569331642446be05292e3e1f8a51218827168cdclaireho      /* Skip nonexistant lookups */
60705569331642446be05292e3e1f8a51218827168cdclaireho      if (lookup_index >= lookup_count)
60715569331642446be05292e3e1f8a51218827168cdclaireho       continue;
60725569331642446be05292e3e1f8a51218827168cdclaireho
60735569331642446be05292e3e1f8a51218827168cdclaireho      error = GPOS_Do_String_Lookup( &gpi, lookup_index, buffer );
60745569331642446be05292e3e1f8a51218827168cdclaireho      if ( error )
60755569331642446be05292e3e1f8a51218827168cdclaireho      {
60765569331642446be05292e3e1f8a51218827168cdclaireho	if ( error != HB_Err_Not_Covered )
60775569331642446be05292e3e1f8a51218827168cdclaireho	  return error;
60785569331642446be05292e3e1f8a51218827168cdclaireho      }
60795569331642446be05292e3e1f8a51218827168cdclaireho      else
60805569331642446be05292e3e1f8a51218827168cdclaireho	retError = error;
60815569331642446be05292e3e1f8a51218827168cdclaireho    }
60825569331642446be05292e3e1f8a51218827168cdclaireho  }
60835569331642446be05292e3e1f8a51218827168cdclaireho
60845569331642446be05292e3e1f8a51218827168cdclaireho  if ( num_features )
60855569331642446be05292e3e1f8a51218827168cdclaireho    {
60865569331642446be05292e3e1f8a51218827168cdclaireho  error = Position_CursiveChain ( buffer );
60875569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
60885569331642446be05292e3e1f8a51218827168cdclaireho    return error;
60895569331642446be05292e3e1f8a51218827168cdclaireho    }
60905569331642446be05292e3e1f8a51218827168cdclaireho
60915569331642446be05292e3e1f8a51218827168cdclaireho  return retError;
60925569331642446be05292e3e1f8a51218827168cdclaireho}
60935569331642446be05292e3e1f8a51218827168cdclaireho
60945569331642446be05292e3e1f8a51218827168cdclaireho/* END */
6095