15569331642446be05292e3e1f8a51218827168cdclaireho/*
25569331642446be05292e3e1f8a51218827168cdclaireho * Copyright (C) 1998-2004  David Turner and Werner Lemberg
35569331642446be05292e3e1f8a51218827168cdclaireho * Copyright (C) 2006  Behdad Esfahbod
45569331642446be05292e3e1f8a51218827168cdclaireho *
55569331642446be05292e3e1f8a51218827168cdclaireho * This is part of HarfBuzz, an OpenType Layout engine library.
65569331642446be05292e3e1f8a51218827168cdclaireho *
75569331642446be05292e3e1f8a51218827168cdclaireho * Permission is hereby granted, without written agreement and without
85569331642446be05292e3e1f8a51218827168cdclaireho * license or royalty fees, to use, copy, modify, and distribute this
95569331642446be05292e3e1f8a51218827168cdclaireho * software and its documentation for any purpose, provided that the
105569331642446be05292e3e1f8a51218827168cdclaireho * above copyright notice and the following two paragraphs appear in
115569331642446be05292e3e1f8a51218827168cdclaireho * all copies of this software.
125569331642446be05292e3e1f8a51218827168cdclaireho *
135569331642446be05292e3e1f8a51218827168cdclaireho * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
145569331642446be05292e3e1f8a51218827168cdclaireho * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
155569331642446be05292e3e1f8a51218827168cdclaireho * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
165569331642446be05292e3e1f8a51218827168cdclaireho * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
175569331642446be05292e3e1f8a51218827168cdclaireho * DAMAGE.
185569331642446be05292e3e1f8a51218827168cdclaireho *
195569331642446be05292e3e1f8a51218827168cdclaireho * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
205569331642446be05292e3e1f8a51218827168cdclaireho * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
215569331642446be05292e3e1f8a51218827168cdclaireho * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
225569331642446be05292e3e1f8a51218827168cdclaireho * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
235569331642446be05292e3e1f8a51218827168cdclaireho * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
245569331642446be05292e3e1f8a51218827168cdclaireho */
255569331642446be05292e3e1f8a51218827168cdclaireho
265569331642446be05292e3e1f8a51218827168cdclaireho#include "harfbuzz-impl.h"
275569331642446be05292e3e1f8a51218827168cdclaireho#include "harfbuzz-open-private.h"
285569331642446be05292e3e1f8a51218827168cdclaireho
295569331642446be05292e3e1f8a51218827168cdclaireho
305569331642446be05292e3e1f8a51218827168cdclaireho/***************************
315569331642446be05292e3e1f8a51218827168cdclaireho * Script related functions
325569331642446be05292e3e1f8a51218827168cdclaireho ***************************/
335569331642446be05292e3e1f8a51218827168cdclaireho
345569331642446be05292e3e1f8a51218827168cdclaireho
355569331642446be05292e3e1f8a51218827168cdclaireho/* LangSys */
365569331642446be05292e3e1f8a51218827168cdclaireho
375569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_LangSys( HB_LangSys*  ls,
385569331642446be05292e3e1f8a51218827168cdclaireho			       HB_Stream     stream )
395569331642446be05292e3e1f8a51218827168cdclaireho{
405569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error   error;
415569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort  n, count;
425569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort* fi;
435569331642446be05292e3e1f8a51218827168cdclaireho
445569331642446be05292e3e1f8a51218827168cdclaireho
455569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 6L ) )
465569331642446be05292e3e1f8a51218827168cdclaireho    return error;
475569331642446be05292e3e1f8a51218827168cdclaireho
485569331642446be05292e3e1f8a51218827168cdclaireho  ls->LookupOrderOffset    = GET_UShort();    /* should be 0 */
495569331642446be05292e3e1f8a51218827168cdclaireho  ls->ReqFeatureIndex      = GET_UShort();
505569331642446be05292e3e1f8a51218827168cdclaireho  count = ls->FeatureCount = GET_UShort();
515569331642446be05292e3e1f8a51218827168cdclaireho
525569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
535569331642446be05292e3e1f8a51218827168cdclaireho
545569331642446be05292e3e1f8a51218827168cdclaireho  ls->FeatureIndex = NULL;
555569331642446be05292e3e1f8a51218827168cdclaireho
565569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ls->FeatureIndex, count, HB_UShort ) )
575569331642446be05292e3e1f8a51218827168cdclaireho    return error;
585569331642446be05292e3e1f8a51218827168cdclaireho
595569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
605569331642446be05292e3e1f8a51218827168cdclaireho  {
615569331642446be05292e3e1f8a51218827168cdclaireho    FREE( ls->FeatureIndex );
625569331642446be05292e3e1f8a51218827168cdclaireho    return error;
635569331642446be05292e3e1f8a51218827168cdclaireho  }
645569331642446be05292e3e1f8a51218827168cdclaireho
655569331642446be05292e3e1f8a51218827168cdclaireho  fi = ls->FeatureIndex;
665569331642446be05292e3e1f8a51218827168cdclaireho
675569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
685569331642446be05292e3e1f8a51218827168cdclaireho    fi[n] = GET_UShort();
695569331642446be05292e3e1f8a51218827168cdclaireho
705569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
715569331642446be05292e3e1f8a51218827168cdclaireho
725569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
735569331642446be05292e3e1f8a51218827168cdclaireho}
745569331642446be05292e3e1f8a51218827168cdclaireho
755569331642446be05292e3e1f8a51218827168cdclaireho
765569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_LangSys( HB_LangSys*  ls )
775569331642446be05292e3e1f8a51218827168cdclaireho{
785569331642446be05292e3e1f8a51218827168cdclaireho  FREE( ls->FeatureIndex );
795569331642446be05292e3e1f8a51218827168cdclaireho}
805569331642446be05292e3e1f8a51218827168cdclaireho
815569331642446be05292e3e1f8a51218827168cdclaireho
825569331642446be05292e3e1f8a51218827168cdclaireho/* Script */
835569331642446be05292e3e1f8a51218827168cdclaireho
845569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_Script( HB_ScriptTable*  s,
855569331642446be05292e3e1f8a51218827168cdclaireho			      HB_Stream    stream )
865569331642446be05292e3e1f8a51218827168cdclaireho{
875569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error   error;
885569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort  n, m, count;
895569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt   cur_offset, new_offset, base_offset;
905569331642446be05292e3e1f8a51218827168cdclaireho
915569331642446be05292e3e1f8a51218827168cdclaireho  HB_LangSysRecord*  lsr;
925569331642446be05292e3e1f8a51218827168cdclaireho
935569331642446be05292e3e1f8a51218827168cdclaireho
945569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
955569331642446be05292e3e1f8a51218827168cdclaireho
965569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
975569331642446be05292e3e1f8a51218827168cdclaireho    return error;
985569331642446be05292e3e1f8a51218827168cdclaireho
995569331642446be05292e3e1f8a51218827168cdclaireho  new_offset = GET_UShort() + base_offset;
1005569331642446be05292e3e1f8a51218827168cdclaireho
1015569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
1025569331642446be05292e3e1f8a51218827168cdclaireho
1035569331642446be05292e3e1f8a51218827168cdclaireho  if ( new_offset != base_offset )        /* not a NULL offset */
1045569331642446be05292e3e1f8a51218827168cdclaireho  {
1055569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
1065569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
1075569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_LangSys( &s->DefaultLangSys,
1085569331642446be05292e3e1f8a51218827168cdclaireho				 stream ) ) != HB_Err_Ok )
1095569331642446be05292e3e1f8a51218827168cdclaireho      return error;
1105569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
1115569331642446be05292e3e1f8a51218827168cdclaireho  }
1125569331642446be05292e3e1f8a51218827168cdclaireho  else
1135569331642446be05292e3e1f8a51218827168cdclaireho  {
1145569331642446be05292e3e1f8a51218827168cdclaireho    /* we create a DefaultLangSys table with no entries */
1155569331642446be05292e3e1f8a51218827168cdclaireho
1165569331642446be05292e3e1f8a51218827168cdclaireho    s->DefaultLangSys.LookupOrderOffset = 0;
1175569331642446be05292e3e1f8a51218827168cdclaireho    s->DefaultLangSys.ReqFeatureIndex   = 0xFFFF;
1185569331642446be05292e3e1f8a51218827168cdclaireho    s->DefaultLangSys.FeatureCount      = 0;
1195569331642446be05292e3e1f8a51218827168cdclaireho    s->DefaultLangSys.FeatureIndex      = NULL;
1205569331642446be05292e3e1f8a51218827168cdclaireho  }
1215569331642446be05292e3e1f8a51218827168cdclaireho
1225569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
1235569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
1245569331642446be05292e3e1f8a51218827168cdclaireho
1255569331642446be05292e3e1f8a51218827168cdclaireho  count = s->LangSysCount = GET_UShort();
1265569331642446be05292e3e1f8a51218827168cdclaireho
1275569331642446be05292e3e1f8a51218827168cdclaireho  /* safety check; otherwise the official handling of TrueType Open
1285569331642446be05292e3e1f8a51218827168cdclaireho     fonts won't work */
1295569331642446be05292e3e1f8a51218827168cdclaireho
1305569331642446be05292e3e1f8a51218827168cdclaireho  if ( s->LangSysCount == 0 && s->DefaultLangSys.FeatureCount == 0 )
1315569331642446be05292e3e1f8a51218827168cdclaireho  {
1325569331642446be05292e3e1f8a51218827168cdclaireho    error = HB_Err_Not_Covered;
1335569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
1345569331642446be05292e3e1f8a51218827168cdclaireho  }
1355569331642446be05292e3e1f8a51218827168cdclaireho
1365569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
1375569331642446be05292e3e1f8a51218827168cdclaireho
1385569331642446be05292e3e1f8a51218827168cdclaireho  s->LangSysRecord = NULL;
1395569331642446be05292e3e1f8a51218827168cdclaireho
1405569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( s->LangSysRecord, count, HB_LangSysRecord ) )
1415569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
1425569331642446be05292e3e1f8a51218827168cdclaireho
1435569331642446be05292e3e1f8a51218827168cdclaireho  lsr = s->LangSysRecord;
1445569331642446be05292e3e1f8a51218827168cdclaireho
1455569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
1465569331642446be05292e3e1f8a51218827168cdclaireho  {
1475569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 6L ) )
1485569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
1495569331642446be05292e3e1f8a51218827168cdclaireho
1505569331642446be05292e3e1f8a51218827168cdclaireho    lsr[n].LangSysTag = GET_ULong();
1515569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
1525569331642446be05292e3e1f8a51218827168cdclaireho
1535569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
1545569331642446be05292e3e1f8a51218827168cdclaireho
1555569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
1565569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
1575569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_LangSys( &lsr[n].LangSys, stream ) ) != HB_Err_Ok )
1585569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
1595569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
1605569331642446be05292e3e1f8a51218827168cdclaireho  }
1615569331642446be05292e3e1f8a51218827168cdclaireho
1625569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
1635569331642446be05292e3e1f8a51218827168cdclaireho
1645569331642446be05292e3e1f8a51218827168cdclairehoFail1:
1655569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
1665569331642446be05292e3e1f8a51218827168cdclaireho    Free_LangSys( &lsr[m].LangSys );
1675569331642446be05292e3e1f8a51218827168cdclaireho
1685569331642446be05292e3e1f8a51218827168cdclaireho  FREE( s->LangSysRecord );
1695569331642446be05292e3e1f8a51218827168cdclaireho
1705569331642446be05292e3e1f8a51218827168cdclairehoFail2:
1715569331642446be05292e3e1f8a51218827168cdclaireho  Free_LangSys( &s->DefaultLangSys );
1725569331642446be05292e3e1f8a51218827168cdclaireho  return error;
1735569331642446be05292e3e1f8a51218827168cdclaireho}
1745569331642446be05292e3e1f8a51218827168cdclaireho
1755569331642446be05292e3e1f8a51218827168cdclaireho
1765569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_Script( HB_ScriptTable*  s )
1775569331642446be05292e3e1f8a51218827168cdclaireho{
1785569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort           n, count;
1795569331642446be05292e3e1f8a51218827168cdclaireho
1805569331642446be05292e3e1f8a51218827168cdclaireho  HB_LangSysRecord*  lsr;
1815569331642446be05292e3e1f8a51218827168cdclaireho
1825569331642446be05292e3e1f8a51218827168cdclaireho
1835569331642446be05292e3e1f8a51218827168cdclaireho  Free_LangSys( &s->DefaultLangSys );
1845569331642446be05292e3e1f8a51218827168cdclaireho
1855569331642446be05292e3e1f8a51218827168cdclaireho  if ( s->LangSysRecord )
1865569331642446be05292e3e1f8a51218827168cdclaireho  {
1875569331642446be05292e3e1f8a51218827168cdclaireho    count = s->LangSysCount;
1885569331642446be05292e3e1f8a51218827168cdclaireho    lsr   = s->LangSysRecord;
1895569331642446be05292e3e1f8a51218827168cdclaireho
1905569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
1915569331642446be05292e3e1f8a51218827168cdclaireho      Free_LangSys( &lsr[n].LangSys );
1925569331642446be05292e3e1f8a51218827168cdclaireho
1935569331642446be05292e3e1f8a51218827168cdclaireho    FREE( lsr );
1945569331642446be05292e3e1f8a51218827168cdclaireho  }
1955569331642446be05292e3e1f8a51218827168cdclaireho}
1965569331642446be05292e3e1f8a51218827168cdclaireho
1975569331642446be05292e3e1f8a51218827168cdclaireho
1985569331642446be05292e3e1f8a51218827168cdclaireho/* ScriptList */
1995569331642446be05292e3e1f8a51218827168cdclaireho
2005569331642446be05292e3e1f8a51218827168cdclairehoHB_INTERNAL HB_Error
2015569331642446be05292e3e1f8a51218827168cdclaireho_HB_OPEN_Load_ScriptList( HB_ScriptList* sl,
2025569331642446be05292e3e1f8a51218827168cdclaireho			   HB_Stream        stream )
2035569331642446be05292e3e1f8a51218827168cdclaireho{
2045569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error   error;
2055569331642446be05292e3e1f8a51218827168cdclaireho
2065569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          n, script_count;
2075569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt           cur_offset, new_offset, base_offset;
2085569331642446be05292e3e1f8a51218827168cdclaireho
2095569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptRecord*  sr;
2105569331642446be05292e3e1f8a51218827168cdclaireho
2115569331642446be05292e3e1f8a51218827168cdclaireho
2125569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
2135569331642446be05292e3e1f8a51218827168cdclaireho
2145569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
2155569331642446be05292e3e1f8a51218827168cdclaireho    return error;
2165569331642446be05292e3e1f8a51218827168cdclaireho
2175569331642446be05292e3e1f8a51218827168cdclaireho  script_count = GET_UShort();
2185569331642446be05292e3e1f8a51218827168cdclaireho
2195569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
2205569331642446be05292e3e1f8a51218827168cdclaireho
2215569331642446be05292e3e1f8a51218827168cdclaireho  sl->ScriptRecord = NULL;
2225569331642446be05292e3e1f8a51218827168cdclaireho
2235569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( sl->ScriptRecord, script_count, HB_ScriptRecord ) )
2245569331642446be05292e3e1f8a51218827168cdclaireho    return error;
2255569331642446be05292e3e1f8a51218827168cdclaireho
2265569331642446be05292e3e1f8a51218827168cdclaireho  sr = sl->ScriptRecord;
2275569331642446be05292e3e1f8a51218827168cdclaireho
2285569331642446be05292e3e1f8a51218827168cdclaireho  sl->ScriptCount= 0;
2295569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < script_count; n++ )
2305569331642446be05292e3e1f8a51218827168cdclaireho  {
2315569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 6L ) )
2325569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
2335569331642446be05292e3e1f8a51218827168cdclaireho
2345569331642446be05292e3e1f8a51218827168cdclaireho    sr[sl->ScriptCount].ScriptTag = GET_ULong();
2355569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
2365569331642446be05292e3e1f8a51218827168cdclaireho
2375569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
2385569331642446be05292e3e1f8a51218827168cdclaireho
2395569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
2405569331642446be05292e3e1f8a51218827168cdclaireho
2415569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) )
2425569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
2435569331642446be05292e3e1f8a51218827168cdclaireho
2445569331642446be05292e3e1f8a51218827168cdclaireho    error = Load_Script( &sr[sl->ScriptCount].Script, stream );
2455569331642446be05292e3e1f8a51218827168cdclaireho    if ( error == HB_Err_Ok )
2465569331642446be05292e3e1f8a51218827168cdclaireho      sl->ScriptCount += 1;
2475569331642446be05292e3e1f8a51218827168cdclaireho    else if ( error != HB_Err_Not_Covered )
2485569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
2495569331642446be05292e3e1f8a51218827168cdclaireho
2505569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
2515569331642446be05292e3e1f8a51218827168cdclaireho  }
2525569331642446be05292e3e1f8a51218827168cdclaireho
2535569331642446be05292e3e1f8a51218827168cdclaireho  /* Empty tables are harmless and generated by fontforge.
2545569331642446be05292e3e1f8a51218827168cdclaireho   * See http://bugzilla.gnome.org/show_bug.cgi?id=347073
2555569331642446be05292e3e1f8a51218827168cdclaireho   */
2565569331642446be05292e3e1f8a51218827168cdclaireho#if 0
2575569331642446be05292e3e1f8a51218827168cdclaireho  if ( sl->ScriptCount == 0 )
2585569331642446be05292e3e1f8a51218827168cdclaireho  {
2595569331642446be05292e3e1f8a51218827168cdclaireho    error = ERR(HB_Err_Invalid_SubTable);
2605569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail;
2615569331642446be05292e3e1f8a51218827168cdclaireho  }
2625569331642446be05292e3e1f8a51218827168cdclaireho#endif
2635569331642446be05292e3e1f8a51218827168cdclaireho
2645569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
2655569331642446be05292e3e1f8a51218827168cdclaireho
2665569331642446be05292e3e1f8a51218827168cdclairehoFail:
2675569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < sl->ScriptCount; n++ )
2685569331642446be05292e3e1f8a51218827168cdclaireho    Free_Script( &sr[n].Script );
2695569331642446be05292e3e1f8a51218827168cdclaireho
2705569331642446be05292e3e1f8a51218827168cdclaireho  FREE( sl->ScriptRecord );
2715569331642446be05292e3e1f8a51218827168cdclaireho  return error;
2725569331642446be05292e3e1f8a51218827168cdclaireho}
2735569331642446be05292e3e1f8a51218827168cdclaireho
2745569331642446be05292e3e1f8a51218827168cdclaireho
2755569331642446be05292e3e1f8a51218827168cdclairehoHB_INTERNAL void
2765569331642446be05292e3e1f8a51218827168cdclaireho_HB_OPEN_Free_ScriptList( HB_ScriptList* sl )
2775569331642446be05292e3e1f8a51218827168cdclaireho{
2785569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort          n, count;
2795569331642446be05292e3e1f8a51218827168cdclaireho
2805569331642446be05292e3e1f8a51218827168cdclaireho  HB_ScriptRecord*  sr;
2815569331642446be05292e3e1f8a51218827168cdclaireho
2825569331642446be05292e3e1f8a51218827168cdclaireho
2835569331642446be05292e3e1f8a51218827168cdclaireho  if ( sl->ScriptRecord )
2845569331642446be05292e3e1f8a51218827168cdclaireho  {
2855569331642446be05292e3e1f8a51218827168cdclaireho    count = sl->ScriptCount;
2865569331642446be05292e3e1f8a51218827168cdclaireho    sr    = sl->ScriptRecord;
2875569331642446be05292e3e1f8a51218827168cdclaireho
2885569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
2895569331642446be05292e3e1f8a51218827168cdclaireho      Free_Script( &sr[n].Script );
2905569331642446be05292e3e1f8a51218827168cdclaireho
2915569331642446be05292e3e1f8a51218827168cdclaireho    FREE( sr );
2925569331642446be05292e3e1f8a51218827168cdclaireho  }
2935569331642446be05292e3e1f8a51218827168cdclaireho}
2945569331642446be05292e3e1f8a51218827168cdclaireho
2955569331642446be05292e3e1f8a51218827168cdclaireho
2965569331642446be05292e3e1f8a51218827168cdclaireho
2975569331642446be05292e3e1f8a51218827168cdclaireho/*********************************
2985569331642446be05292e3e1f8a51218827168cdclaireho * Feature List related functions
2995569331642446be05292e3e1f8a51218827168cdclaireho *********************************/
3005569331642446be05292e3e1f8a51218827168cdclaireho
3015569331642446be05292e3e1f8a51218827168cdclaireho
3025569331642446be05292e3e1f8a51218827168cdclaireho/* Feature */
3035569331642446be05292e3e1f8a51218827168cdclaireho
3045569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_Feature( HB_Feature*  f,
3055569331642446be05292e3e1f8a51218827168cdclaireho			       HB_Stream     stream )
3065569331642446be05292e3e1f8a51218827168cdclaireho{
3075569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error   error;
3085569331642446be05292e3e1f8a51218827168cdclaireho
3095569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort   n, count;
3105569331642446be05292e3e1f8a51218827168cdclaireho
3115569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*  lli;
3125569331642446be05292e3e1f8a51218827168cdclaireho
3135569331642446be05292e3e1f8a51218827168cdclaireho
3145569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 4L ) )
3155569331642446be05292e3e1f8a51218827168cdclaireho    return error;
3165569331642446be05292e3e1f8a51218827168cdclaireho
3175569331642446be05292e3e1f8a51218827168cdclaireho  f->FeatureParams           = GET_UShort();    /* should be 0 */
3185569331642446be05292e3e1f8a51218827168cdclaireho  count = f->LookupListCount = GET_UShort();
3195569331642446be05292e3e1f8a51218827168cdclaireho
3205569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
3215569331642446be05292e3e1f8a51218827168cdclaireho
3225569331642446be05292e3e1f8a51218827168cdclaireho  f->LookupListIndex = NULL;
3235569331642446be05292e3e1f8a51218827168cdclaireho
3245569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( f->LookupListIndex, count, HB_UShort ) )
3255569331642446be05292e3e1f8a51218827168cdclaireho    return error;
3265569331642446be05292e3e1f8a51218827168cdclaireho
3275569331642446be05292e3e1f8a51218827168cdclaireho  lli = f->LookupListIndex;
3285569331642446be05292e3e1f8a51218827168cdclaireho
3295569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
3305569331642446be05292e3e1f8a51218827168cdclaireho  {
3315569331642446be05292e3e1f8a51218827168cdclaireho    FREE( f->LookupListIndex );
3325569331642446be05292e3e1f8a51218827168cdclaireho    return error;
3335569331642446be05292e3e1f8a51218827168cdclaireho  }
3345569331642446be05292e3e1f8a51218827168cdclaireho
3355569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
3365569331642446be05292e3e1f8a51218827168cdclaireho    lli[n] = GET_UShort();
3375569331642446be05292e3e1f8a51218827168cdclaireho
3385569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
3395569331642446be05292e3e1f8a51218827168cdclaireho
3405569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
3415569331642446be05292e3e1f8a51218827168cdclaireho}
3425569331642446be05292e3e1f8a51218827168cdclaireho
3435569331642446be05292e3e1f8a51218827168cdclaireho
3445569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_Feature( HB_Feature*  f )
3455569331642446be05292e3e1f8a51218827168cdclaireho{
3465569331642446be05292e3e1f8a51218827168cdclaireho  FREE( f->LookupListIndex );
3475569331642446be05292e3e1f8a51218827168cdclaireho}
3485569331642446be05292e3e1f8a51218827168cdclaireho
3495569331642446be05292e3e1f8a51218827168cdclaireho
3505569331642446be05292e3e1f8a51218827168cdclaireho/* FeatureList */
3515569331642446be05292e3e1f8a51218827168cdclaireho
3525569331642446be05292e3e1f8a51218827168cdclairehoHB_INTERNAL HB_Error
3535569331642446be05292e3e1f8a51218827168cdclaireho_HB_OPEN_Load_FeatureList( HB_FeatureList* fl,
3545569331642446be05292e3e1f8a51218827168cdclaireho			    HB_Stream         stream )
3555569331642446be05292e3e1f8a51218827168cdclaireho{
3565569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error   error;
3575569331642446be05292e3e1f8a51218827168cdclaireho
3585569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort           n, m, count;
3595569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt            cur_offset, new_offset, base_offset;
3605569331642446be05292e3e1f8a51218827168cdclaireho
3615569331642446be05292e3e1f8a51218827168cdclaireho  HB_FeatureRecord*  fr;
3625569331642446be05292e3e1f8a51218827168cdclaireho
3635569331642446be05292e3e1f8a51218827168cdclaireho
3645569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
3655569331642446be05292e3e1f8a51218827168cdclaireho
3665569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
3675569331642446be05292e3e1f8a51218827168cdclaireho    return error;
3685569331642446be05292e3e1f8a51218827168cdclaireho
3695569331642446be05292e3e1f8a51218827168cdclaireho  count = fl->FeatureCount = GET_UShort();
3705569331642446be05292e3e1f8a51218827168cdclaireho
3715569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
3725569331642446be05292e3e1f8a51218827168cdclaireho
3735569331642446be05292e3e1f8a51218827168cdclaireho  fl->FeatureRecord = NULL;
3745569331642446be05292e3e1f8a51218827168cdclaireho
3755569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( fl->FeatureRecord, count, HB_FeatureRecord ) )
3765569331642446be05292e3e1f8a51218827168cdclaireho    return error;
3775569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( fl->ApplyOrder, count, HB_UShort ) )
3785569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
3795569331642446be05292e3e1f8a51218827168cdclaireho
3805569331642446be05292e3e1f8a51218827168cdclaireho  fl->ApplyCount = 0;
3815569331642446be05292e3e1f8a51218827168cdclaireho
3825569331642446be05292e3e1f8a51218827168cdclaireho  fr = fl->FeatureRecord;
3835569331642446be05292e3e1f8a51218827168cdclaireho
3845569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
3855569331642446be05292e3e1f8a51218827168cdclaireho  {
3865569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 6L ) )
3875569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
3885569331642446be05292e3e1f8a51218827168cdclaireho
3895569331642446be05292e3e1f8a51218827168cdclaireho    fr[n].FeatureTag = GET_ULong();
3905569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
3915569331642446be05292e3e1f8a51218827168cdclaireho
3925569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
3935569331642446be05292e3e1f8a51218827168cdclaireho
3945569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
3955569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
3965569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_Feature( &fr[n].Feature, stream ) ) != HB_Err_Ok )
3975569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
3985569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
3995569331642446be05292e3e1f8a51218827168cdclaireho  }
4005569331642446be05292e3e1f8a51218827168cdclaireho
4015569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
4025569331642446be05292e3e1f8a51218827168cdclaireho
4035569331642446be05292e3e1f8a51218827168cdclairehoFail1:
4045569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
4055569331642446be05292e3e1f8a51218827168cdclaireho    Free_Feature( &fr[m].Feature );
4065569331642446be05292e3e1f8a51218827168cdclaireho
4075569331642446be05292e3e1f8a51218827168cdclaireho  FREE( fl->ApplyOrder );
4085569331642446be05292e3e1f8a51218827168cdclaireho
4095569331642446be05292e3e1f8a51218827168cdclairehoFail2:
4105569331642446be05292e3e1f8a51218827168cdclaireho  FREE( fl->FeatureRecord );
4115569331642446be05292e3e1f8a51218827168cdclaireho
4125569331642446be05292e3e1f8a51218827168cdclaireho  return error;
4135569331642446be05292e3e1f8a51218827168cdclaireho}
4145569331642446be05292e3e1f8a51218827168cdclaireho
4155569331642446be05292e3e1f8a51218827168cdclaireho
4165569331642446be05292e3e1f8a51218827168cdclairehoHB_INTERNAL void
4175569331642446be05292e3e1f8a51218827168cdclaireho_HB_OPEN_Free_FeatureList( HB_FeatureList*  fl )
4185569331642446be05292e3e1f8a51218827168cdclaireho{
4195569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort           n, count;
4205569331642446be05292e3e1f8a51218827168cdclaireho
4215569331642446be05292e3e1f8a51218827168cdclaireho  HB_FeatureRecord*  fr;
4225569331642446be05292e3e1f8a51218827168cdclaireho
4235569331642446be05292e3e1f8a51218827168cdclaireho
4245569331642446be05292e3e1f8a51218827168cdclaireho  if ( fl->FeatureRecord )
4255569331642446be05292e3e1f8a51218827168cdclaireho  {
4265569331642446be05292e3e1f8a51218827168cdclaireho    count = fl->FeatureCount;
4275569331642446be05292e3e1f8a51218827168cdclaireho    fr    = fl->FeatureRecord;
4285569331642446be05292e3e1f8a51218827168cdclaireho
4295569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
4305569331642446be05292e3e1f8a51218827168cdclaireho      Free_Feature( &fr[n].Feature );
4315569331642446be05292e3e1f8a51218827168cdclaireho
4325569331642446be05292e3e1f8a51218827168cdclaireho    FREE( fr );
4335569331642446be05292e3e1f8a51218827168cdclaireho  }
4345569331642446be05292e3e1f8a51218827168cdclaireho
4355569331642446be05292e3e1f8a51218827168cdclaireho  FREE( fl->ApplyOrder );
4365569331642446be05292e3e1f8a51218827168cdclaireho}
4375569331642446be05292e3e1f8a51218827168cdclaireho
4385569331642446be05292e3e1f8a51218827168cdclaireho
4395569331642446be05292e3e1f8a51218827168cdclaireho
4405569331642446be05292e3e1f8a51218827168cdclaireho/********************************
4415569331642446be05292e3e1f8a51218827168cdclaireho * Lookup List related functions
4425569331642446be05292e3e1f8a51218827168cdclaireho ********************************/
4435569331642446be05292e3e1f8a51218827168cdclaireho
4445569331642446be05292e3e1f8a51218827168cdclaireho/* the subroutines of the following two functions are defined in
4455569331642446be05292e3e1f8a51218827168cdclaireho   ftxgsub.c and ftxgpos.c respectively                          */
4465569331642446be05292e3e1f8a51218827168cdclaireho
4475569331642446be05292e3e1f8a51218827168cdclaireho
4485569331642446be05292e3e1f8a51218827168cdclaireho/* SubTable */
4495569331642446be05292e3e1f8a51218827168cdclaireho
4505569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_SubTable( HB_SubTable*  st,
4515569331642446be05292e3e1f8a51218827168cdclaireho				HB_Stream     stream,
4525569331642446be05292e3e1f8a51218827168cdclaireho				HB_Type       table_type,
4535569331642446be05292e3e1f8a51218827168cdclaireho				HB_UShort     lookup_type )
4545569331642446be05292e3e1f8a51218827168cdclaireho{
4555569331642446be05292e3e1f8a51218827168cdclaireho  if ( table_type == HB_Type_GSUB )
4565569331642446be05292e3e1f8a51218827168cdclaireho    return _HB_GSUB_Load_SubTable ( &st->st.gsub, stream, lookup_type );
4575569331642446be05292e3e1f8a51218827168cdclaireho  else
4585569331642446be05292e3e1f8a51218827168cdclaireho    return _HB_GPOS_Load_SubTable ( &st->st.gpos, stream, lookup_type );
4595569331642446be05292e3e1f8a51218827168cdclaireho}
4605569331642446be05292e3e1f8a51218827168cdclaireho
4615569331642446be05292e3e1f8a51218827168cdclaireho
4625569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_SubTable( HB_SubTable*  st,
4635569331642446be05292e3e1f8a51218827168cdclaireho			    HB_Type       table_type,
4645569331642446be05292e3e1f8a51218827168cdclaireho			    HB_UShort      lookup_type )
4655569331642446be05292e3e1f8a51218827168cdclaireho{
4665569331642446be05292e3e1f8a51218827168cdclaireho  if ( table_type == HB_Type_GSUB )
4675569331642446be05292e3e1f8a51218827168cdclaireho    _HB_GSUB_Free_SubTable ( &st->st.gsub, lookup_type );
4685569331642446be05292e3e1f8a51218827168cdclaireho  else
4695569331642446be05292e3e1f8a51218827168cdclaireho    _HB_GPOS_Free_SubTable ( &st->st.gpos, lookup_type );
4705569331642446be05292e3e1f8a51218827168cdclaireho}
4715569331642446be05292e3e1f8a51218827168cdclaireho
4725569331642446be05292e3e1f8a51218827168cdclaireho
4735569331642446be05292e3e1f8a51218827168cdclaireho/* Lookup */
4745569331642446be05292e3e1f8a51218827168cdclaireho
4755569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_Lookup( HB_Lookup*   l,
4765569331642446be05292e3e1f8a51218827168cdclaireho			      HB_Stream     stream,
4775569331642446be05292e3e1f8a51218827168cdclaireho			      HB_Type      type )
4785569331642446be05292e3e1f8a51218827168cdclaireho{
4795569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error   error;
4805569331642446be05292e3e1f8a51218827168cdclaireho
4815569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort      n, m, count;
4825569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt       cur_offset, new_offset, base_offset;
4835569331642446be05292e3e1f8a51218827168cdclaireho
4845569331642446be05292e3e1f8a51218827168cdclaireho  HB_SubTable*  st;
4855569331642446be05292e3e1f8a51218827168cdclaireho
4865569331642446be05292e3e1f8a51218827168cdclaireho  HB_Bool        is_extension = FALSE;
4875569331642446be05292e3e1f8a51218827168cdclaireho
4885569331642446be05292e3e1f8a51218827168cdclaireho
4895569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
4905569331642446be05292e3e1f8a51218827168cdclaireho
4915569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 6L ) )
4925569331642446be05292e3e1f8a51218827168cdclaireho    return error;
4935569331642446be05292e3e1f8a51218827168cdclaireho
4945569331642446be05292e3e1f8a51218827168cdclaireho  l->LookupType            = GET_UShort();
4955569331642446be05292e3e1f8a51218827168cdclaireho  l->LookupFlag            = GET_UShort();
4965569331642446be05292e3e1f8a51218827168cdclaireho  count = l->SubTableCount = GET_UShort();
4975569331642446be05292e3e1f8a51218827168cdclaireho
4985569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
4995569331642446be05292e3e1f8a51218827168cdclaireho
5005569331642446be05292e3e1f8a51218827168cdclaireho  l->SubTable = NULL;
5015569331642446be05292e3e1f8a51218827168cdclaireho
5025569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( l->SubTable, count, HB_SubTable ) )
5035569331642446be05292e3e1f8a51218827168cdclaireho    return error;
5045569331642446be05292e3e1f8a51218827168cdclaireho
5055569331642446be05292e3e1f8a51218827168cdclaireho  st = l->SubTable;
5065569331642446be05292e3e1f8a51218827168cdclaireho
5075569331642446be05292e3e1f8a51218827168cdclaireho  if ( ( type == HB_Type_GSUB && l->LookupType == HB_GSUB_LOOKUP_EXTENSION ) ||
5085569331642446be05292e3e1f8a51218827168cdclaireho       ( type == HB_Type_GPOS && l->LookupType == HB_GPOS_LOOKUP_EXTENSION ) )
5095569331642446be05292e3e1f8a51218827168cdclaireho    is_extension = TRUE;
5105569331642446be05292e3e1f8a51218827168cdclaireho
5115569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
5125569331642446be05292e3e1f8a51218827168cdclaireho  {
5135569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
5145569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
5155569331642446be05292e3e1f8a51218827168cdclaireho
5165569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
5175569331642446be05292e3e1f8a51218827168cdclaireho
5185569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
5195569331642446be05292e3e1f8a51218827168cdclaireho
5205569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
5215569331642446be05292e3e1f8a51218827168cdclaireho
5225569331642446be05292e3e1f8a51218827168cdclaireho    if ( is_extension )
5235569331642446be05292e3e1f8a51218827168cdclaireho    {
5245569331642446be05292e3e1f8a51218827168cdclaireho      if ( FILE_Seek( new_offset ) || ACCESS_Frame( 8L ) )
5255569331642446be05292e3e1f8a51218827168cdclaireho	goto Fail;
5265569331642446be05292e3e1f8a51218827168cdclaireho
5275569331642446be05292e3e1f8a51218827168cdclaireho      if (GET_UShort() != 1) /* format should be 1 */
5285569331642446be05292e3e1f8a51218827168cdclaireho	goto Fail;
5295569331642446be05292e3e1f8a51218827168cdclaireho
5305569331642446be05292e3e1f8a51218827168cdclaireho      l->LookupType = GET_UShort();
5315569331642446be05292e3e1f8a51218827168cdclaireho      new_offset += GET_ULong();
5325569331642446be05292e3e1f8a51218827168cdclaireho
5335569331642446be05292e3e1f8a51218827168cdclaireho      FORGET_Frame();
5345569331642446be05292e3e1f8a51218827168cdclaireho    }
5355569331642446be05292e3e1f8a51218827168cdclaireho
5365569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
5375569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_SubTable( &st[n], stream,
5385569331642446be05292e3e1f8a51218827168cdclaireho				  type, l->LookupType ) ) != HB_Err_Ok )
5395569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
5405569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
5415569331642446be05292e3e1f8a51218827168cdclaireho  }
5425569331642446be05292e3e1f8a51218827168cdclaireho
5435569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
5445569331642446be05292e3e1f8a51218827168cdclaireho
5455569331642446be05292e3e1f8a51218827168cdclairehoFail:
5465569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
5475569331642446be05292e3e1f8a51218827168cdclaireho    Free_SubTable( &st[m], type, l->LookupType );
5485569331642446be05292e3e1f8a51218827168cdclaireho
5495569331642446be05292e3e1f8a51218827168cdclaireho  FREE( l->SubTable );
5505569331642446be05292e3e1f8a51218827168cdclaireho  return error;
5515569331642446be05292e3e1f8a51218827168cdclaireho}
5525569331642446be05292e3e1f8a51218827168cdclaireho
5535569331642446be05292e3e1f8a51218827168cdclaireho
5545569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_Lookup( HB_Lookup*   l,
5555569331642446be05292e3e1f8a51218827168cdclaireho			  HB_Type      type)
5565569331642446be05292e3e1f8a51218827168cdclaireho{
5575569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort      n, count;
5585569331642446be05292e3e1f8a51218827168cdclaireho
5595569331642446be05292e3e1f8a51218827168cdclaireho  HB_SubTable*  st;
5605569331642446be05292e3e1f8a51218827168cdclaireho
5615569331642446be05292e3e1f8a51218827168cdclaireho
5625569331642446be05292e3e1f8a51218827168cdclaireho  if ( l->SubTable )
5635569331642446be05292e3e1f8a51218827168cdclaireho  {
5645569331642446be05292e3e1f8a51218827168cdclaireho    count = l->SubTableCount;
5655569331642446be05292e3e1f8a51218827168cdclaireho    st    = l->SubTable;
5665569331642446be05292e3e1f8a51218827168cdclaireho
5675569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
5685569331642446be05292e3e1f8a51218827168cdclaireho      Free_SubTable( &st[n], type, l->LookupType );
5695569331642446be05292e3e1f8a51218827168cdclaireho
5705569331642446be05292e3e1f8a51218827168cdclaireho    FREE( st );
5715569331642446be05292e3e1f8a51218827168cdclaireho  }
5725569331642446be05292e3e1f8a51218827168cdclaireho}
5735569331642446be05292e3e1f8a51218827168cdclaireho
5745569331642446be05292e3e1f8a51218827168cdclaireho
5755569331642446be05292e3e1f8a51218827168cdclaireho/* LookupList */
5765569331642446be05292e3e1f8a51218827168cdclaireho
5775569331642446be05292e3e1f8a51218827168cdclairehoHB_INTERNAL HB_Error
5785569331642446be05292e3e1f8a51218827168cdclaireho_HB_OPEN_Load_LookupList( HB_LookupList* ll,
5795569331642446be05292e3e1f8a51218827168cdclaireho			   HB_Stream        stream,
5805569331642446be05292e3e1f8a51218827168cdclaireho			   HB_Type         type )
5815569331642446be05292e3e1f8a51218827168cdclaireho{
5825569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error   error;
5835569331642446be05292e3e1f8a51218827168cdclaireho
5845569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort    n, m, count;
5855569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt     cur_offset, new_offset, base_offset;
5865569331642446be05292e3e1f8a51218827168cdclaireho
5875569331642446be05292e3e1f8a51218827168cdclaireho  HB_Lookup*  l;
5885569331642446be05292e3e1f8a51218827168cdclaireho
5895569331642446be05292e3e1f8a51218827168cdclaireho
5905569331642446be05292e3e1f8a51218827168cdclaireho  base_offset = FILE_Pos();
5915569331642446be05292e3e1f8a51218827168cdclaireho
5925569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
5935569331642446be05292e3e1f8a51218827168cdclaireho    return error;
5945569331642446be05292e3e1f8a51218827168cdclaireho
5955569331642446be05292e3e1f8a51218827168cdclaireho  count = ll->LookupCount = GET_UShort();
5965569331642446be05292e3e1f8a51218827168cdclaireho
5975569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
5985569331642446be05292e3e1f8a51218827168cdclaireho
5995569331642446be05292e3e1f8a51218827168cdclaireho  ll->Lookup = NULL;
6005569331642446be05292e3e1f8a51218827168cdclaireho
6015569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ll->Lookup, count, HB_Lookup ) )
6025569331642446be05292e3e1f8a51218827168cdclaireho    return error;
6035569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( ll->Properties, count, HB_UInt ) )
6045569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail2;
6055569331642446be05292e3e1f8a51218827168cdclaireho
6065569331642446be05292e3e1f8a51218827168cdclaireho  l = ll->Lookup;
6075569331642446be05292e3e1f8a51218827168cdclaireho
6085569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
6095569331642446be05292e3e1f8a51218827168cdclaireho  {
6105569331642446be05292e3e1f8a51218827168cdclaireho    if ( ACCESS_Frame( 2L ) )
6115569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
6125569331642446be05292e3e1f8a51218827168cdclaireho
6135569331642446be05292e3e1f8a51218827168cdclaireho    new_offset = GET_UShort() + base_offset;
6145569331642446be05292e3e1f8a51218827168cdclaireho
6155569331642446be05292e3e1f8a51218827168cdclaireho    FORGET_Frame();
6165569331642446be05292e3e1f8a51218827168cdclaireho
6175569331642446be05292e3e1f8a51218827168cdclaireho    cur_offset = FILE_Pos();
6185569331642446be05292e3e1f8a51218827168cdclaireho    if ( FILE_Seek( new_offset ) ||
6195569331642446be05292e3e1f8a51218827168cdclaireho	 ( error = Load_Lookup( &l[n], stream, type ) ) != HB_Err_Ok )
6205569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail1;
6215569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset );
6225569331642446be05292e3e1f8a51218827168cdclaireho  }
6235569331642446be05292e3e1f8a51218827168cdclaireho
6245569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
6255569331642446be05292e3e1f8a51218827168cdclaireho
6265569331642446be05292e3e1f8a51218827168cdclairehoFail1:
6275569331642446be05292e3e1f8a51218827168cdclaireho  FREE( ll->Properties );
6285569331642446be05292e3e1f8a51218827168cdclaireho
6295569331642446be05292e3e1f8a51218827168cdclaireho  for ( m = 0; m < n; m++ )
6305569331642446be05292e3e1f8a51218827168cdclaireho    Free_Lookup( &l[m], type );
6315569331642446be05292e3e1f8a51218827168cdclaireho
6325569331642446be05292e3e1f8a51218827168cdclairehoFail2:
6335569331642446be05292e3e1f8a51218827168cdclaireho  FREE( ll->Lookup );
6345569331642446be05292e3e1f8a51218827168cdclaireho  return error;
6355569331642446be05292e3e1f8a51218827168cdclaireho}
6365569331642446be05292e3e1f8a51218827168cdclaireho
6375569331642446be05292e3e1f8a51218827168cdclaireho
6385569331642446be05292e3e1f8a51218827168cdclairehoHB_INTERNAL void
6395569331642446be05292e3e1f8a51218827168cdclaireho_HB_OPEN_Free_LookupList( HB_LookupList* ll,
6405569331642446be05292e3e1f8a51218827168cdclaireho		       HB_Type         type )
6415569331642446be05292e3e1f8a51218827168cdclaireho{
6425569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort    n, count;
6435569331642446be05292e3e1f8a51218827168cdclaireho
6445569331642446be05292e3e1f8a51218827168cdclaireho  HB_Lookup*  l;
6455569331642446be05292e3e1f8a51218827168cdclaireho
6465569331642446be05292e3e1f8a51218827168cdclaireho
6475569331642446be05292e3e1f8a51218827168cdclaireho  FREE( ll->Properties );
6485569331642446be05292e3e1f8a51218827168cdclaireho
6495569331642446be05292e3e1f8a51218827168cdclaireho  if ( ll->Lookup )
6505569331642446be05292e3e1f8a51218827168cdclaireho  {
6515569331642446be05292e3e1f8a51218827168cdclaireho    count = ll->LookupCount;
6525569331642446be05292e3e1f8a51218827168cdclaireho    l     = ll->Lookup;
6535569331642446be05292e3e1f8a51218827168cdclaireho
6545569331642446be05292e3e1f8a51218827168cdclaireho    for ( n = 0; n < count; n++ )
6555569331642446be05292e3e1f8a51218827168cdclaireho      Free_Lookup( &l[n], type );
6565569331642446be05292e3e1f8a51218827168cdclaireho
6575569331642446be05292e3e1f8a51218827168cdclaireho    FREE( l );
6585569331642446be05292e3e1f8a51218827168cdclaireho  }
6595569331642446be05292e3e1f8a51218827168cdclaireho}
6605569331642446be05292e3e1f8a51218827168cdclaireho
6615569331642446be05292e3e1f8a51218827168cdclaireho
6625569331642446be05292e3e1f8a51218827168cdclaireho
6635569331642446be05292e3e1f8a51218827168cdclaireho/*****************************
6645569331642446be05292e3e1f8a51218827168cdclaireho * Coverage related functions
6655569331642446be05292e3e1f8a51218827168cdclaireho *****************************/
6665569331642446be05292e3e1f8a51218827168cdclaireho
6675569331642446be05292e3e1f8a51218827168cdclaireho
6685569331642446be05292e3e1f8a51218827168cdclaireho/* CoverageFormat1 */
6695569331642446be05292e3e1f8a51218827168cdclaireho
6705569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_Coverage1( HB_CoverageFormat1*  cf1,
6715569331642446be05292e3e1f8a51218827168cdclaireho				 HB_Stream             stream )
6725569331642446be05292e3e1f8a51218827168cdclaireho{
6735569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error   error;
6745569331642446be05292e3e1f8a51218827168cdclaireho
6755569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort  n, count;
6765569331642446be05292e3e1f8a51218827168cdclaireho
6775569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort* ga;
6785569331642446be05292e3e1f8a51218827168cdclaireho
6795569331642446be05292e3e1f8a51218827168cdclaireho
6805569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
6815569331642446be05292e3e1f8a51218827168cdclaireho    return error;
6825569331642446be05292e3e1f8a51218827168cdclaireho
6835569331642446be05292e3e1f8a51218827168cdclaireho  count = cf1->GlyphCount = GET_UShort();
6845569331642446be05292e3e1f8a51218827168cdclaireho
6855569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
6865569331642446be05292e3e1f8a51218827168cdclaireho
6875569331642446be05292e3e1f8a51218827168cdclaireho  cf1->GlyphArray = NULL;
6885569331642446be05292e3e1f8a51218827168cdclaireho
6895569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cf1->GlyphArray, count, HB_UShort ) )
6905569331642446be05292e3e1f8a51218827168cdclaireho    return error;
6915569331642446be05292e3e1f8a51218827168cdclaireho
6925569331642446be05292e3e1f8a51218827168cdclaireho  ga = cf1->GlyphArray;
6935569331642446be05292e3e1f8a51218827168cdclaireho
6945569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
6955569331642446be05292e3e1f8a51218827168cdclaireho  {
6965569331642446be05292e3e1f8a51218827168cdclaireho    FREE( cf1->GlyphArray );
6975569331642446be05292e3e1f8a51218827168cdclaireho    return error;
6985569331642446be05292e3e1f8a51218827168cdclaireho  }
6995569331642446be05292e3e1f8a51218827168cdclaireho
7005569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
7015569331642446be05292e3e1f8a51218827168cdclaireho    ga[n] = GET_UShort();
7025569331642446be05292e3e1f8a51218827168cdclaireho
7035569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
7045569331642446be05292e3e1f8a51218827168cdclaireho
7055569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
7065569331642446be05292e3e1f8a51218827168cdclaireho}
7075569331642446be05292e3e1f8a51218827168cdclaireho
7085569331642446be05292e3e1f8a51218827168cdclaireho
7095569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_Coverage1( HB_CoverageFormat1*  cf1)
7105569331642446be05292e3e1f8a51218827168cdclaireho{
7115569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cf1->GlyphArray );
7125569331642446be05292e3e1f8a51218827168cdclaireho}
7135569331642446be05292e3e1f8a51218827168cdclaireho
7145569331642446be05292e3e1f8a51218827168cdclaireho
7155569331642446be05292e3e1f8a51218827168cdclaireho/* CoverageFormat2 */
7165569331642446be05292e3e1f8a51218827168cdclaireho
7175569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_Coverage2( HB_CoverageFormat2*  cf2,
7185569331642446be05292e3e1f8a51218827168cdclaireho				 HB_Stream             stream )
7195569331642446be05292e3e1f8a51218827168cdclaireho{
7205569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error   error;
7215569331642446be05292e3e1f8a51218827168cdclaireho
7225569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort         n, count;
7235569331642446be05292e3e1f8a51218827168cdclaireho
7245569331642446be05292e3e1f8a51218827168cdclaireho  HB_RangeRecord*  rr;
7255569331642446be05292e3e1f8a51218827168cdclaireho
7265569331642446be05292e3e1f8a51218827168cdclaireho
7275569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
7285569331642446be05292e3e1f8a51218827168cdclaireho    return error;
7295569331642446be05292e3e1f8a51218827168cdclaireho
7305569331642446be05292e3e1f8a51218827168cdclaireho  count = cf2->RangeCount = GET_UShort();
7315569331642446be05292e3e1f8a51218827168cdclaireho
7325569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
7335569331642446be05292e3e1f8a51218827168cdclaireho
7345569331642446be05292e3e1f8a51218827168cdclaireho  cf2->RangeRecord = NULL;
7355569331642446be05292e3e1f8a51218827168cdclaireho
7365569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cf2->RangeRecord, count, HB_RangeRecord ) )
7375569331642446be05292e3e1f8a51218827168cdclaireho    return error;
7385569331642446be05292e3e1f8a51218827168cdclaireho
7395569331642446be05292e3e1f8a51218827168cdclaireho  rr = cf2->RangeRecord;
7405569331642446be05292e3e1f8a51218827168cdclaireho
7415569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 6L ) )
7425569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail;
7435569331642446be05292e3e1f8a51218827168cdclaireho
7445569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
7455569331642446be05292e3e1f8a51218827168cdclaireho  {
7465569331642446be05292e3e1f8a51218827168cdclaireho    rr[n].Start              = GET_UShort();
7475569331642446be05292e3e1f8a51218827168cdclaireho    rr[n].End                = GET_UShort();
7485569331642446be05292e3e1f8a51218827168cdclaireho    rr[n].StartCoverageIndex = GET_UShort();
7495569331642446be05292e3e1f8a51218827168cdclaireho
7505569331642446be05292e3e1f8a51218827168cdclaireho    /* sanity check; we are limited to 16bit integers */
7515569331642446be05292e3e1f8a51218827168cdclaireho    if ( rr[n].Start > rr[n].End ||
7525569331642446be05292e3e1f8a51218827168cdclaireho	 ( rr[n].End - rr[n].Start + (long)rr[n].StartCoverageIndex ) >=
7535569331642446be05292e3e1f8a51218827168cdclaireho	   0x10000L )
7545569331642446be05292e3e1f8a51218827168cdclaireho    {
7555569331642446be05292e3e1f8a51218827168cdclaireho      error = ERR(HB_Err_Invalid_SubTable);
7565569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
7575569331642446be05292e3e1f8a51218827168cdclaireho    }
7585569331642446be05292e3e1f8a51218827168cdclaireho  }
7595569331642446be05292e3e1f8a51218827168cdclaireho
7605569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
7615569331642446be05292e3e1f8a51218827168cdclaireho
7625569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
7635569331642446be05292e3e1f8a51218827168cdclaireho
7645569331642446be05292e3e1f8a51218827168cdclairehoFail:
7655569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cf2->RangeRecord );
7665569331642446be05292e3e1f8a51218827168cdclaireho  return error;
7675569331642446be05292e3e1f8a51218827168cdclaireho}
7685569331642446be05292e3e1f8a51218827168cdclaireho
7695569331642446be05292e3e1f8a51218827168cdclaireho
7705569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_Coverage2( HB_CoverageFormat2*  cf2 )
7715569331642446be05292e3e1f8a51218827168cdclaireho{
7725569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cf2->RangeRecord );
7735569331642446be05292e3e1f8a51218827168cdclaireho}
7745569331642446be05292e3e1f8a51218827168cdclaireho
7755569331642446be05292e3e1f8a51218827168cdclaireho
7765569331642446be05292e3e1f8a51218827168cdclairehoHB_INTERNAL HB_Error
7775569331642446be05292e3e1f8a51218827168cdclaireho_HB_OPEN_Load_Coverage( HB_Coverage* c,
7785569331642446be05292e3e1f8a51218827168cdclaireho			 HB_Stream      stream )
7795569331642446be05292e3e1f8a51218827168cdclaireho{
7805569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error   error;
7815569331642446be05292e3e1f8a51218827168cdclaireho
7825569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
7835569331642446be05292e3e1f8a51218827168cdclaireho    return error;
7845569331642446be05292e3e1f8a51218827168cdclaireho
7855569331642446be05292e3e1f8a51218827168cdclaireho  c->CoverageFormat = GET_UShort();
7865569331642446be05292e3e1f8a51218827168cdclaireho
7875569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
7885569331642446be05292e3e1f8a51218827168cdclaireho
7895569331642446be05292e3e1f8a51218827168cdclaireho  switch ( c->CoverageFormat )
7905569331642446be05292e3e1f8a51218827168cdclaireho  {
7915569331642446be05292e3e1f8a51218827168cdclaireho  case 1:  return Load_Coverage1( &c->cf.cf1, stream );
7925569331642446be05292e3e1f8a51218827168cdclaireho  case 2:  return Load_Coverage2( &c->cf.cf2, stream );
7935569331642446be05292e3e1f8a51218827168cdclaireho  default: return ERR(HB_Err_Invalid_SubTable_Format);
7945569331642446be05292e3e1f8a51218827168cdclaireho  }
7955569331642446be05292e3e1f8a51218827168cdclaireho
7965569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;               /* never reached */
7975569331642446be05292e3e1f8a51218827168cdclaireho}
7985569331642446be05292e3e1f8a51218827168cdclaireho
7995569331642446be05292e3e1f8a51218827168cdclaireho
8005569331642446be05292e3e1f8a51218827168cdclairehoHB_INTERNAL void
8015569331642446be05292e3e1f8a51218827168cdclaireho_HB_OPEN_Free_Coverage( HB_Coverage* c )
8025569331642446be05292e3e1f8a51218827168cdclaireho{
8035569331642446be05292e3e1f8a51218827168cdclaireho  switch ( c->CoverageFormat )
8045569331642446be05292e3e1f8a51218827168cdclaireho  {
8055569331642446be05292e3e1f8a51218827168cdclaireho  case 1:  Free_Coverage1( &c->cf.cf1 ); break;
8065569331642446be05292e3e1f8a51218827168cdclaireho  case 2:  Free_Coverage2( &c->cf.cf2 ); break;
8075569331642446be05292e3e1f8a51218827168cdclaireho  default:					 break;
8085569331642446be05292e3e1f8a51218827168cdclaireho  }
8095569331642446be05292e3e1f8a51218827168cdclaireho}
8105569331642446be05292e3e1f8a51218827168cdclaireho
8115569331642446be05292e3e1f8a51218827168cdclaireho
8125569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Coverage_Index1( HB_CoverageFormat1*  cf1,
8135569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort             glyphID,
8145569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort*            index )
8155569331642446be05292e3e1f8a51218827168cdclaireho{
8165569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort min, max, new_min, new_max, middle;
8175569331642446be05292e3e1f8a51218827168cdclaireho
8185569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*  array = cf1->GlyphArray;
8195569331642446be05292e3e1f8a51218827168cdclaireho
8205569331642446be05292e3e1f8a51218827168cdclaireho
8215569331642446be05292e3e1f8a51218827168cdclaireho  /* binary search */
8225569331642446be05292e3e1f8a51218827168cdclaireho
8235569331642446be05292e3e1f8a51218827168cdclaireho  if ( cf1->GlyphCount == 0 )
8245569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
8255569331642446be05292e3e1f8a51218827168cdclaireho
8265569331642446be05292e3e1f8a51218827168cdclaireho  new_min = 0;
8275569331642446be05292e3e1f8a51218827168cdclaireho  new_max = cf1->GlyphCount - 1;
8285569331642446be05292e3e1f8a51218827168cdclaireho
8295569331642446be05292e3e1f8a51218827168cdclaireho  do
8305569331642446be05292e3e1f8a51218827168cdclaireho  {
8315569331642446be05292e3e1f8a51218827168cdclaireho    min = new_min;
8325569331642446be05292e3e1f8a51218827168cdclaireho    max = new_max;
8335569331642446be05292e3e1f8a51218827168cdclaireho
8345569331642446be05292e3e1f8a51218827168cdclaireho    /* we use (min + max) / 2 = max - (max - min) / 2  to avoid
8355569331642446be05292e3e1f8a51218827168cdclaireho       overflow and rounding errors                             */
8365569331642446be05292e3e1f8a51218827168cdclaireho
8375569331642446be05292e3e1f8a51218827168cdclaireho    middle = max - ( ( max - min ) >> 1 );
8385569331642446be05292e3e1f8a51218827168cdclaireho
8395569331642446be05292e3e1f8a51218827168cdclaireho    if ( glyphID == array[middle] )
8405569331642446be05292e3e1f8a51218827168cdclaireho    {
8415569331642446be05292e3e1f8a51218827168cdclaireho      *index = middle;
8425569331642446be05292e3e1f8a51218827168cdclaireho      return HB_Err_Ok;
8435569331642446be05292e3e1f8a51218827168cdclaireho    }
8445569331642446be05292e3e1f8a51218827168cdclaireho    else if ( glyphID < array[middle] )
8455569331642446be05292e3e1f8a51218827168cdclaireho    {
8465569331642446be05292e3e1f8a51218827168cdclaireho      if ( middle == min )
8475569331642446be05292e3e1f8a51218827168cdclaireho	break;
8485569331642446be05292e3e1f8a51218827168cdclaireho      new_max = middle - 1;
8495569331642446be05292e3e1f8a51218827168cdclaireho    }
8505569331642446be05292e3e1f8a51218827168cdclaireho    else
8515569331642446be05292e3e1f8a51218827168cdclaireho    {
8525569331642446be05292e3e1f8a51218827168cdclaireho      if ( middle == max )
8535569331642446be05292e3e1f8a51218827168cdclaireho	break;
8545569331642446be05292e3e1f8a51218827168cdclaireho      new_min = middle + 1;
8555569331642446be05292e3e1f8a51218827168cdclaireho    }
8565569331642446be05292e3e1f8a51218827168cdclaireho  } while ( min < max );
8575569331642446be05292e3e1f8a51218827168cdclaireho
8585569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Not_Covered;
8595569331642446be05292e3e1f8a51218827168cdclaireho}
8605569331642446be05292e3e1f8a51218827168cdclaireho
8615569331642446be05292e3e1f8a51218827168cdclaireho
8625569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Coverage_Index2( HB_CoverageFormat2*  cf2,
8635569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort             glyphID,
8645569331642446be05292e3e1f8a51218827168cdclaireho				  HB_UShort*            index )
8655569331642446be05292e3e1f8a51218827168cdclaireho{
8665569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort         min, max, new_min, new_max, middle;
8675569331642446be05292e3e1f8a51218827168cdclaireho
8685569331642446be05292e3e1f8a51218827168cdclaireho  HB_RangeRecord*  rr = cf2->RangeRecord;
8695569331642446be05292e3e1f8a51218827168cdclaireho
8705569331642446be05292e3e1f8a51218827168cdclaireho
8715569331642446be05292e3e1f8a51218827168cdclaireho  /* binary search */
8725569331642446be05292e3e1f8a51218827168cdclaireho
8735569331642446be05292e3e1f8a51218827168cdclaireho  if ( cf2->RangeCount == 0 )
8745569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
8755569331642446be05292e3e1f8a51218827168cdclaireho
8765569331642446be05292e3e1f8a51218827168cdclaireho  new_min = 0;
8775569331642446be05292e3e1f8a51218827168cdclaireho  new_max = cf2->RangeCount - 1;
8785569331642446be05292e3e1f8a51218827168cdclaireho
8795569331642446be05292e3e1f8a51218827168cdclaireho  do
8805569331642446be05292e3e1f8a51218827168cdclaireho  {
8815569331642446be05292e3e1f8a51218827168cdclaireho    min = new_min;
8825569331642446be05292e3e1f8a51218827168cdclaireho    max = new_max;
8835569331642446be05292e3e1f8a51218827168cdclaireho
8845569331642446be05292e3e1f8a51218827168cdclaireho    /* we use (min + max) / 2 = max - (max - min) / 2  to avoid
8855569331642446be05292e3e1f8a51218827168cdclaireho       overflow and rounding errors                             */
8865569331642446be05292e3e1f8a51218827168cdclaireho
8875569331642446be05292e3e1f8a51218827168cdclaireho    middle = max - ( ( max - min ) >> 1 );
8885569331642446be05292e3e1f8a51218827168cdclaireho
8895569331642446be05292e3e1f8a51218827168cdclaireho    if ( glyphID >= rr[middle].Start && glyphID <= rr[middle].End )
8905569331642446be05292e3e1f8a51218827168cdclaireho    {
8915569331642446be05292e3e1f8a51218827168cdclaireho      *index = rr[middle].StartCoverageIndex + glyphID - rr[middle].Start;
8925569331642446be05292e3e1f8a51218827168cdclaireho      return HB_Err_Ok;
8935569331642446be05292e3e1f8a51218827168cdclaireho    }
8945569331642446be05292e3e1f8a51218827168cdclaireho    else if ( glyphID < rr[middle].Start )
8955569331642446be05292e3e1f8a51218827168cdclaireho    {
8965569331642446be05292e3e1f8a51218827168cdclaireho      if ( middle == min )
8975569331642446be05292e3e1f8a51218827168cdclaireho	break;
8985569331642446be05292e3e1f8a51218827168cdclaireho      new_max = middle - 1;
8995569331642446be05292e3e1f8a51218827168cdclaireho    }
9005569331642446be05292e3e1f8a51218827168cdclaireho    else
9015569331642446be05292e3e1f8a51218827168cdclaireho    {
9025569331642446be05292e3e1f8a51218827168cdclaireho      if ( middle == max )
9035569331642446be05292e3e1f8a51218827168cdclaireho	break;
9045569331642446be05292e3e1f8a51218827168cdclaireho      new_min = middle + 1;
9055569331642446be05292e3e1f8a51218827168cdclaireho    }
9065569331642446be05292e3e1f8a51218827168cdclaireho  } while ( min < max );
9075569331642446be05292e3e1f8a51218827168cdclaireho
9085569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Not_Covered;
9095569331642446be05292e3e1f8a51218827168cdclaireho}
9105569331642446be05292e3e1f8a51218827168cdclaireho
9115569331642446be05292e3e1f8a51218827168cdclaireho
9125569331642446be05292e3e1f8a51218827168cdclairehoHB_INTERNAL HB_Error
9135569331642446be05292e3e1f8a51218827168cdclaireho_HB_OPEN_Coverage_Index( HB_Coverage* c,
9145569331642446be05292e3e1f8a51218827168cdclaireho			  HB_UShort      glyphID,
9155569331642446be05292e3e1f8a51218827168cdclaireho			  HB_UShort*     index )
9165569331642446be05292e3e1f8a51218827168cdclaireho{
9175569331642446be05292e3e1f8a51218827168cdclaireho  switch ( c->CoverageFormat )
9185569331642446be05292e3e1f8a51218827168cdclaireho  {
9195569331642446be05292e3e1f8a51218827168cdclaireho  case 1:  return Coverage_Index1( &c->cf.cf1, glyphID, index );
9205569331642446be05292e3e1f8a51218827168cdclaireho  case 2:  return Coverage_Index2( &c->cf.cf2, glyphID, index );
9215569331642446be05292e3e1f8a51218827168cdclaireho  default: return ERR(HB_Err_Invalid_SubTable_Format);
9225569331642446be05292e3e1f8a51218827168cdclaireho  }
9235569331642446be05292e3e1f8a51218827168cdclaireho
9245569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;               /* never reached */
9255569331642446be05292e3e1f8a51218827168cdclaireho}
9265569331642446be05292e3e1f8a51218827168cdclaireho
9275569331642446be05292e3e1f8a51218827168cdclaireho
9285569331642446be05292e3e1f8a51218827168cdclaireho
9295569331642446be05292e3e1f8a51218827168cdclaireho/*************************************
9305569331642446be05292e3e1f8a51218827168cdclaireho * Class Definition related functions
9315569331642446be05292e3e1f8a51218827168cdclaireho *************************************/
9325569331642446be05292e3e1f8a51218827168cdclaireho
9335569331642446be05292e3e1f8a51218827168cdclaireho
9345569331642446be05292e3e1f8a51218827168cdclaireho/* ClassDefFormat1 */
9355569331642446be05292e3e1f8a51218827168cdclaireho
9365569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ClassDef1( HB_ClassDefinition*  cd,
9375569331642446be05292e3e1f8a51218827168cdclaireho				 HB_UShort             limit,
9385569331642446be05292e3e1f8a51218827168cdclaireho				 HB_Stream             stream )
9395569331642446be05292e3e1f8a51218827168cdclaireho{
9405569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error   error;
9415569331642446be05292e3e1f8a51218827168cdclaireho
9425569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort             n, count;
9435569331642446be05292e3e1f8a51218827168cdclaireho
9445569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*            cva;
9455569331642446be05292e3e1f8a51218827168cdclaireho
9465569331642446be05292e3e1f8a51218827168cdclaireho  HB_ClassDefFormat1*  cdf1;
9475569331642446be05292e3e1f8a51218827168cdclaireho
9485569331642446be05292e3e1f8a51218827168cdclaireho
9495569331642446be05292e3e1f8a51218827168cdclaireho  cdf1 = &cd->cd.cd1;
9505569331642446be05292e3e1f8a51218827168cdclaireho
9515569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 4L ) )
9525569331642446be05292e3e1f8a51218827168cdclaireho    return error;
9535569331642446be05292e3e1f8a51218827168cdclaireho
9545569331642446be05292e3e1f8a51218827168cdclaireho  cdf1->StartGlyph         = GET_UShort();
9555569331642446be05292e3e1f8a51218827168cdclaireho  count = cdf1->GlyphCount = GET_UShort();
9565569331642446be05292e3e1f8a51218827168cdclaireho
9575569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
9585569331642446be05292e3e1f8a51218827168cdclaireho
9595569331642446be05292e3e1f8a51218827168cdclaireho  /* sanity check; we are limited to 16bit integers */
9605569331642446be05292e3e1f8a51218827168cdclaireho
9615569331642446be05292e3e1f8a51218827168cdclaireho  if ( cdf1->StartGlyph + (long)count >= 0x10000L )
9625569331642446be05292e3e1f8a51218827168cdclaireho    return ERR(HB_Err_Invalid_SubTable);
9635569331642446be05292e3e1f8a51218827168cdclaireho
9645569331642446be05292e3e1f8a51218827168cdclaireho  cdf1->ClassValueArray = NULL;
9655569331642446be05292e3e1f8a51218827168cdclaireho
9665569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cdf1->ClassValueArray, count, HB_UShort ) )
9675569331642446be05292e3e1f8a51218827168cdclaireho    return error;
9685569331642446be05292e3e1f8a51218827168cdclaireho
9695569331642446be05292e3e1f8a51218827168cdclaireho  cva = cdf1->ClassValueArray;
9705569331642446be05292e3e1f8a51218827168cdclaireho
9715569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
9725569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail;
9735569331642446be05292e3e1f8a51218827168cdclaireho
9745569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
9755569331642446be05292e3e1f8a51218827168cdclaireho  {
9765569331642446be05292e3e1f8a51218827168cdclaireho    cva[n] = GET_UShort();
9775569331642446be05292e3e1f8a51218827168cdclaireho    if ( cva[n] >= limit )
9785569331642446be05292e3e1f8a51218827168cdclaireho    {
9795569331642446be05292e3e1f8a51218827168cdclaireho      error = ERR(HB_Err_Invalid_SubTable);
9805569331642446be05292e3e1f8a51218827168cdclaireho      goto Fail;
9815569331642446be05292e3e1f8a51218827168cdclaireho    }
9825569331642446be05292e3e1f8a51218827168cdclaireho  }
9835569331642446be05292e3e1f8a51218827168cdclaireho
9845569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
9855569331642446be05292e3e1f8a51218827168cdclaireho
9865569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
9875569331642446be05292e3e1f8a51218827168cdclaireho
9885569331642446be05292e3e1f8a51218827168cdclairehoFail:
9895569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cva );
9905569331642446be05292e3e1f8a51218827168cdclaireho
9915569331642446be05292e3e1f8a51218827168cdclaireho  return error;
9925569331642446be05292e3e1f8a51218827168cdclaireho}
9935569331642446be05292e3e1f8a51218827168cdclaireho
9945569331642446be05292e3e1f8a51218827168cdclaireho
9955569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ClassDef1( HB_ClassDefFormat1*  cdf1 )
9965569331642446be05292e3e1f8a51218827168cdclaireho{
9975569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cdf1->ClassValueArray );
9985569331642446be05292e3e1f8a51218827168cdclaireho}
9995569331642446be05292e3e1f8a51218827168cdclaireho
10005569331642446be05292e3e1f8a51218827168cdclaireho
10015569331642446be05292e3e1f8a51218827168cdclaireho/* ClassDefFormat2 */
10025569331642446be05292e3e1f8a51218827168cdclaireho
10035569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Load_ClassDef2( HB_ClassDefinition*  cd,
10045569331642446be05292e3e1f8a51218827168cdclaireho				 HB_UShort             limit,
10055569331642446be05292e3e1f8a51218827168cdclaireho				 HB_Stream             stream )
10065569331642446be05292e3e1f8a51218827168cdclaireho{
10075569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error   error;
10085569331642446be05292e3e1f8a51218827168cdclaireho
10095569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort              n, count;
10105569331642446be05292e3e1f8a51218827168cdclaireho
10115569331642446be05292e3e1f8a51218827168cdclaireho  HB_ClassRangeRecord*  crr;
10125569331642446be05292e3e1f8a51218827168cdclaireho
10135569331642446be05292e3e1f8a51218827168cdclaireho  HB_ClassDefFormat2*   cdf2;
10145569331642446be05292e3e1f8a51218827168cdclaireho
10155569331642446be05292e3e1f8a51218827168cdclaireho
10165569331642446be05292e3e1f8a51218827168cdclaireho  cdf2 = &cd->cd.cd2;
10175569331642446be05292e3e1f8a51218827168cdclaireho
10185569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
10195569331642446be05292e3e1f8a51218827168cdclaireho    return error;
10205569331642446be05292e3e1f8a51218827168cdclaireho
10215569331642446be05292e3e1f8a51218827168cdclaireho  count = GET_UShort();
10225569331642446be05292e3e1f8a51218827168cdclaireho  cdf2->ClassRangeCount = 0; /* zero for now.  we fill with the number of good entries later */
10235569331642446be05292e3e1f8a51218827168cdclaireho
10245569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
10255569331642446be05292e3e1f8a51218827168cdclaireho
10265569331642446be05292e3e1f8a51218827168cdclaireho  cdf2->ClassRangeRecord = NULL;
10275569331642446be05292e3e1f8a51218827168cdclaireho
10285569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cdf2->ClassRangeRecord, count, HB_ClassRangeRecord ) )
10295569331642446be05292e3e1f8a51218827168cdclaireho    return error;
10305569331642446be05292e3e1f8a51218827168cdclaireho
10315569331642446be05292e3e1f8a51218827168cdclaireho  crr = cdf2->ClassRangeRecord;
10325569331642446be05292e3e1f8a51218827168cdclaireho
10335569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 6L ) )
10345569331642446be05292e3e1f8a51218827168cdclaireho    goto Fail;
10355569331642446be05292e3e1f8a51218827168cdclaireho
10365569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
10375569331642446be05292e3e1f8a51218827168cdclaireho  {
10385569331642446be05292e3e1f8a51218827168cdclaireho    crr[n].Start = GET_UShort();
10395569331642446be05292e3e1f8a51218827168cdclaireho    crr[n].End   = GET_UShort();
10405569331642446be05292e3e1f8a51218827168cdclaireho    crr[n].Class = GET_UShort();
10415569331642446be05292e3e1f8a51218827168cdclaireho
10425569331642446be05292e3e1f8a51218827168cdclaireho    /* sanity check */
10435569331642446be05292e3e1f8a51218827168cdclaireho
10445569331642446be05292e3e1f8a51218827168cdclaireho    if ( crr[n].Start > crr[n].End ||
10455569331642446be05292e3e1f8a51218827168cdclaireho	 crr[n].Class >= limit )
10465569331642446be05292e3e1f8a51218827168cdclaireho    {
10475569331642446be05292e3e1f8a51218827168cdclaireho      /* XXX
10485569331642446be05292e3e1f8a51218827168cdclaireho       * Corrupt entry.  Skip it.
10495569331642446be05292e3e1f8a51218827168cdclaireho       * This is hit by Nafees Nastaliq font for example
10505569331642446be05292e3e1f8a51218827168cdclaireho       */
10515569331642446be05292e3e1f8a51218827168cdclaireho       n--;
10525569331642446be05292e3e1f8a51218827168cdclaireho       count--;
10535569331642446be05292e3e1f8a51218827168cdclaireho    }
10545569331642446be05292e3e1f8a51218827168cdclaireho  }
10555569331642446be05292e3e1f8a51218827168cdclaireho
10565569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
10575569331642446be05292e3e1f8a51218827168cdclaireho
10585569331642446be05292e3e1f8a51218827168cdclaireho  cdf2->ClassRangeCount = count;
10595569331642446be05292e3e1f8a51218827168cdclaireho
10605569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
10615569331642446be05292e3e1f8a51218827168cdclaireho
10625569331642446be05292e3e1f8a51218827168cdclairehoFail:
10635569331642446be05292e3e1f8a51218827168cdclaireho  FREE( crr );
10645569331642446be05292e3e1f8a51218827168cdclaireho
10655569331642446be05292e3e1f8a51218827168cdclaireho  return error;
10665569331642446be05292e3e1f8a51218827168cdclaireho}
10675569331642446be05292e3e1f8a51218827168cdclaireho
10685569331642446be05292e3e1f8a51218827168cdclaireho
10695569331642446be05292e3e1f8a51218827168cdclairehostatic void  Free_ClassDef2( HB_ClassDefFormat2*  cdf2 )
10705569331642446be05292e3e1f8a51218827168cdclaireho{
10715569331642446be05292e3e1f8a51218827168cdclaireho  FREE( cdf2->ClassRangeRecord );
10725569331642446be05292e3e1f8a51218827168cdclaireho}
10735569331642446be05292e3e1f8a51218827168cdclaireho
10745569331642446be05292e3e1f8a51218827168cdclaireho
10755569331642446be05292e3e1f8a51218827168cdclaireho/* ClassDefinition */
10765569331642446be05292e3e1f8a51218827168cdclaireho
10775569331642446be05292e3e1f8a51218827168cdclairehoHB_INTERNAL HB_Error
10785569331642446be05292e3e1f8a51218827168cdclaireho_HB_OPEN_Load_ClassDefinition( HB_ClassDefinition* cd,
10795569331642446be05292e3e1f8a51218827168cdclaireho				HB_UShort             limit,
10805569331642446be05292e3e1f8a51218827168cdclaireho				HB_Stream             stream )
10815569331642446be05292e3e1f8a51218827168cdclaireho{
10825569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error   error;
10835569331642446be05292e3e1f8a51218827168cdclaireho
10845569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 2L ) )
10855569331642446be05292e3e1f8a51218827168cdclaireho    return error;
10865569331642446be05292e3e1f8a51218827168cdclaireho
10875569331642446be05292e3e1f8a51218827168cdclaireho  cd->ClassFormat = GET_UShort();
10885569331642446be05292e3e1f8a51218827168cdclaireho
10895569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
10905569331642446be05292e3e1f8a51218827168cdclaireho
10915569331642446be05292e3e1f8a51218827168cdclaireho  switch ( cd->ClassFormat )
10925569331642446be05292e3e1f8a51218827168cdclaireho  {
10935569331642446be05292e3e1f8a51218827168cdclaireho  case 1:  error = Load_ClassDef1( cd, limit, stream ); break;
10945569331642446be05292e3e1f8a51218827168cdclaireho  case 2:  error = Load_ClassDef2( cd, limit, stream ); break;
10955569331642446be05292e3e1f8a51218827168cdclaireho  default: error = ERR(HB_Err_Invalid_SubTable_Format);	break;
10965569331642446be05292e3e1f8a51218827168cdclaireho  }
10975569331642446be05292e3e1f8a51218827168cdclaireho
10985569331642446be05292e3e1f8a51218827168cdclaireho  if ( error )
10995569331642446be05292e3e1f8a51218827168cdclaireho    return error;
11005569331642446be05292e3e1f8a51218827168cdclaireho
11015569331642446be05292e3e1f8a51218827168cdclaireho  cd->loaded = TRUE;
11025569331642446be05292e3e1f8a51218827168cdclaireho
11035569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
11045569331642446be05292e3e1f8a51218827168cdclaireho}
11055569331642446be05292e3e1f8a51218827168cdclaireho
11065569331642446be05292e3e1f8a51218827168cdclaireho
11075569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error
11085569331642446be05292e3e1f8a51218827168cdclaireho_HB_OPEN_Load_EmptyClassDefinition( HB_ClassDefinition*  cd )
11095569331642446be05292e3e1f8a51218827168cdclaireho{
11105569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error   error;
11115569331642446be05292e3e1f8a51218827168cdclaireho
11125569331642446be05292e3e1f8a51218827168cdclaireho  cd->ClassFormat = 1; /* Meaningless */
11135569331642446be05292e3e1f8a51218827168cdclaireho
11145569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( cd->cd.cd1.ClassValueArray, 1, HB_UShort ) )
11155569331642446be05292e3e1f8a51218827168cdclaireho    return error;
11165569331642446be05292e3e1f8a51218827168cdclaireho
11175569331642446be05292e3e1f8a51218827168cdclaireho  cd->loaded = TRUE;
11185569331642446be05292e3e1f8a51218827168cdclaireho
11195569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
11205569331642446be05292e3e1f8a51218827168cdclaireho}
11215569331642446be05292e3e1f8a51218827168cdclaireho
11225569331642446be05292e3e1f8a51218827168cdclairehoHB_INTERNAL HB_Error
11235569331642446be05292e3e1f8a51218827168cdclaireho_HB_OPEN_Load_EmptyOrClassDefinition( HB_ClassDefinition* cd,
11245569331642446be05292e3e1f8a51218827168cdclaireho					       HB_UShort             limit,
11255569331642446be05292e3e1f8a51218827168cdclaireho					       HB_UInt              class_offset,
11265569331642446be05292e3e1f8a51218827168cdclaireho					       HB_UInt              base_offset,
11275569331642446be05292e3e1f8a51218827168cdclaireho					       HB_Stream             stream )
11285569331642446be05292e3e1f8a51218827168cdclaireho{
11295569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error error;
11305569331642446be05292e3e1f8a51218827168cdclaireho  HB_UInt               cur_offset;
11315569331642446be05292e3e1f8a51218827168cdclaireho
11325569331642446be05292e3e1f8a51218827168cdclaireho  cur_offset = FILE_Pos();
11335569331642446be05292e3e1f8a51218827168cdclaireho
11345569331642446be05292e3e1f8a51218827168cdclaireho  if ( class_offset )
11355569331642446be05292e3e1f8a51218827168cdclaireho    {
11365569331642446be05292e3e1f8a51218827168cdclaireho      if ( !FILE_Seek( class_offset + base_offset ) )
11375569331642446be05292e3e1f8a51218827168cdclaireho	error = _HB_OPEN_Load_ClassDefinition( cd, limit, stream );
11385569331642446be05292e3e1f8a51218827168cdclaireho    }
11395569331642446be05292e3e1f8a51218827168cdclaireho  else
11405569331642446be05292e3e1f8a51218827168cdclaireho     error = _HB_OPEN_Load_EmptyClassDefinition ( cd );
11415569331642446be05292e3e1f8a51218827168cdclaireho
11425569331642446be05292e3e1f8a51218827168cdclaireho  if (error == HB_Err_Ok)
11435569331642446be05292e3e1f8a51218827168cdclaireho    (void)FILE_Seek( cur_offset ); /* Changes error as a side-effect */
11445569331642446be05292e3e1f8a51218827168cdclaireho
11455569331642446be05292e3e1f8a51218827168cdclaireho  return error;
11465569331642446be05292e3e1f8a51218827168cdclaireho}
11475569331642446be05292e3e1f8a51218827168cdclaireho
11485569331642446be05292e3e1f8a51218827168cdclairehoHB_INTERNAL void
11495569331642446be05292e3e1f8a51218827168cdclaireho_HB_OPEN_Free_ClassDefinition( HB_ClassDefinition*  cd )
11505569331642446be05292e3e1f8a51218827168cdclaireho{
11515569331642446be05292e3e1f8a51218827168cdclaireho  if ( !cd->loaded )
11525569331642446be05292e3e1f8a51218827168cdclaireho    return;
11535569331642446be05292e3e1f8a51218827168cdclaireho
11545569331642446be05292e3e1f8a51218827168cdclaireho  switch ( cd->ClassFormat )
11555569331642446be05292e3e1f8a51218827168cdclaireho  {
11565569331642446be05292e3e1f8a51218827168cdclaireho  case 1:  Free_ClassDef1( &cd->cd.cd1 ); break;
11575569331642446be05292e3e1f8a51218827168cdclaireho  case 2:  Free_ClassDef2( &cd->cd.cd2 ); break;
11585569331642446be05292e3e1f8a51218827168cdclaireho  default:				  break;
11595569331642446be05292e3e1f8a51218827168cdclaireho  }
11605569331642446be05292e3e1f8a51218827168cdclaireho}
11615569331642446be05292e3e1f8a51218827168cdclaireho
11625569331642446be05292e3e1f8a51218827168cdclaireho
11635569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Get_Class1( HB_ClassDefFormat1*  cdf1,
11645569331642446be05292e3e1f8a51218827168cdclaireho			     HB_UShort             glyphID,
11655569331642446be05292e3e1f8a51218827168cdclaireho			     HB_UShort*            klass,
11665569331642446be05292e3e1f8a51218827168cdclaireho			     HB_UShort*            index )
11675569331642446be05292e3e1f8a51218827168cdclaireho{
11685569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*  cva = cdf1->ClassValueArray;
11695569331642446be05292e3e1f8a51218827168cdclaireho
11705569331642446be05292e3e1f8a51218827168cdclaireho
11715569331642446be05292e3e1f8a51218827168cdclaireho  if ( index )
11725569331642446be05292e3e1f8a51218827168cdclaireho    *index = 0;
11735569331642446be05292e3e1f8a51218827168cdclaireho
11745569331642446be05292e3e1f8a51218827168cdclaireho  if ( glyphID >= cdf1->StartGlyph &&
11755569331642446be05292e3e1f8a51218827168cdclaireho       glyphID < cdf1->StartGlyph + cdf1->GlyphCount )
11765569331642446be05292e3e1f8a51218827168cdclaireho  {
11775569331642446be05292e3e1f8a51218827168cdclaireho    *klass = cva[glyphID - cdf1->StartGlyph];
11785569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Ok;
11795569331642446be05292e3e1f8a51218827168cdclaireho  }
11805569331642446be05292e3e1f8a51218827168cdclaireho  else
11815569331642446be05292e3e1f8a51218827168cdclaireho  {
11825569331642446be05292e3e1f8a51218827168cdclaireho    *klass = 0;
11835569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
11845569331642446be05292e3e1f8a51218827168cdclaireho  }
11855569331642446be05292e3e1f8a51218827168cdclaireho}
11865569331642446be05292e3e1f8a51218827168cdclaireho
11875569331642446be05292e3e1f8a51218827168cdclaireho
11885569331642446be05292e3e1f8a51218827168cdclaireho/* we need the index value of the last searched class range record
11895569331642446be05292e3e1f8a51218827168cdclaireho   in case of failure for constructed GDEF tables                  */
11905569331642446be05292e3e1f8a51218827168cdclaireho
11915569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Error  Get_Class2( HB_ClassDefFormat2*  cdf2,
11925569331642446be05292e3e1f8a51218827168cdclaireho			     HB_UShort             glyphID,
11935569331642446be05292e3e1f8a51218827168cdclaireho			     HB_UShort*            klass,
11945569331642446be05292e3e1f8a51218827168cdclaireho			     HB_UShort*            index )
11955569331642446be05292e3e1f8a51218827168cdclaireho{
11965569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error               error = HB_Err_Ok;
11975569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort              min, max, new_min, new_max, middle;
11985569331642446be05292e3e1f8a51218827168cdclaireho
11995569331642446be05292e3e1f8a51218827168cdclaireho  HB_ClassRangeRecord*  crr = cdf2->ClassRangeRecord;
12005569331642446be05292e3e1f8a51218827168cdclaireho
12015569331642446be05292e3e1f8a51218827168cdclaireho
12025569331642446be05292e3e1f8a51218827168cdclaireho  /* binary search */
12035569331642446be05292e3e1f8a51218827168cdclaireho
12045569331642446be05292e3e1f8a51218827168cdclaireho  if ( cdf2->ClassRangeCount == 0 )
12055569331642446be05292e3e1f8a51218827168cdclaireho    {
12065569331642446be05292e3e1f8a51218827168cdclaireho      *klass = 0;
12075569331642446be05292e3e1f8a51218827168cdclaireho      if ( index )
12085569331642446be05292e3e1f8a51218827168cdclaireho	*index = 0;
12095569331642446be05292e3e1f8a51218827168cdclaireho
12105569331642446be05292e3e1f8a51218827168cdclaireho      return HB_Err_Not_Covered;
12115569331642446be05292e3e1f8a51218827168cdclaireho    }
12125569331642446be05292e3e1f8a51218827168cdclaireho
12135569331642446be05292e3e1f8a51218827168cdclaireho  new_min = 0;
12145569331642446be05292e3e1f8a51218827168cdclaireho  new_max = cdf2->ClassRangeCount - 1;
12155569331642446be05292e3e1f8a51218827168cdclaireho
12165569331642446be05292e3e1f8a51218827168cdclaireho  do
12175569331642446be05292e3e1f8a51218827168cdclaireho  {
12185569331642446be05292e3e1f8a51218827168cdclaireho    min = new_min;
12195569331642446be05292e3e1f8a51218827168cdclaireho    max = new_max;
12205569331642446be05292e3e1f8a51218827168cdclaireho
12215569331642446be05292e3e1f8a51218827168cdclaireho    /* we use (min + max) / 2 = max - (max - min) / 2  to avoid
12225569331642446be05292e3e1f8a51218827168cdclaireho       overflow and rounding errors                             */
12235569331642446be05292e3e1f8a51218827168cdclaireho
12245569331642446be05292e3e1f8a51218827168cdclaireho    middle = max - ( ( max - min ) >> 1 );
12255569331642446be05292e3e1f8a51218827168cdclaireho
12265569331642446be05292e3e1f8a51218827168cdclaireho    if ( glyphID >= crr[middle].Start && glyphID <= crr[middle].End )
12275569331642446be05292e3e1f8a51218827168cdclaireho    {
12285569331642446be05292e3e1f8a51218827168cdclaireho      *klass = crr[middle].Class;
12295569331642446be05292e3e1f8a51218827168cdclaireho      error  = HB_Err_Ok;
12305569331642446be05292e3e1f8a51218827168cdclaireho      break;
12315569331642446be05292e3e1f8a51218827168cdclaireho    }
12325569331642446be05292e3e1f8a51218827168cdclaireho    else if ( glyphID < crr[middle].Start )
12335569331642446be05292e3e1f8a51218827168cdclaireho    {
12345569331642446be05292e3e1f8a51218827168cdclaireho      if ( middle == min )
12355569331642446be05292e3e1f8a51218827168cdclaireho      {
12365569331642446be05292e3e1f8a51218827168cdclaireho	*klass = 0;
12375569331642446be05292e3e1f8a51218827168cdclaireho	error  = HB_Err_Not_Covered;
12385569331642446be05292e3e1f8a51218827168cdclaireho	break;
12395569331642446be05292e3e1f8a51218827168cdclaireho      }
12405569331642446be05292e3e1f8a51218827168cdclaireho      new_max = middle - 1;
12415569331642446be05292e3e1f8a51218827168cdclaireho    }
12425569331642446be05292e3e1f8a51218827168cdclaireho    else
12435569331642446be05292e3e1f8a51218827168cdclaireho    {
12445569331642446be05292e3e1f8a51218827168cdclaireho      if ( middle == max )
12455569331642446be05292e3e1f8a51218827168cdclaireho      {
12465569331642446be05292e3e1f8a51218827168cdclaireho	*klass = 0;
12475569331642446be05292e3e1f8a51218827168cdclaireho	error  = HB_Err_Not_Covered;
12485569331642446be05292e3e1f8a51218827168cdclaireho	break;
12495569331642446be05292e3e1f8a51218827168cdclaireho      }
12505569331642446be05292e3e1f8a51218827168cdclaireho      new_min = middle + 1;
12515569331642446be05292e3e1f8a51218827168cdclaireho    }
12525569331642446be05292e3e1f8a51218827168cdclaireho  } while ( min < max );
12535569331642446be05292e3e1f8a51218827168cdclaireho
12545569331642446be05292e3e1f8a51218827168cdclaireho  if ( index )
12555569331642446be05292e3e1f8a51218827168cdclaireho    *index = middle;
12565569331642446be05292e3e1f8a51218827168cdclaireho
12575569331642446be05292e3e1f8a51218827168cdclaireho  return error;
12585569331642446be05292e3e1f8a51218827168cdclaireho}
12595569331642446be05292e3e1f8a51218827168cdclaireho
12605569331642446be05292e3e1f8a51218827168cdclaireho
12615569331642446be05292e3e1f8a51218827168cdclairehoHB_INTERNAL HB_Error
12625569331642446be05292e3e1f8a51218827168cdclaireho_HB_OPEN_Get_Class( HB_ClassDefinition* cd,
12635569331642446be05292e3e1f8a51218827168cdclaireho		     HB_UShort             glyphID,
12645569331642446be05292e3e1f8a51218827168cdclaireho		    HB_UShort*          klass,
12655569331642446be05292e3e1f8a51218827168cdclaireho		     HB_UShort*            index )
12665569331642446be05292e3e1f8a51218827168cdclaireho{
12675569331642446be05292e3e1f8a51218827168cdclaireho  switch ( cd->ClassFormat )
12685569331642446be05292e3e1f8a51218827168cdclaireho  {
12695569331642446be05292e3e1f8a51218827168cdclaireho  case 1:  return Get_Class1( &cd->cd.cd1, glyphID, klass, index );
12705569331642446be05292e3e1f8a51218827168cdclaireho  case 2:  return Get_Class2( &cd->cd.cd2, glyphID, klass, index );
12715569331642446be05292e3e1f8a51218827168cdclaireho  default: return ERR(HB_Err_Invalid_SubTable_Format);
12725569331642446be05292e3e1f8a51218827168cdclaireho  }
12735569331642446be05292e3e1f8a51218827168cdclaireho
12745569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;               /* never reached */
12755569331642446be05292e3e1f8a51218827168cdclaireho}
12765569331642446be05292e3e1f8a51218827168cdclaireho
12775569331642446be05292e3e1f8a51218827168cdclaireho
12785569331642446be05292e3e1f8a51218827168cdclaireho
12795569331642446be05292e3e1f8a51218827168cdclaireho/***************************
12805569331642446be05292e3e1f8a51218827168cdclaireho * Device related functions
12815569331642446be05292e3e1f8a51218827168cdclaireho ***************************/
12825569331642446be05292e3e1f8a51218827168cdclaireho
12835569331642446be05292e3e1f8a51218827168cdclaireho
12845569331642446be05292e3e1f8a51218827168cdclairehoHB_INTERNAL HB_Error
128557e6107a9d66a9a97b146def0ef38c010f954be6claireho_HB_OPEN_Load_Device( HB_Device** device,
12865569331642446be05292e3e1f8a51218827168cdclaireho		       HB_Stream    stream )
12875569331642446be05292e3e1f8a51218827168cdclaireho{
128857e6107a9d66a9a97b146def0ef38c010f954be6claireho  HB_Device*  d;
12895569331642446be05292e3e1f8a51218827168cdclaireho  HB_Error   error;
12905569331642446be05292e3e1f8a51218827168cdclaireho
12915569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort   n, count;
12925569331642446be05292e3e1f8a51218827168cdclaireho
12935569331642446be05292e3e1f8a51218827168cdclaireho  HB_UShort*  dv;
12945569331642446be05292e3e1f8a51218827168cdclaireho
12955569331642446be05292e3e1f8a51218827168cdclaireho
12965569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( 6L ) )
12975569331642446be05292e3e1f8a51218827168cdclaireho    return error;
12985569331642446be05292e3e1f8a51218827168cdclaireho
129957e6107a9d66a9a97b146def0ef38c010f954be6claireho  if ( ALLOC( *device, sizeof(HB_Device)) )
130057e6107a9d66a9a97b146def0ef38c010f954be6claireho  {
130157e6107a9d66a9a97b146def0ef38c010f954be6claireho    *device = 0;
130257e6107a9d66a9a97b146def0ef38c010f954be6claireho    return error;
130357e6107a9d66a9a97b146def0ef38c010f954be6claireho  }
130457e6107a9d66a9a97b146def0ef38c010f954be6claireho
130557e6107a9d66a9a97b146def0ef38c010f954be6claireho  d = *device;
130657e6107a9d66a9a97b146def0ef38c010f954be6claireho
13075569331642446be05292e3e1f8a51218827168cdclaireho  d->StartSize   = GET_UShort();
13085569331642446be05292e3e1f8a51218827168cdclaireho  d->EndSize     = GET_UShort();
13095569331642446be05292e3e1f8a51218827168cdclaireho  d->DeltaFormat = GET_UShort();
13105569331642446be05292e3e1f8a51218827168cdclaireho
13115569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
13125569331642446be05292e3e1f8a51218827168cdclaireho
13135569331642446be05292e3e1f8a51218827168cdclaireho  d->DeltaValue = NULL;
13145569331642446be05292e3e1f8a51218827168cdclaireho
13155569331642446be05292e3e1f8a51218827168cdclaireho  if ( d->StartSize > d->EndSize ||
13165569331642446be05292e3e1f8a51218827168cdclaireho       d->DeltaFormat == 0 || d->DeltaFormat > 3 )
13175569331642446be05292e3e1f8a51218827168cdclaireho    {
13185569331642446be05292e3e1f8a51218827168cdclaireho      /* XXX
13195569331642446be05292e3e1f8a51218827168cdclaireho       * I've seen fontforge generate DeltaFormat == 0.
13205569331642446be05292e3e1f8a51218827168cdclaireho       * Just return Ok and let the NULL DeltaValue disable
13215569331642446be05292e3e1f8a51218827168cdclaireho       * this table.
13225569331642446be05292e3e1f8a51218827168cdclaireho       */
13235569331642446be05292e3e1f8a51218827168cdclaireho      return HB_Err_Ok;
13245569331642446be05292e3e1f8a51218827168cdclaireho    }
13255569331642446be05292e3e1f8a51218827168cdclaireho
13265569331642446be05292e3e1f8a51218827168cdclaireho  count = ( ( d->EndSize - d->StartSize + 1 ) >>
13275569331642446be05292e3e1f8a51218827168cdclaireho	      ( 4 - d->DeltaFormat ) ) + 1;
13285569331642446be05292e3e1f8a51218827168cdclaireho
13295569331642446be05292e3e1f8a51218827168cdclaireho  if ( ALLOC_ARRAY( d->DeltaValue, count, HB_UShort ) )
133057e6107a9d66a9a97b146def0ef38c010f954be6claireho  {
133157e6107a9d66a9a97b146def0ef38c010f954be6claireho    FREE( *device );
133257e6107a9d66a9a97b146def0ef38c010f954be6claireho    *device = 0;
13335569331642446be05292e3e1f8a51218827168cdclaireho    return error;
133457e6107a9d66a9a97b146def0ef38c010f954be6claireho  }
13355569331642446be05292e3e1f8a51218827168cdclaireho
13365569331642446be05292e3e1f8a51218827168cdclaireho  if ( ACCESS_Frame( count * 2L ) )
13375569331642446be05292e3e1f8a51218827168cdclaireho  {
13385569331642446be05292e3e1f8a51218827168cdclaireho    FREE( d->DeltaValue );
133957e6107a9d66a9a97b146def0ef38c010f954be6claireho    FREE( *device );
134057e6107a9d66a9a97b146def0ef38c010f954be6claireho    *device = 0;
13415569331642446be05292e3e1f8a51218827168cdclaireho    return error;
13425569331642446be05292e3e1f8a51218827168cdclaireho  }
13435569331642446be05292e3e1f8a51218827168cdclaireho
13445569331642446be05292e3e1f8a51218827168cdclaireho  dv = d->DeltaValue;
13455569331642446be05292e3e1f8a51218827168cdclaireho
13465569331642446be05292e3e1f8a51218827168cdclaireho  for ( n = 0; n < count; n++ )
13475569331642446be05292e3e1f8a51218827168cdclaireho    dv[n] = GET_UShort();
13485569331642446be05292e3e1f8a51218827168cdclaireho
13495569331642446be05292e3e1f8a51218827168cdclaireho  FORGET_Frame();
13505569331642446be05292e3e1f8a51218827168cdclaireho
13515569331642446be05292e3e1f8a51218827168cdclaireho  return HB_Err_Ok;
13525569331642446be05292e3e1f8a51218827168cdclaireho}
13535569331642446be05292e3e1f8a51218827168cdclaireho
13545569331642446be05292e3e1f8a51218827168cdclaireho
13555569331642446be05292e3e1f8a51218827168cdclairehoHB_INTERNAL void
13565569331642446be05292e3e1f8a51218827168cdclaireho_HB_OPEN_Free_Device( HB_Device* d )
13575569331642446be05292e3e1f8a51218827168cdclaireho{
135857e6107a9d66a9a97b146def0ef38c010f954be6claireho  if ( d )
135957e6107a9d66a9a97b146def0ef38c010f954be6claireho  {
136057e6107a9d66a9a97b146def0ef38c010f954be6claireho    FREE( d->DeltaValue );
136157e6107a9d66a9a97b146def0ef38c010f954be6claireho    FREE( d );
136257e6107a9d66a9a97b146def0ef38c010f954be6claireho  }
13635569331642446be05292e3e1f8a51218827168cdclaireho}
13645569331642446be05292e3e1f8a51218827168cdclaireho
13655569331642446be05292e3e1f8a51218827168cdclaireho
13665569331642446be05292e3e1f8a51218827168cdclaireho/* Since we have the delta values stored in compressed form, we must
13675569331642446be05292e3e1f8a51218827168cdclaireho   uncompress it now.  To simplify the interface, the function always
13685569331642446be05292e3e1f8a51218827168cdclaireho   returns a meaningful value in `value'; the error is just for
13695569331642446be05292e3e1f8a51218827168cdclaireho   information.
13705569331642446be05292e3e1f8a51218827168cdclaireho			       |                |
13715569331642446be05292e3e1f8a51218827168cdclaireho   format = 1: 0011223344556677|8899101112131415|...
13725569331642446be05292e3e1f8a51218827168cdclaireho			       |                |
13735569331642446be05292e3e1f8a51218827168cdclaireho		    byte 1           byte 2
13745569331642446be05292e3e1f8a51218827168cdclaireho
13755569331642446be05292e3e1f8a51218827168cdclaireho     00: (byte >> 14) & mask
13765569331642446be05292e3e1f8a51218827168cdclaireho     11: (byte >> 12) & mask
13775569331642446be05292e3e1f8a51218827168cdclaireho     ...
13785569331642446be05292e3e1f8a51218827168cdclaireho
13795569331642446be05292e3e1f8a51218827168cdclaireho     mask = 0x0003
13805569331642446be05292e3e1f8a51218827168cdclaireho			       |                |
13815569331642446be05292e3e1f8a51218827168cdclaireho   format = 2: 0000111122223333|4444555566667777|...
13825569331642446be05292e3e1f8a51218827168cdclaireho			       |                |
13835569331642446be05292e3e1f8a51218827168cdclaireho		    byte 1           byte 2
13845569331642446be05292e3e1f8a51218827168cdclaireho
13855569331642446be05292e3e1f8a51218827168cdclaireho     0000: (byte >> 12) & mask
13865569331642446be05292e3e1f8a51218827168cdclaireho     1111: (byte >>  8) & mask
13875569331642446be05292e3e1f8a51218827168cdclaireho     ...
13885569331642446be05292e3e1f8a51218827168cdclaireho
13895569331642446be05292e3e1f8a51218827168cdclaireho     mask = 0x000F
13905569331642446be05292e3e1f8a51218827168cdclaireho			       |                |
13915569331642446be05292e3e1f8a51218827168cdclaireho   format = 3: 0000000011111111|2222222233333333|...
13925569331642446be05292e3e1f8a51218827168cdclaireho			       |                |
13935569331642446be05292e3e1f8a51218827168cdclaireho		    byte 1           byte 2
13945569331642446be05292e3e1f8a51218827168cdclaireho
13955569331642446be05292e3e1f8a51218827168cdclaireho     00000000: (byte >> 8) & mask
13965569331642446be05292e3e1f8a51218827168cdclaireho     11111111: (byte >> 0) & mask
13975569331642446be05292e3e1f8a51218827168cdclaireho     ....
13985569331642446be05292e3e1f8a51218827168cdclaireho
13995569331642446be05292e3e1f8a51218827168cdclaireho     mask = 0x00FF                                    */
14005569331642446be05292e3e1f8a51218827168cdclaireho
14015569331642446be05292e3e1f8a51218827168cdclairehoHB_INTERNAL HB_Error
14025569331642446be05292e3e1f8a51218827168cdclaireho_HB_OPEN_Get_Device( HB_Device* d,
14035569331642446be05292e3e1f8a51218827168cdclaireho		      HB_UShort    size,
14045569331642446be05292e3e1f8a51218827168cdclaireho		      HB_Short*    value )
14055569331642446be05292e3e1f8a51218827168cdclaireho{
140657e6107a9d66a9a97b146def0ef38c010f954be6claireho  HB_UShort  byte, bits, mask, s;
14075569331642446be05292e3e1f8a51218827168cdclaireho
140857e6107a9d66a9a97b146def0ef38c010f954be6claireho  if ( d && d->DeltaValue && size >= d->StartSize && size <= d->EndSize )
14095569331642446be05292e3e1f8a51218827168cdclaireho  {
141057e6107a9d66a9a97b146def0ef38c010f954be6claireho    HB_UShort f = d->DeltaFormat;
14115569331642446be05292e3e1f8a51218827168cdclaireho    s    = size - d->StartSize;
14125569331642446be05292e3e1f8a51218827168cdclaireho    byte = d->DeltaValue[s >> ( 4 - f )];
14135569331642446be05292e3e1f8a51218827168cdclaireho    bits = byte >> ( 16 - ( ( s % ( 1 << ( 4 - f ) ) + 1 ) << f ) );
14145569331642446be05292e3e1f8a51218827168cdclaireho    mask = 0xFFFF >> ( 16 - ( 1 << f ) );
14155569331642446be05292e3e1f8a51218827168cdclaireho
14165569331642446be05292e3e1f8a51218827168cdclaireho    *value = (HB_Short)( bits & mask );
14175569331642446be05292e3e1f8a51218827168cdclaireho
14185569331642446be05292e3e1f8a51218827168cdclaireho    /* conversion to a signed value */
14195569331642446be05292e3e1f8a51218827168cdclaireho
14205569331642446be05292e3e1f8a51218827168cdclaireho    if ( *value >= ( ( mask + 1 ) >> 1 ) )
14215569331642446be05292e3e1f8a51218827168cdclaireho      *value -= mask + 1;
14225569331642446be05292e3e1f8a51218827168cdclaireho
14235569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Ok;
14245569331642446be05292e3e1f8a51218827168cdclaireho  }
14255569331642446be05292e3e1f8a51218827168cdclaireho  else
14265569331642446be05292e3e1f8a51218827168cdclaireho  {
14275569331642446be05292e3e1f8a51218827168cdclaireho    *value = 0;
14285569331642446be05292e3e1f8a51218827168cdclaireho    return HB_Err_Not_Covered;
14295569331642446be05292e3e1f8a51218827168cdclaireho  }
14305569331642446be05292e3e1f8a51218827168cdclaireho}
14315569331642446be05292e3e1f8a51218827168cdclaireho
14325569331642446be05292e3e1f8a51218827168cdclaireho
14335569331642446be05292e3e1f8a51218827168cdclaireho/* END */
1434