11512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/*
21512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * Copyright (C) 1998-2004  David Turner and Werner Lemberg
31512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * Copyright (C) 2006  Behdad Esfahbod
41512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod *
51512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * This is part of HarfBuzz, an OpenType Layout engine library.
61512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod *
71512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * Permission is hereby granted, without written agreement and without
81512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this
91512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * software and its documentation for any purpose, provided that the
101512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * above copyright notice and the following two paragraphs appear in
111512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * all copies of this software.
121512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod *
131512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
141512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
151512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
161512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
171512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * DAMAGE.
181512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod *
191512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
201512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
211512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
221512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
231512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
241512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod */
251512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
261512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod#include "harfbuzz-impl.h"
271512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod#include "harfbuzz-open-private.h"
281512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
291512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
301512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/***************************
311512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * Script related functions
321512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod ***************************/
331512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
341512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
351512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/* LangSys */
361512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
371512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic HB_Error  Load_LangSys( HB_LangSys*  ls,
381512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			       HB_Stream     stream )
391512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
401512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Error   error;
411512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort  n, count;
421512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort* fi;
431512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
441512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
451512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ACCESS_Frame( 6L ) )
461512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
471512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
481512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  ls->LookupOrderOffset    = GET_UShort();    /* should be 0 */
491512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  ls->ReqFeatureIndex      = GET_UShort();
501512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  count = ls->FeatureCount = GET_UShort();
511512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
521512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FORGET_Frame();
531512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
541512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  ls->FeatureIndex = NULL;
551512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
561512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ALLOC_ARRAY( ls->FeatureIndex, count, HB_UShort ) )
571512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
581512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
591512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ACCESS_Frame( count * 2L ) )
601512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
611512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    FREE( ls->FeatureIndex );
621512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
631512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
641512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
651512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  fi = ls->FeatureIndex;
661512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
671512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  for ( n = 0; n < count; n++ )
681512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    fi[n] = GET_UShort();
691512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
701512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FORGET_Frame();
711512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
721512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;
731512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
741512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
751512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
761512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic void  Free_LangSys( HB_LangSys*  ls )
771512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
781512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FREE( ls->FeatureIndex );
791512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
801512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
811512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
821512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/* Script */
831512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
841512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic HB_Error  Load_Script( HB_ScriptTable*  s,
851512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			      HB_Stream    stream )
861512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
871512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Error   error;
881512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort  n, m, count;
891512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UInt   cur_offset, new_offset, base_offset;
901512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
911512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_LangSysRecord*  lsr;
921512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
931512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
941512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  base_offset = FILE_Pos();
951512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
961512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ACCESS_Frame( 2L ) )
971512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
981512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
991512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  new_offset = GET_UShort() + base_offset;
1001512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1011512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FORGET_Frame();
1021512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1031512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( new_offset != base_offset )        /* not a NULL offset */
1041512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
1051512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    cur_offset = FILE_Pos();
1061512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    if ( FILE_Seek( new_offset ) ||
1071512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	 ( error = Load_LangSys( &s->DefaultLangSys,
1081512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod				 stream ) ) != HB_Err_Ok )
1091512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      return error;
1101512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    (void)FILE_Seek( cur_offset );
1111512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
1121512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  else
1131512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
1141512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    /* we create a DefaultLangSys table with no entries */
1151512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1161512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    s->DefaultLangSys.LookupOrderOffset = 0;
1171512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    s->DefaultLangSys.ReqFeatureIndex   = 0xFFFF;
1181512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    s->DefaultLangSys.FeatureCount      = 0;
1191512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    s->DefaultLangSys.FeatureIndex      = NULL;
1201512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
1211512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1221512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ACCESS_Frame( 2L ) )
1231512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    goto Fail2;
1241512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1251512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  count = s->LangSysCount = GET_UShort();
1261512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1271512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  /* safety check; otherwise the official handling of TrueType Open
1281512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod     fonts won't work */
1291512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1301512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( s->LangSysCount == 0 && s->DefaultLangSys.FeatureCount == 0 )
1311512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
1321512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    error = HB_Err_Not_Covered;
1331512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    goto Fail2;
1341512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
1351512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1361512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FORGET_Frame();
1371512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1381512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  s->LangSysRecord = NULL;
1391512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1401512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ALLOC_ARRAY( s->LangSysRecord, count, HB_LangSysRecord ) )
1411512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    goto Fail2;
1421512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1431512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  lsr = s->LangSysRecord;
1441512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1451512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  for ( n = 0; n < count; n++ )
1461512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
1471512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    if ( ACCESS_Frame( 6L ) )
1481512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      goto Fail1;
1491512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1501512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    lsr[n].LangSysTag = GET_ULong();
1511512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    new_offset = GET_UShort() + base_offset;
1521512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1531512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    FORGET_Frame();
1541512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1551512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    cur_offset = FILE_Pos();
1561512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    if ( FILE_Seek( new_offset ) ||
1571512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	 ( error = Load_LangSys( &lsr[n].LangSys, stream ) ) != HB_Err_Ok )
1581512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      goto Fail1;
1591512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    (void)FILE_Seek( cur_offset );
1601512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
1611512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1621512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;
1631512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1641512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodFail1:
1651512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  for ( m = 0; m < n; m++ )
1661512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    Free_LangSys( &lsr[m].LangSys );
1671512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1681512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FREE( s->LangSysRecord );
1691512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1701512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodFail2:
1711512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  Free_LangSys( &s->DefaultLangSys );
1721512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return error;
1731512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
1741512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1751512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1761512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic void  Free_Script( HB_ScriptTable*  s )
1771512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
1781512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort           n, count;
1791512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1801512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_LangSysRecord*  lsr;
1811512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1821512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1831512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  Free_LangSys( &s->DefaultLangSys );
1841512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1851512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( s->LangSysRecord )
1861512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
1871512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    count = s->LangSysCount;
1881512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    lsr   = s->LangSysRecord;
1891512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1901512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    for ( n = 0; n < count; n++ )
1911512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      Free_LangSys( &lsr[n].LangSys );
1921512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1931512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    FREE( lsr );
1941512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
1951512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
1961512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1971512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1981512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/* ScriptList */
1991512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2001512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL HB_Error
2011512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_HB_OPEN_Load_ScriptList( HB_ScriptList* sl,
2021512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			   HB_Stream        stream )
2031512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
2041512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Error   error;
2051512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2061512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort          n, script_count;
2071512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UInt           cur_offset, new_offset, base_offset;
2081512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2091512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_ScriptRecord*  sr;
2101512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2111512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2121512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  base_offset = FILE_Pos();
2131512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2141512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ACCESS_Frame( 2L ) )
2151512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
2161512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2171512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  script_count = GET_UShort();
2181512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2191512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FORGET_Frame();
2201512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2211512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  sl->ScriptRecord = NULL;
2221512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2231512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ALLOC_ARRAY( sl->ScriptRecord, script_count, HB_ScriptRecord ) )
2241512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
2251512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2261512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  sr = sl->ScriptRecord;
2271512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2281512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  sl->ScriptCount= 0;
2291512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  for ( n = 0; n < script_count; n++ )
2301512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
2311512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    if ( ACCESS_Frame( 6L ) )
2321512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      goto Fail;
2331512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2341512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    sr[sl->ScriptCount].ScriptTag = GET_ULong();
2351512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    new_offset = GET_UShort() + base_offset;
2361512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2371512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    FORGET_Frame();
2381512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2391512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    cur_offset = FILE_Pos();
2401512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2411512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    if ( FILE_Seek( new_offset ) )
2421512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      goto Fail;
2431512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2441512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    error = Load_Script( &sr[sl->ScriptCount].Script, stream );
2451512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    if ( error == HB_Err_Ok )
2461512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      sl->ScriptCount += 1;
2471512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    else if ( error != HB_Err_Not_Covered )
2481512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      goto Fail;
2491512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2501512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    (void)FILE_Seek( cur_offset );
2511512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
2521512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2531512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  /* Empty tables are harmless and generated by fontforge.
2541512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   * See http://bugzilla.gnome.org/show_bug.cgi?id=347073
2551512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   */
2561512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod#if 0
2571512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( sl->ScriptCount == 0 )
2581512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
2591512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    error = ERR(HB_Err_Invalid_SubTable);
2601512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    goto Fail;
2611512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
2621512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod#endif
2631512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2641512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;
2651512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2661512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodFail:
2671512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  for ( n = 0; n < sl->ScriptCount; n++ )
2681512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    Free_Script( &sr[n].Script );
2691512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2701512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FREE( sl->ScriptRecord );
2711512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return error;
2721512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
2731512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2741512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2751512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL void
2761512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_HB_OPEN_Free_ScriptList( HB_ScriptList* sl )
2771512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
2781512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort          n, count;
2791512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2801512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_ScriptRecord*  sr;
2811512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2821512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2831512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( sl->ScriptRecord )
2841512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
2851512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    count = sl->ScriptCount;
2861512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    sr    = sl->ScriptRecord;
2871512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2881512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    for ( n = 0; n < count; n++ )
2891512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      Free_Script( &sr[n].Script );
2901512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2911512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    FREE( sr );
2921512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
2931512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
2941512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2951512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2961512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2971512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/*********************************
2981512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * Feature List related functions
2991512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod *********************************/
3001512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3011512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3021512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/* Feature */
3031512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3041512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic HB_Error  Load_Feature( HB_Feature*  f,
3051512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			       HB_Stream     stream )
3061512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
3071512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Error   error;
3081512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3091512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort   n, count;
3101512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3111512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort*  lli;
3121512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3131512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3141512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ACCESS_Frame( 4L ) )
3151512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
3161512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3171512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  f->FeatureParams           = GET_UShort();    /* should be 0 */
3181512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  count = f->LookupListCount = GET_UShort();
3191512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3201512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FORGET_Frame();
3211512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3221512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  f->LookupListIndex = NULL;
3231512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3241512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ALLOC_ARRAY( f->LookupListIndex, count, HB_UShort ) )
3251512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
3261512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3271512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  lli = f->LookupListIndex;
3281512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3291512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ACCESS_Frame( count * 2L ) )
3301512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
3311512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    FREE( f->LookupListIndex );
3321512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
3331512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
3341512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3351512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  for ( n = 0; n < count; n++ )
3361512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    lli[n] = GET_UShort();
3371512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3381512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FORGET_Frame();
3391512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3401512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;
3411512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
3421512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3431512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3441512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic void  Free_Feature( HB_Feature*  f )
3451512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
3461512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FREE( f->LookupListIndex );
3471512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
3481512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3491512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3501512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/* FeatureList */
3511512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3521512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL HB_Error
3531512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_HB_OPEN_Load_FeatureList( HB_FeatureList* fl,
3541512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			    HB_Stream         stream )
3551512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
3561512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Error   error;
3571512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3581512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort           n, m, count;
3591512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UInt            cur_offset, new_offset, base_offset;
3601512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3611512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_FeatureRecord*  fr;
3621512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3631512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3641512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  base_offset = FILE_Pos();
3651512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3661512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ACCESS_Frame( 2L ) )
3671512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
3681512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3691512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  count = fl->FeatureCount = GET_UShort();
3701512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3711512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FORGET_Frame();
3721512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3731512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  fl->FeatureRecord = NULL;
3741512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3751512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ALLOC_ARRAY( fl->FeatureRecord, count, HB_FeatureRecord ) )
3761512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
3771512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ALLOC_ARRAY( fl->ApplyOrder, count, HB_UShort ) )
3781512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    goto Fail2;
3791512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3801512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  fl->ApplyCount = 0;
3811512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3821512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  fr = fl->FeatureRecord;
3831512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3841512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  for ( n = 0; n < count; n++ )
3851512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
3861512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    if ( ACCESS_Frame( 6L ) )
3871512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      goto Fail1;
3881512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3891512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    fr[n].FeatureTag = GET_ULong();
3901512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    new_offset = GET_UShort() + base_offset;
3911512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3921512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    FORGET_Frame();
3931512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3941512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    cur_offset = FILE_Pos();
3951512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    if ( FILE_Seek( new_offset ) ||
3961512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	 ( error = Load_Feature( &fr[n].Feature, stream ) ) != HB_Err_Ok )
3971512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      goto Fail1;
3981512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    (void)FILE_Seek( cur_offset );
3991512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
4001512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4011512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;
4021512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4031512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodFail1:
4041512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  for ( m = 0; m < n; m++ )
4051512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    Free_Feature( &fr[m].Feature );
4061512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4071512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FREE( fl->ApplyOrder );
4081512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4091512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodFail2:
4101512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FREE( fl->FeatureRecord );
4111512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4121512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return error;
4131512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
4141512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4151512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4161512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL void
4171512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_HB_OPEN_Free_FeatureList( HB_FeatureList*  fl )
4181512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
4191512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort           n, count;
4201512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4211512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_FeatureRecord*  fr;
4221512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4231512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4241512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( fl->FeatureRecord )
4251512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
4261512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    count = fl->FeatureCount;
4271512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    fr    = fl->FeatureRecord;
4281512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4291512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    for ( n = 0; n < count; n++ )
4301512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      Free_Feature( &fr[n].Feature );
4311512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4321512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    FREE( fr );
4331512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
4341512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4351512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FREE( fl->ApplyOrder );
4361512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
4371512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4381512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4391512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4401512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/********************************
4411512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * Lookup List related functions
4421512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod ********************************/
4431512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4441512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/* the subroutines of the following two functions are defined in
4451512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   ftxgsub.c and ftxgpos.c respectively                          */
4461512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4471512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4481512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/* SubTable */
4491512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4501512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic HB_Error  Load_SubTable( HB_SubTable*  st,
4511512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod				HB_Stream     stream,
4521512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod				HB_Type       table_type,
4531512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod				HB_UShort     lookup_type )
4541512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
4551512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( table_type == HB_Type_GSUB )
4561512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return _HB_GSUB_Load_SubTable ( &st->st.gsub, stream, lookup_type );
4571512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  else
4581512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return _HB_GPOS_Load_SubTable ( &st->st.gpos, stream, lookup_type );
4591512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
4601512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4611512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4621512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic void  Free_SubTable( HB_SubTable*  st,
4631512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			    HB_Type       table_type,
4641512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			    HB_UShort      lookup_type )
4651512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
4661512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( table_type == HB_Type_GSUB )
4671512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    _HB_GSUB_Free_SubTable ( &st->st.gsub, lookup_type );
4681512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  else
4691512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    _HB_GPOS_Free_SubTable ( &st->st.gpos, lookup_type );
4701512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
4711512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4721512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4731512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/* Lookup */
4741512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4751512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic HB_Error  Load_Lookup( HB_Lookup*   l,
4761512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			      HB_Stream     stream,
4771512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			      HB_Type      type )
4781512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
4791512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Error   error;
4801512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4811512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort      n, m, count;
4821512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UInt       cur_offset, new_offset, base_offset;
4831512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4841512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_SubTable*  st;
4851512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4861512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Bool        is_extension = FALSE;
4871512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4881512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4891512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  base_offset = FILE_Pos();
4901512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4911512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ACCESS_Frame( 6L ) )
4921512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
4931512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4941512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  l->LookupType            = GET_UShort();
4951512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  l->LookupFlag            = GET_UShort();
4961512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  count = l->SubTableCount = GET_UShort();
4971512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
4981512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FORGET_Frame();
4991512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5001512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  l->SubTable = NULL;
5011512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5021512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ALLOC_ARRAY( l->SubTable, count, HB_SubTable ) )
5031512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
5041512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5051512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  st = l->SubTable;
5061512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5071512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ( type == HB_Type_GSUB && l->LookupType == HB_GSUB_LOOKUP_EXTENSION ) ||
5081512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod       ( type == HB_Type_GPOS && l->LookupType == HB_GPOS_LOOKUP_EXTENSION ) )
5091512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    is_extension = TRUE;
5101512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5111512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  for ( n = 0; n < count; n++ )
5121512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
5131512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    if ( ACCESS_Frame( 2L ) )
5141512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      goto Fail;
5151512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5161512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    new_offset = GET_UShort() + base_offset;
5171512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5181512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    FORGET_Frame();
5191512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5201512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    cur_offset = FILE_Pos();
5211512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5221512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    if ( is_extension )
5231512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
5241512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      if ( FILE_Seek( new_offset ) || ACCESS_Frame( 8L ) )
5251512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	goto Fail;
5261512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5271512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      if (GET_UShort() != 1) /* format should be 1 */
5281512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	goto Fail;
5291512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5301512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      l->LookupType = GET_UShort();
5311512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      new_offset += GET_ULong();
5321512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5331512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      FORGET_Frame();
5341512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
5351512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5361512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    if ( FILE_Seek( new_offset ) ||
5371512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	 ( error = Load_SubTable( &st[n], stream,
5381512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod				  type, l->LookupType ) ) != HB_Err_Ok )
5391512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      goto Fail;
5401512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    (void)FILE_Seek( cur_offset );
5411512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
5421512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5431512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;
5441512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5451512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodFail:
5461512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  for ( m = 0; m < n; m++ )
5471512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    Free_SubTable( &st[m], type, l->LookupType );
5481512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5491512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FREE( l->SubTable );
5501512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return error;
5511512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
5521512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5531512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5541512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic void  Free_Lookup( HB_Lookup*   l,
5551512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			  HB_Type      type)
5561512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
5571512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort      n, count;
5581512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5591512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_SubTable*  st;
5601512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5611512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5621512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( l->SubTable )
5631512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
5641512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    count = l->SubTableCount;
5651512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    st    = l->SubTable;
5661512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5671512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    for ( n = 0; n < count; n++ )
5681512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      Free_SubTable( &st[n], type, l->LookupType );
5691512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5701512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    FREE( st );
5711512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
5721512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
5731512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5741512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5751512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/* LookupList */
5761512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5771512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL HB_Error
5781512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_HB_OPEN_Load_LookupList( HB_LookupList* ll,
5791512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			   HB_Stream        stream,
5801512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			   HB_Type         type )
5811512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
5821512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Error   error;
5831512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5841512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort    n, m, count;
5851512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UInt     cur_offset, new_offset, base_offset;
5861512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5871512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Lookup*  l;
5881512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5891512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5901512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  base_offset = FILE_Pos();
5911512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5921512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ACCESS_Frame( 2L ) )
5931512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
5941512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5951512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  count = ll->LookupCount = GET_UShort();
5961512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5971512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FORGET_Frame();
5981512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
5991512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  ll->Lookup = NULL;
6001512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6011512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ALLOC_ARRAY( ll->Lookup, count, HB_Lookup ) )
6021512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
6031512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ALLOC_ARRAY( ll->Properties, count, HB_UInt ) )
6041512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    goto Fail2;
6051512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6061512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  l = ll->Lookup;
6071512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6081512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  for ( n = 0; n < count; n++ )
6091512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
6101512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    if ( ACCESS_Frame( 2L ) )
6111512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      goto Fail1;
6121512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6131512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    new_offset = GET_UShort() + base_offset;
6141512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6151512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    FORGET_Frame();
6161512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6171512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    cur_offset = FILE_Pos();
6181512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    if ( FILE_Seek( new_offset ) ||
6191512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	 ( error = Load_Lookup( &l[n], stream, type ) ) != HB_Err_Ok )
6201512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      goto Fail1;
6211512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    (void)FILE_Seek( cur_offset );
6221512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
6231512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6241512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;
6251512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6261512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodFail1:
6271512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FREE( ll->Properties );
6281512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6291512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  for ( m = 0; m < n; m++ )
6301512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    Free_Lookup( &l[m], type );
6311512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6321512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodFail2:
6331512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FREE( ll->Lookup );
6341512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return error;
6351512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
6361512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6371512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6381512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL void
6391512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_HB_OPEN_Free_LookupList( HB_LookupList* ll,
6401512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod		       HB_Type         type )
6411512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
6421512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort    n, count;
6431512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6441512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Lookup*  l;
6451512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6461512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6471512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FREE( ll->Properties );
6481512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6491512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ll->Lookup )
6501512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
6511512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    count = ll->LookupCount;
6521512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    l     = ll->Lookup;
6531512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6541512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    for ( n = 0; n < count; n++ )
6551512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      Free_Lookup( &l[n], type );
6561512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6571512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    FREE( l );
6581512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
6591512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
6601512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6611512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6621512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6631512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/*****************************
6641512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * Coverage related functions
6651512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod *****************************/
6661512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6671512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6681512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/* CoverageFormat1 */
6691512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6701512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic HB_Error  Load_Coverage1( HB_CoverageFormat1*  cf1,
6711512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod				 HB_Stream             stream )
6721512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
6731512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Error   error;
6741512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6751512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort  n, count;
6761512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6771512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort* ga;
6781512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6791512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6801512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ACCESS_Frame( 2L ) )
6811512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
6821512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6831512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  count = cf1->GlyphCount = GET_UShort();
6841512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6851512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FORGET_Frame();
6861512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6871512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  cf1->GlyphArray = NULL;
6881512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6891512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ALLOC_ARRAY( cf1->GlyphArray, count, HB_UShort ) )
6901512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
6911512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6921512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  ga = cf1->GlyphArray;
6931512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
6941512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ACCESS_Frame( count * 2L ) )
6951512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
6961512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    FREE( cf1->GlyphArray );
6971512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
6981512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
6991512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7001512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  for ( n = 0; n < count; n++ )
7011512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    ga[n] = GET_UShort();
7021512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7031512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FORGET_Frame();
7041512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7051512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;
7061512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
7071512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7081512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7091512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic void  Free_Coverage1( HB_CoverageFormat1*  cf1)
7101512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
7111512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FREE( cf1->GlyphArray );
7121512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
7131512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7141512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7151512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/* CoverageFormat2 */
7161512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7171512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic HB_Error  Load_Coverage2( HB_CoverageFormat2*  cf2,
7181512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod				 HB_Stream             stream )
7191512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
7201512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Error   error;
7211512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7221512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort         n, count;
7231512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7241512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_RangeRecord*  rr;
7251512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7261512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7271512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ACCESS_Frame( 2L ) )
7281512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
7291512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7301512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  count = cf2->RangeCount = GET_UShort();
7311512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7321512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FORGET_Frame();
7331512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7341512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  cf2->RangeRecord = NULL;
7351512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7361512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ALLOC_ARRAY( cf2->RangeRecord, count, HB_RangeRecord ) )
7371512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
7381512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7391512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  rr = cf2->RangeRecord;
7401512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7411512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ACCESS_Frame( count * 6L ) )
7421512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    goto Fail;
7431512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7441512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  for ( n = 0; n < count; n++ )
7451512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
7461512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    rr[n].Start              = GET_UShort();
7471512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    rr[n].End                = GET_UShort();
7481512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    rr[n].StartCoverageIndex = GET_UShort();
7491512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7501512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    /* sanity check; we are limited to 16bit integers */
7511512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    if ( rr[n].Start > rr[n].End ||
7521512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	 ( rr[n].End - rr[n].Start + (long)rr[n].StartCoverageIndex ) >=
7531512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	   0x10000L )
7541512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
7551512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      error = ERR(HB_Err_Invalid_SubTable);
7561512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      goto Fail;
7571512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
7581512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
7591512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7601512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FORGET_Frame();
7611512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7621512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;
7631512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7641512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodFail:
7651512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FREE( cf2->RangeRecord );
7661512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return error;
7671512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
7681512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7691512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7701512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic void  Free_Coverage2( HB_CoverageFormat2*  cf2 )
7711512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
7721512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FREE( cf2->RangeRecord );
7731512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
7741512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7751512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7761512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL HB_Error
7771512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_HB_OPEN_Load_Coverage( HB_Coverage* c,
7781512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			 HB_Stream      stream )
7791512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
7801512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Error   error;
7811512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7821512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ACCESS_Frame( 2L ) )
7831512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
7841512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7851512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  c->CoverageFormat = GET_UShort();
7861512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7871512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FORGET_Frame();
7881512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7891512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  switch ( c->CoverageFormat )
7901512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
7911512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  case 1:  return Load_Coverage1( &c->cf.cf1, stream );
7921512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  case 2:  return Load_Coverage2( &c->cf.cf2, stream );
7931512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  default: return ERR(HB_Err_Invalid_SubTable_Format);
7941512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
7951512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7961512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;               /* never reached */
7971512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
7981512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
7991512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8001512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL void
8011512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_HB_OPEN_Free_Coverage( HB_Coverage* c )
8021512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
8031512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  switch ( c->CoverageFormat )
8041512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
8051512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  case 1:  Free_Coverage1( &c->cf.cf1 ); break;
8061512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  case 2:  Free_Coverage2( &c->cf.cf2 ); break;
8071512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  default:					 break;
8081512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
8091512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
8101512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8111512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8121512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic HB_Error  Coverage_Index1( HB_CoverageFormat1*  cf1,
8131512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod				  HB_UShort             glyphID,
8141512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod				  HB_UShort*            index )
8151512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
8161512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort min, max, new_min, new_max, middle;
8171512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8181512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort*  array = cf1->GlyphArray;
8191512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8201512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8211512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  /* binary search */
8221512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8231512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( cf1->GlyphCount == 0 )
8241512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return HB_Err_Not_Covered;
8251512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8261512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  new_min = 0;
8271512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  new_max = cf1->GlyphCount - 1;
8281512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8291512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  do
8301512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
8311512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    min = new_min;
8321512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    max = new_max;
8331512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8341512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    /* we use (min + max) / 2 = max - (max - min) / 2  to avoid
8351512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod       overflow and rounding errors                             */
8361512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8371512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    middle = max - ( ( max - min ) >> 1 );
8381512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8391512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    if ( glyphID == array[middle] )
8401512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
8411512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      *index = middle;
8421512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      return HB_Err_Ok;
8431512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
8441512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    else if ( glyphID < array[middle] )
8451512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
8461512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      if ( middle == min )
8471512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	break;
8481512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      new_max = middle - 1;
8491512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
8501512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    else
8511512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
8521512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      if ( middle == max )
8531512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	break;
8541512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      new_min = middle + 1;
8551512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
8561512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  } while ( min < max );
8571512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8581512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Not_Covered;
8591512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
8601512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8611512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8621512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic HB_Error  Coverage_Index2( HB_CoverageFormat2*  cf2,
8631512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod				  HB_UShort             glyphID,
8641512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod				  HB_UShort*            index )
8651512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
8661512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort         min, max, new_min, new_max, middle;
8671512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8681512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_RangeRecord*  rr = cf2->RangeRecord;
8691512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8701512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8711512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  /* binary search */
8721512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8731512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( cf2->RangeCount == 0 )
8741512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return HB_Err_Not_Covered;
8751512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8761512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  new_min = 0;
8771512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  new_max = cf2->RangeCount - 1;
8781512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8791512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  do
8801512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
8811512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    min = new_min;
8821512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    max = new_max;
8831512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8841512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    /* we use (min + max) / 2 = max - (max - min) / 2  to avoid
8851512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod       overflow and rounding errors                             */
8861512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8871512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    middle = max - ( ( max - min ) >> 1 );
8881512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
8891512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    if ( glyphID >= rr[middle].Start && glyphID <= rr[middle].End )
8901512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
8911512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      *index = rr[middle].StartCoverageIndex + glyphID - rr[middle].Start;
8921512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      return HB_Err_Ok;
8931512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
8941512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    else if ( glyphID < rr[middle].Start )
8951512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
8961512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      if ( middle == min )
8971512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	break;
8981512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      new_max = middle - 1;
8991512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
9001512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    else
9011512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
9021512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      if ( middle == max )
9031512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	break;
9041512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      new_min = middle + 1;
9051512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
9061512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  } while ( min < max );
9071512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9081512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Not_Covered;
9091512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
9101512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9111512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9121512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL HB_Error
9131512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_HB_OPEN_Coverage_Index( HB_Coverage* c,
9141512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			  HB_UShort      glyphID,
9151512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			  HB_UShort*     index )
9161512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
9171512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  switch ( c->CoverageFormat )
9181512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
9191512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  case 1:  return Coverage_Index1( &c->cf.cf1, glyphID, index );
9201512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  case 2:  return Coverage_Index2( &c->cf.cf2, glyphID, index );
9211512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  default: return ERR(HB_Err_Invalid_SubTable_Format);
9221512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
9231512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9241512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;               /* never reached */
9251512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
9261512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9271512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9281512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9291512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/*************************************
9301512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * Class Definition related functions
9311512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod *************************************/
9321512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9331512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9341512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/* ClassDefFormat1 */
9351512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9361512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic HB_Error  Load_ClassDef1( HB_ClassDefinition*  cd,
9371512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod				 HB_UShort             limit,
9381512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod				 HB_Stream             stream )
9391512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
9401512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Error   error;
9411512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9421512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort             n, count;
9431512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9441512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort*            cva;
9451512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9461512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_ClassDefFormat1*  cdf1;
9471512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9481512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9491512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  cdf1 = &cd->cd.cd1;
9501512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9511512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ACCESS_Frame( 4L ) )
9521512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
9531512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9541512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  cdf1->StartGlyph         = GET_UShort();
9551512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  count = cdf1->GlyphCount = GET_UShort();
9561512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9571512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FORGET_Frame();
9581512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9591512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  /* sanity check; we are limited to 16bit integers */
9601512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9611512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( cdf1->StartGlyph + (long)count >= 0x10000L )
9621512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return ERR(HB_Err_Invalid_SubTable);
9631512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9641512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  cdf1->ClassValueArray = NULL;
9651512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9661512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ALLOC_ARRAY( cdf1->ClassValueArray, count, HB_UShort ) )
9671512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
9681512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9691512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  cva = cdf1->ClassValueArray;
9701512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9711512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ACCESS_Frame( count * 2L ) )
9721512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    goto Fail;
9731512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9741512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  for ( n = 0; n < count; n++ )
9751512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
9761512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    cva[n] = GET_UShort();
9771512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    if ( cva[n] >= limit )
9781512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
9791512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      error = ERR(HB_Err_Invalid_SubTable);
9801512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      goto Fail;
9811512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
9821512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
9831512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9841512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FORGET_Frame();
9851512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9861512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;
9871512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9881512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodFail:
9891512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FREE( cva );
9901512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9911512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return error;
9921512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
9931512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9941512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
9951512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic void  Free_ClassDef1( HB_ClassDefFormat1*  cdf1 )
9961512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
9971512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FREE( cdf1->ClassValueArray );
9981512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
9991512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10001512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10011512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/* ClassDefFormat2 */
10021512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10031512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic HB_Error  Load_ClassDef2( HB_ClassDefinition*  cd,
10041512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod				 HB_UShort             limit,
10051512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod				 HB_Stream             stream )
10061512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
10071512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Error   error;
10081512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10091512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort              n, count;
10101512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10111512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_ClassRangeRecord*  crr;
10121512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10131512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_ClassDefFormat2*   cdf2;
10141512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10151512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10161512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  cdf2 = &cd->cd.cd2;
10171512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10181512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ACCESS_Frame( 2L ) )
10191512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
10201512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10211512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  count = GET_UShort();
10221512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  cdf2->ClassRangeCount = 0; /* zero for now.  we fill with the number of good entries later */
10231512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10241512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FORGET_Frame();
10251512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10261512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  cdf2->ClassRangeRecord = NULL;
10271512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10281512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ALLOC_ARRAY( cdf2->ClassRangeRecord, count, HB_ClassRangeRecord ) )
10291512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
10301512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10311512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  crr = cdf2->ClassRangeRecord;
10321512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10331512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ACCESS_Frame( count * 6L ) )
10341512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    goto Fail;
10351512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10361512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  for ( n = 0; n < count; n++ )
10371512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
10381512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    crr[n].Start = GET_UShort();
10391512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    crr[n].End   = GET_UShort();
10401512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    crr[n].Class = GET_UShort();
10411512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10421512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    /* sanity check */
10431512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10441512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    if ( crr[n].Start > crr[n].End ||
10451512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	 crr[n].Class >= limit )
10461512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
10471512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      /* XXX
10481512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod       * Corrupt entry.  Skip it.
10491512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod       * This is hit by Nafees Nastaliq font for example
10501512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod       */
10511512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod       n--;
10521512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod       count--;
10531512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
10541512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
10551512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10561512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FORGET_Frame();
10571512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10581512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  cdf2->ClassRangeCount = count;
10591512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10601512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;
10611512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10621512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodFail:
10631512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FREE( crr );
10641512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10651512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return error;
10661512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
10671512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10681512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10691512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic void  Free_ClassDef2( HB_ClassDefFormat2*  cdf2 )
10701512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
10711512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FREE( cdf2->ClassRangeRecord );
10721512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
10731512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10741512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10751512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/* ClassDefinition */
10761512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10771512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL HB_Error
10781512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_HB_OPEN_Load_ClassDefinition( HB_ClassDefinition* cd,
10791512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod				HB_UShort             limit,
10801512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod				HB_Stream             stream )
10811512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
10821512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Error   error;
10831512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10841512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ACCESS_Frame( 2L ) )
10851512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
10861512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10871512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  cd->ClassFormat = GET_UShort();
10881512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10891512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FORGET_Frame();
10901512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10911512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  switch ( cd->ClassFormat )
10921512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
10931512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  case 1:  error = Load_ClassDef1( cd, limit, stream ); break;
10941512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  case 2:  error = Load_ClassDef2( cd, limit, stream ); break;
10951512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  default: error = ERR(HB_Err_Invalid_SubTable_Format);	break;
10961512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
10971512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
10981512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( error )
10991512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
11001512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11011512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  cd->loaded = TRUE;
11021512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11031512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;
11041512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
11051512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11061512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11071512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic HB_Error
11081512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_HB_OPEN_Load_EmptyClassDefinition( HB_ClassDefinition*  cd )
11091512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
11101512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Error   error;
11111512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11121512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  cd->ClassFormat = 1; /* Meaningless */
11131512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11141512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ALLOC_ARRAY( cd->cd.cd1.ClassValueArray, 1, HB_UShort ) )
11151512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
11161512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11171512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  cd->loaded = TRUE;
11181512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11191512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;
11201512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
11211512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11221512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL HB_Error
11231512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_HB_OPEN_Load_EmptyOrClassDefinition( HB_ClassDefinition* cd,
11241512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod					       HB_UShort             limit,
11251512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod					       HB_UInt              class_offset,
11261512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod					       HB_UInt              base_offset,
11271512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod					       HB_Stream             stream )
11281512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
11291512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Error error;
11301512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UInt               cur_offset;
11311512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11321512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  cur_offset = FILE_Pos();
11331512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11341512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( class_offset )
11351512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
11361512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      if ( !FILE_Seek( class_offset + base_offset ) )
11371512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	error = _HB_OPEN_Load_ClassDefinition( cd, limit, stream );
11381512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
11391512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  else
11401512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod     error = _HB_OPEN_Load_EmptyClassDefinition ( cd );
11411512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11421512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if (error == HB_Err_Ok)
11431512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    (void)FILE_Seek( cur_offset ); /* Changes error as a side-effect */
11441512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11451512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return error;
11461512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
11471512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11481512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL void
11491512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_HB_OPEN_Free_ClassDefinition( HB_ClassDefinition*  cd )
11501512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
11511512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( !cd->loaded )
11521512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return;
11531512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11541512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  switch ( cd->ClassFormat )
11551512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
11561512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  case 1:  Free_ClassDef1( &cd->cd.cd1 ); break;
11571512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  case 2:  Free_ClassDef2( &cd->cd.cd2 ); break;
11581512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  default:				  break;
11591512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
11601512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
11611512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11621512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11631512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic HB_Error  Get_Class1( HB_ClassDefFormat1*  cdf1,
11641512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			     HB_UShort             glyphID,
11651512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			     HB_UShort*            klass,
11661512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			     HB_UShort*            index )
11671512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
11681512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort*  cva = cdf1->ClassValueArray;
11691512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11701512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11711512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( index )
11721512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    *index = 0;
11731512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11741512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( glyphID >= cdf1->StartGlyph &&
11751512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod       glyphID < cdf1->StartGlyph + cdf1->GlyphCount )
11761512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
11771512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    *klass = cva[glyphID - cdf1->StartGlyph];
11781512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return HB_Err_Ok;
11791512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
11801512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  else
11811512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
11821512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    *klass = 0;
11831512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return HB_Err_Not_Covered;
11841512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
11851512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
11861512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11871512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11881512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/* we need the index value of the last searched class range record
11891512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   in case of failure for constructed GDEF tables                  */
11901512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11911512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic HB_Error  Get_Class2( HB_ClassDefFormat2*  cdf2,
11921512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			     HB_UShort             glyphID,
11931512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			     HB_UShort*            klass,
11941512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			     HB_UShort*            index )
11951512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
11961512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Error               error = HB_Err_Ok;
11971512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort              min, max, new_min, new_max, middle;
11981512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
11991512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_ClassRangeRecord*  crr = cdf2->ClassRangeRecord;
12001512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12011512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12021512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  /* binary search */
12031512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12041512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( cdf2->ClassRangeCount == 0 )
12051512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
12061512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      *klass = 0;
12071512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      if ( index )
12081512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	*index = 0;
12091512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12101512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      return HB_Err_Not_Covered;
12111512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
12121512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12131512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  new_min = 0;
12141512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  new_max = cdf2->ClassRangeCount - 1;
12151512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12161512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  do
12171512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
12181512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    min = new_min;
12191512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    max = new_max;
12201512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12211512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    /* we use (min + max) / 2 = max - (max - min) / 2  to avoid
12221512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod       overflow and rounding errors                             */
12231512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12241512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    middle = max - ( ( max - min ) >> 1 );
12251512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12261512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    if ( glyphID >= crr[middle].Start && glyphID <= crr[middle].End )
12271512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
12281512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      *klass = crr[middle].Class;
12291512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      error  = HB_Err_Ok;
12301512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      break;
12311512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
12321512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    else if ( glyphID < crr[middle].Start )
12331512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
12341512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      if ( middle == min )
12351512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      {
12361512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	*klass = 0;
12371512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	error  = HB_Err_Not_Covered;
12381512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	break;
12391512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      }
12401512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      new_max = middle - 1;
12411512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
12421512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    else
12431512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
12441512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      if ( middle == max )
12451512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      {
12461512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	*klass = 0;
12471512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	error  = HB_Err_Not_Covered;
12481512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	break;
12491512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      }
12501512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      new_min = middle + 1;
12511512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
12521512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  } while ( min < max );
12531512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12541512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( index )
12551512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    *index = middle;
12561512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12571512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return error;
12581512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
12591512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12601512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12611512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL HB_Error
12621512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_HB_OPEN_Get_Class( HB_ClassDefinition* cd,
12631512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod		     HB_UShort             glyphID,
12641512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod		    HB_UShort*          klass,
12651512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod		     HB_UShort*            index )
12661512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
12671512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  switch ( cd->ClassFormat )
12681512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
12691512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  case 1:  return Get_Class1( &cd->cd.cd1, glyphID, klass, index );
12701512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  case 2:  return Get_Class2( &cd->cd.cd2, glyphID, klass, index );
12711512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  default: return ERR(HB_Err_Invalid_SubTable_Format);
12721512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
12731512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12741512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;               /* never reached */
12751512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
12761512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12771512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12781512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12791512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/***************************
12801512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * Device related functions
12811512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod ***************************/
12821512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12831512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12841512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL HB_Error
12851512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_HB_OPEN_Load_Device( HB_Device** device,
12861512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod		       HB_Stream    stream )
12871512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
12881512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Device*  d;
12891512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Error   error;
12901512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12911512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort   n, count;
12921512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12931512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort*  dv;
12941512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12951512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12961512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ACCESS_Frame( 6L ) )
12971512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
12981512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
12991512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ALLOC( *device, sizeof(HB_Device)) )
13001512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
13011512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    *device = 0;
13021512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
13031512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
13041512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
13051512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  d = *device;
13061512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
13071512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  d->StartSize   = GET_UShort();
13081512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  d->EndSize     = GET_UShort();
13091512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  d->DeltaFormat = GET_UShort();
13101512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
13111512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FORGET_Frame();
13121512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
13131512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  d->DeltaValue = NULL;
13141512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
13151512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( d->StartSize > d->EndSize ||
13161512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod       d->DeltaFormat == 0 || d->DeltaFormat > 3 )
13171512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
13181512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      /* XXX
13191512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod       * I've seen fontforge generate DeltaFormat == 0.
13201512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod       * Just return Ok and let the NULL DeltaValue disable
13211512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod       * this table.
13221512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod       */
13231512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      return HB_Err_Ok;
13241512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
13251512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
13261512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  count = ( ( d->EndSize - d->StartSize + 1 ) >>
13271512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	      ( 4 - d->DeltaFormat ) ) + 1;
13281512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
13291512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ALLOC_ARRAY( d->DeltaValue, count, HB_UShort ) )
13301512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
13311512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    FREE( *device );
13321512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    *device = 0;
13331512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
13341512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
13351512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
13361512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ACCESS_Frame( count * 2L ) )
13371512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
13381512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    FREE( d->DeltaValue );
13391512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    FREE( *device );
13401512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    *device = 0;
13411512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
13421512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
13431512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
13441512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  dv = d->DeltaValue;
13451512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
13461512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  for ( n = 0; n < count; n++ )
13471512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    dv[n] = GET_UShort();
13481512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
13491512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FORGET_Frame();
13501512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
13511512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;
13521512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
13531512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
13541512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
13551512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL void
13561512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_HB_OPEN_Free_Device( HB_Device* d )
13571512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
13581512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( d )
13591512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
13601512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    FREE( d->DeltaValue );
13611512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    FREE( d );
13621512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
13631512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
13641512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
13651512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
13661512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/* Since we have the delta values stored in compressed form, we must
13671512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   uncompress it now.  To simplify the interface, the function always
13681512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   returns a meaningful value in `value'; the error is just for
13691512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   information.
13701512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			       |                |
13711512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   format = 1: 0011223344556677|8899101112131415|...
13721512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			       |                |
13731512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod		    byte 1           byte 2
13741512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
13751512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod     00: (byte >> 14) & mask
13761512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod     11: (byte >> 12) & mask
13771512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod     ...
13781512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
13791512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod     mask = 0x0003
13801512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			       |                |
13811512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   format = 2: 0000111122223333|4444555566667777|...
13821512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			       |                |
13831512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod		    byte 1           byte 2
13841512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
13851512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod     0000: (byte >> 12) & mask
13861512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod     1111: (byte >>  8) & mask
13871512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod     ...
13881512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
13891512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod     mask = 0x000F
13901512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			       |                |
13911512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   format = 3: 0000000011111111|2222222233333333|...
13921512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			       |                |
13931512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod		    byte 1           byte 2
13941512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
13951512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod     00000000: (byte >> 8) & mask
13961512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod     11111111: (byte >> 0) & mask
13971512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod     ....
13981512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
13991512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod     mask = 0x00FF                                    */
14001512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
14011512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL HB_Error
14021512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_HB_OPEN_Get_Device( HB_Device* d,
14031512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod		      HB_UShort    size,
14041512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod		      HB_Short*    value )
14051512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
14061512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort  byte, bits, mask, s;
14071512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
14081512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( d && d->DeltaValue && size >= d->StartSize && size <= d->EndSize )
14091512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
14101512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    HB_UShort f = d->DeltaFormat;
14111512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    s    = size - d->StartSize;
14121512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    byte = d->DeltaValue[s >> ( 4 - f )];
14131512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    bits = byte >> ( 16 - ( ( s % ( 1 << ( 4 - f ) ) + 1 ) << f ) );
14141512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    mask = 0xFFFF >> ( 16 - ( 1 << f ) );
14151512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
14161512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    *value = (HB_Short)( bits & mask );
14171512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
14181512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    /* conversion to a signed value */
14191512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
14201512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    if ( *value >= ( ( mask + 1 ) >> 1 ) )
14211512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      *value -= mask + 1;
14221512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
14231512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return HB_Err_Ok;
14241512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
14251512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  else
14261512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
14271512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    *value = 0;
14281512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return HB_Err_Not_Covered;
14291512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
14301512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
14311512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
14321512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
14331512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/* END */
1434