/*
 * Copyright (C) 1998-2004  David Turner and Werner Lemberg
 * Copyright (C) 2006  Behdad Esfahbod
 *
 * This is part of HarfBuzz, an OpenType Layout engine library.
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 *
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 */

#include "harfbuzz-impl.h"
#include "harfbuzz-gdef-private.h"
#include "harfbuzz-open-private.h"

static HB_Error  Load_AttachList( HB_AttachList*  al,
				  HB_Stream        stream );
static HB_Error  Load_LigCaretList( HB_LigCaretList*  lcl,
				    HB_Stream          stream );

static void  Free_AttachList( HB_AttachList*  al);
static void  Free_LigCaretList( HB_LigCaretList*  lcl);

static void  Free_NewGlyphClasses( HB_GDEFHeader*  gdef);



/* GDEF glyph classes */

#define UNCLASSIFIED_GLYPH  0
#define SIMPLE_GLYPH        1
#define LIGATURE_GLYPH      2
#define MARK_GLYPH          3
#define COMPONENT_GLYPH     4






HB_Error  HB_New_GDEF_Table( HB_GDEFHeader** retptr )
{
  HB_Error         error;

  HB_GDEFHeader*  gdef;

  if ( !retptr )
    return ERR(HB_Err_Invalid_Argument);

  if ( ALLOC( gdef, sizeof( *gdef ) ) )
    return error;

  gdef->GlyphClassDef.loaded = FALSE;
  gdef->AttachList.loaded = FALSE;
  gdef->LigCaretList.loaded = FALSE;
  gdef->MarkAttachClassDef_offset = 0;
  gdef->MarkAttachClassDef.loaded = FALSE;

  gdef->LastGlyph = 0;
  gdef->NewGlyphClasses = NULL;

  *retptr = gdef;

  return HB_Err_Ok;
}


HB_Error  HB_Load_GDEF_Table( HB_Stream stream, 
			      HB_GDEFHeader** retptr )
{
  HB_Error         error;
  HB_UInt         cur_offset, new_offset, base_offset;

  HB_GDEFHeader*  gdef;


  if ( !retptr )
    return ERR(HB_Err_Invalid_Argument);

  if ( GOTO_Table( TTAG_GDEF ) )
    return error;

  if (( error = HB_New_GDEF_Table ( &gdef ) ))
    return error;

  base_offset = FILE_Pos();

  /* skip version */

  if ( FILE_Seek( base_offset + 4L ) ||
       ACCESS_Frame( 2L ) )
    goto Fail0;

  new_offset = GET_UShort();

  FORGET_Frame();

  /* all GDEF subtables are optional */

  if ( new_offset )
  {
    new_offset += base_offset;

    /* only classes 1-4 are allowed here */

    cur_offset = FILE_Pos();
    if ( FILE_Seek( new_offset ) ||
	 ( error = _HB_OPEN_Load_ClassDefinition( &gdef->GlyphClassDef, 5,
					 stream ) ) != HB_Err_Ok )
      goto Fail0;
    (void)FILE_Seek( cur_offset );
  }

  if ( ACCESS_Frame( 2L ) )
    goto Fail1;

  new_offset = GET_UShort();

  FORGET_Frame();

  if ( new_offset )
  {
    new_offset += base_offset;

    cur_offset = FILE_Pos();
    if ( FILE_Seek( new_offset ) ||
	 ( error = Load_AttachList( &gdef->AttachList,
				    stream ) ) != HB_Err_Ok )
      goto Fail1;
    (void)FILE_Seek( cur_offset );
  }

  if ( ACCESS_Frame( 2L ) )
    goto Fail2;

  new_offset = GET_UShort();

  FORGET_Frame();

  if ( new_offset )
  {
    new_offset += base_offset;

    cur_offset = FILE_Pos();
    if ( FILE_Seek( new_offset ) ||
	 ( error = Load_LigCaretList( &gdef->LigCaretList,
				      stream ) ) != HB_Err_Ok )
      goto Fail2;
    (void)FILE_Seek( cur_offset );
  }

  /* OpenType 1.2 has introduced the `MarkAttachClassDef' field.  We
     first have to scan the LookupFlag values to find out whether we
     must load it or not.  Here we only store the offset of the table. */

  if ( ACCESS_Frame( 2L ) )
    goto Fail3;

  new_offset = GET_UShort();

  FORGET_Frame();

  if ( new_offset )
    gdef->MarkAttachClassDef_offset = new_offset + base_offset;
  else
    gdef->MarkAttachClassDef_offset = 0;

  *retptr = gdef;

  return HB_Err_Ok;

Fail3:
  Free_LigCaretList( &gdef->LigCaretList );
  
Fail2:
  Free_AttachList( &gdef->AttachList );

Fail1:
  _HB_OPEN_Free_ClassDefinition( &gdef->GlyphClassDef );

Fail0:
  FREE( gdef );

  return error;
}


HB_Error  HB_Done_GDEF_Table ( HB_GDEFHeader* gdef ) 
{  
  Free_LigCaretList( &gdef->LigCaretList );
  Free_AttachList( &gdef->AttachList );
  _HB_OPEN_Free_ClassDefinition( &gdef->GlyphClassDef );
  _HB_OPEN_Free_ClassDefinition( &gdef->MarkAttachClassDef );
  
  Free_NewGlyphClasses( gdef );

  FREE( gdef );

  return HB_Err_Ok;
}




/*******************************
 * AttachList related functions
 *******************************/


/* AttachPoint */

static HB_Error  Load_AttachPoint( HB_AttachPoint*  ap,
				   HB_Stream         stream )
{
  HB_Error  error;

  HB_UShort   n, count;
  HB_UShort*  pi;


  if ( ACCESS_Frame( 2L ) )
    return error;

  count = ap->PointCount = GET_UShort();

  FORGET_Frame();

  ap->PointIndex = NULL;

  if ( count )
  {
    if ( ALLOC_ARRAY( ap->PointIndex, count, HB_UShort ) )
      return error;

    pi = ap->PointIndex;

    if ( ACCESS_Frame( count * 2L ) )
    {
      FREE( pi );
      return error;
    }

    for ( n = 0; n < count; n++ )
      pi[n] = GET_UShort();

    FORGET_Frame();
  }

  return HB_Err_Ok;
}


static void  Free_AttachPoint( HB_AttachPoint*  ap )
{
  FREE( ap->PointIndex );
}


/* AttachList */

static HB_Error  Load_AttachList( HB_AttachList*  al,
				  HB_Stream        stream )
{
  HB_Error  error;

  HB_UShort         n, m, count;
  HB_UInt          cur_offset, new_offset, base_offset;

  HB_AttachPoint*  ap;


  base_offset = FILE_Pos();

  if ( ACCESS_Frame( 2L ) )
    return error;

  new_offset = GET_UShort() + base_offset;

  FORGET_Frame();

  cur_offset = FILE_Pos();
  if ( FILE_Seek( new_offset ) ||
       ( error = _HB_OPEN_Load_Coverage( &al->Coverage, stream ) ) != HB_Err_Ok )
    return error;
  (void)FILE_Seek( cur_offset );

  if ( ACCESS_Frame( 2L ) )
    goto Fail2;

  count = al->GlyphCount = GET_UShort();

  FORGET_Frame();

  al->AttachPoint = NULL;

  if ( ALLOC_ARRAY( al->AttachPoint, count, HB_AttachPoint ) )
    goto Fail2;

  ap = al->AttachPoint;

  for ( n = 0; n < count; n++ )
  {
    if ( ACCESS_Frame( 2L ) )
      goto Fail1;

    new_offset = GET_UShort() + base_offset;

    FORGET_Frame();

    cur_offset = FILE_Pos();
    if ( FILE_Seek( new_offset ) ||
	 ( error = Load_AttachPoint( &ap[n], stream ) ) != HB_Err_Ok )
      goto Fail1;
    (void)FILE_Seek( cur_offset );
  }

  al->loaded = TRUE;

  return HB_Err_Ok;

Fail1:
  for ( m = 0; m < n; m++ )
    Free_AttachPoint( &ap[m] );

  FREE( ap );

Fail2:
  _HB_OPEN_Free_Coverage( &al->Coverage );
  return error;
}


static void  Free_AttachList( HB_AttachList*  al)
{
  HB_UShort         n, count;

  HB_AttachPoint*  ap;


  if ( !al->loaded )
    return;

  if ( al->AttachPoint )
  {
    count = al->GlyphCount;
    ap    = al->AttachPoint;

    for ( n = 0; n < count; n++ )
      Free_AttachPoint( &ap[n] );

    FREE( ap );
  }

  _HB_OPEN_Free_Coverage( &al->Coverage );
}



/*********************************
 * LigCaretList related functions
 *********************************/


/* CaretValueFormat1 */
/* CaretValueFormat2 */
/* CaretValueFormat3 */
/* CaretValueFormat4 */

static HB_Error  Load_CaretValue( HB_CaretValue*  cv,
				  HB_Stream        stream )
{
  HB_Error  error;

  HB_UInt cur_offset, new_offset, base_offset;


  base_offset = FILE_Pos();

  if ( ACCESS_Frame( 2L ) )
    return error;

  cv->CaretValueFormat = GET_UShort();

  FORGET_Frame();

  switch ( cv->CaretValueFormat )
  {
  case 1:
    if ( ACCESS_Frame( 2L ) )
      return error;

    cv->cvf.cvf1.Coordinate = GET_Short();

    FORGET_Frame();

    break;

  case 2:
    if ( ACCESS_Frame( 2L ) )
      return error;

    cv->cvf.cvf2.CaretValuePoint = GET_UShort();

    FORGET_Frame();

    break;

  case 3:
    if ( ACCESS_Frame( 4L ) )
      return error;

    cv->cvf.cvf3.Coordinate = GET_Short();

    new_offset = GET_UShort() + base_offset;

    FORGET_Frame();

    cur_offset = FILE_Pos();
    if ( FILE_Seek( new_offset ) ||
	 ( error = _HB_OPEN_Load_Device( &cv->cvf.cvf3.Device,
				stream ) ) != HB_Err_Ok )
      return error;
    (void)FILE_Seek( cur_offset );

    break;

  case 4:
    if ( ACCESS_Frame( 2L ) )
      return error;

    cv->cvf.cvf4.IdCaretValue = GET_UShort();

    FORGET_Frame();
    break;

  default:
    return ERR(HB_Err_Invalid_SubTable_Format);
  }

  return HB_Err_Ok;
}


static void  Free_CaretValue( HB_CaretValue*  cv)
{
  if ( cv->CaretValueFormat == 3 )
    _HB_OPEN_Free_Device( &cv->cvf.cvf3.Device );
}


/* LigGlyph */

static HB_Error  Load_LigGlyph( HB_LigGlyph*  lg,
				HB_Stream      stream )
{
  HB_Error  error;

  HB_UShort        n, m, count;
  HB_UInt         cur_offset, new_offset, base_offset;

  HB_CaretValue*  cv;


  base_offset = FILE_Pos();

  if ( ACCESS_Frame( 2L ) )
    return error;

  count = lg->CaretCount = GET_UShort();

  FORGET_Frame();

  lg->CaretValue = NULL;

  if ( ALLOC_ARRAY( lg->CaretValue, count, HB_CaretValue ) )
    return error;

  cv = lg->CaretValue;

  for ( n = 0; n < count; n++ )
  {
    if ( ACCESS_Frame( 2L ) )
      goto Fail;

    new_offset = GET_UShort() + base_offset;

    FORGET_Frame();

    cur_offset = FILE_Pos();
    if ( FILE_Seek( new_offset ) ||
	 ( error = Load_CaretValue( &cv[n], stream ) ) != HB_Err_Ok )
      goto Fail;
    (void)FILE_Seek( cur_offset );
  }

  return HB_Err_Ok;

Fail:
  for ( m = 0; m < n; m++ )
    Free_CaretValue( &cv[m] );

  FREE( cv );
  return error;
}


static void  Free_LigGlyph( HB_LigGlyph*  lg)
{
  HB_UShort        n, count;

  HB_CaretValue*  cv;


  if ( lg->CaretValue )
  {
    count = lg->CaretCount;
    cv    = lg->CaretValue;

    for ( n = 0; n < count; n++ )
      Free_CaretValue( &cv[n] );

    FREE( cv );
  }
}


/* LigCaretList */

static HB_Error  Load_LigCaretList( HB_LigCaretList*  lcl,
				    HB_Stream          stream )
{
  HB_Error  error;

  HB_UShort      m, n, count;
  HB_UInt       cur_offset, new_offset, base_offset;

  HB_LigGlyph*  lg;


  base_offset = FILE_Pos();

  if ( ACCESS_Frame( 2L ) )
    return error;

  new_offset = GET_UShort() + base_offset;

  FORGET_Frame();

  cur_offset = FILE_Pos();
  if ( FILE_Seek( new_offset ) ||
       ( error = _HB_OPEN_Load_Coverage( &lcl->Coverage, stream ) ) != HB_Err_Ok )
    return error;
  (void)FILE_Seek( cur_offset );

  if ( ACCESS_Frame( 2L ) )
    goto Fail2;

  count = lcl->LigGlyphCount = GET_UShort();

  FORGET_Frame();

  lcl->LigGlyph = NULL;

  if ( ALLOC_ARRAY( lcl->LigGlyph, count, HB_LigGlyph ) )
    goto Fail2;

  lg = lcl->LigGlyph;

  for ( n = 0; n < count; n++ )
  {
    if ( ACCESS_Frame( 2L ) )
      goto Fail1;

    new_offset = GET_UShort() + base_offset;

    FORGET_Frame();

    cur_offset = FILE_Pos();
    if ( FILE_Seek( new_offset ) ||
	 ( error = Load_LigGlyph( &lg[n], stream ) ) != HB_Err_Ok )
      goto Fail1;
    (void)FILE_Seek( cur_offset );
  }

  lcl->loaded = TRUE;

  return HB_Err_Ok;

Fail1:
  for ( m = 0; m < n; m++ )
    Free_LigGlyph( &lg[m] );

  FREE( lg );

Fail2:
  _HB_OPEN_Free_Coverage( &lcl->Coverage );
  return error;
}


static void  Free_LigCaretList( HB_LigCaretList*  lcl )
{
  HB_UShort      n, count;

  HB_LigGlyph*  lg;


  if ( !lcl->loaded )
    return;

  if ( lcl->LigGlyph )
  {
    count = lcl->LigGlyphCount;
    lg    = lcl->LigGlyph;

    for ( n = 0; n < count; n++ )
      Free_LigGlyph( &lg[n] );

    FREE( lg );
  }

  _HB_OPEN_Free_Coverage( &lcl->Coverage );
}



/***********
 * GDEF API
 ***********/


static HB_UShort  Get_New_Class( HB_GDEFHeader*  gdef,
				 HB_UShort        glyphID,
				 HB_UShort        index )
{
  HB_UShort              glyph_index, array_index, count;
  HB_UShort              byte, bits;
  
  HB_ClassRangeRecord*  gcrr;
  HB_UShort**            ngc;


  if ( glyphID >= gdef->LastGlyph )
    return 0;

  count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount;
  gcrr = gdef->GlyphClassDef.cd.cd2.ClassRangeRecord;
  ngc  = gdef->NewGlyphClasses;

  if ( index < count && glyphID < gcrr[index].Start )
  {
    array_index = index;
    if ( index == 0 )
      glyph_index = glyphID;
    else
      glyph_index = glyphID - gcrr[index - 1].End - 1;
  }
  else
  {
    array_index = index + 1;
    glyph_index = glyphID - gcrr[index].End - 1;
  }

  byte = ngc[array_index][glyph_index / 4];
  bits = byte >> ( 16 - ( glyph_index % 4 + 1 ) * 4 );

  return bits & 0x000F;
}



HB_Error  HB_GDEF_Get_Glyph_Property( HB_GDEFHeader*  gdef,
				      HB_UShort        glyphID,
				      HB_UShort*       property )
{
  HB_UShort class = 0, index = 0; /* shut compiler up */

  HB_Error  error;


  if ( !gdef || !property )
    return ERR(HB_Err_Invalid_Argument);

  /* first, we check for mark attach classes */

  if ( gdef->MarkAttachClassDef.loaded )
  {
    error = _HB_OPEN_Get_Class( &gdef->MarkAttachClassDef, glyphID, &class, &index );
    if ( error && error != HB_Err_Not_Covered )
      return error;
    if ( !error )
    {
      *property = class << 8;
      return HB_Err_Ok;
    }
  }

  error = _HB_OPEN_Get_Class( &gdef->GlyphClassDef, glyphID, &class, &index );
  if ( error && error != HB_Err_Not_Covered )
    return error;

  /* if we have a constructed class table, check whether additional
     values have been assigned                                      */

  if ( error == HB_Err_Not_Covered && gdef->NewGlyphClasses )
    class = Get_New_Class( gdef, glyphID, index );

  switch ( class )
  {
  default:
  case UNCLASSIFIED_GLYPH:
    *property = 0;
    break;

  case SIMPLE_GLYPH:
    *property = HB_GDEF_BASE_GLYPH;
    break;

  case LIGATURE_GLYPH:
    *property = HB_GDEF_LIGATURE;
    break;

  case MARK_GLYPH:
    *property = HB_GDEF_MARK;
    break;

  case COMPONENT_GLYPH:
    *property = HB_GDEF_COMPONENT;
    break;
  }

  return HB_Err_Ok;
}


static HB_Error  Make_ClassRange( HB_ClassDefinition*  cd,
				  HB_UShort             start,
				  HB_UShort             end,
				  HB_UShort             class )
{
  HB_Error               error;
  HB_UShort              index;

  HB_ClassDefFormat2*   cdf2;
  HB_ClassRangeRecord*  crr;


  cdf2 = &cd->cd.cd2;

  if ( REALLOC_ARRAY( cdf2->ClassRangeRecord,
		      cdf2->ClassRangeCount + 1 ,
		      HB_ClassRangeRecord ) )
    return error;

  cdf2->ClassRangeCount++;

  crr   = cdf2->ClassRangeRecord;
  index = cdf2->ClassRangeCount - 1;

  crr[index].Start = start;
  crr[index].End   = end;
  crr[index].Class = class;

  return HB_Err_Ok;
}



HB_Error  HB_GDEF_Build_ClassDefinition( HB_GDEFHeader*  gdef,
					 HB_UShort        num_glyphs,
					 HB_UShort        glyph_count,
					 HB_UShort*       glyph_array,
					 HB_UShort*       class_array )
{
  HB_UShort              start, curr_glyph, curr_class;
  HB_UShort              n, m, count;
  HB_Error               error;

  HB_ClassDefinition*   gcd;
  HB_ClassRangeRecord*  gcrr;
  HB_UShort**            ngc;


  if ( !gdef || !glyph_array || !class_array )
    return ERR(HB_Err_Invalid_Argument);

  gcd = &gdef->GlyphClassDef;

  /* We build a format 2 table */

  gcd->ClassFormat = 2;

  gcd->cd.cd2.ClassRangeCount  = 0;
  gcd->cd.cd2.ClassRangeRecord = NULL;

  start      = glyph_array[0];
  curr_class = class_array[0];
  curr_glyph = start;

  if ( curr_class >= 5 )
  {
    error = ERR(HB_Err_Invalid_Argument);
    goto Fail4;
  }

  glyph_count--;

  for ( n = 0; n < glyph_count + 1; n++ )
  {
    if ( curr_glyph == glyph_array[n] && curr_class == class_array[n] )
    {
      if ( n == glyph_count )
      {
	if ( ( error = Make_ClassRange( gcd, start,
					curr_glyph,
					curr_class) ) != HB_Err_Ok )
	  goto Fail3;
      }
      else
      {
	if ( curr_glyph == 0xFFFF )
	{
	  error = ERR(HB_Err_Invalid_Argument);
	  goto Fail3;
	}
	else
	  curr_glyph++;
      }
    }
    else
    {
      if ( ( error = Make_ClassRange( gcd, start,
				      curr_glyph - 1,
				      curr_class) ) != HB_Err_Ok )
	goto Fail3;

      if ( curr_glyph > glyph_array[n] )
      {
	error = ERR(HB_Err_Invalid_Argument);
	goto Fail3;
      }

      start      = glyph_array[n];
      curr_class = class_array[n];
      curr_glyph = start;

      if ( curr_class >= 5 )
      {
	error = ERR(HB_Err_Invalid_Argument);
	goto Fail3;
      }

      if ( n == glyph_count )
      {
	if ( ( error = Make_ClassRange( gcd, start,
					curr_glyph,
					curr_class) ) != HB_Err_Ok )
	  goto Fail3;
      }
      else
      {
	if ( curr_glyph == 0xFFFF )
	{
	  error = ERR(HB_Err_Invalid_Argument);
	  goto Fail3;
	}
	else
	  curr_glyph++;
      }
    }
  }

  /* now prepare the arrays for class values assigned during the lookup
     process                                                            */

  if ( ALLOC_ARRAY( gdef->NewGlyphClasses,
		    gcd->cd.cd2.ClassRangeCount + 1, HB_UShort* ) )
    goto Fail3;

  count = gcd->cd.cd2.ClassRangeCount;
  gcrr  = gcd->cd.cd2.ClassRangeRecord;
  ngc   = gdef->NewGlyphClasses;

  /* We allocate arrays for all glyphs not covered by the class range
     records.  Each element holds four class values.                  */

  if ( count > 0 )
  {
      if ( gcrr[0].Start )
      {
	if ( ALLOC_ARRAY( ngc[0], ( gcrr[0].Start + 3 ) / 4, HB_UShort ) )
	  goto Fail2;
      }

      for ( n = 1; n < count; n++ )
      {
	if ( gcrr[n].Start - gcrr[n - 1].End > 1 )
	  if ( ALLOC_ARRAY( ngc[n],
			    ( gcrr[n].Start - gcrr[n - 1].End + 2 ) / 4,
			    HB_UShort ) )
	    goto Fail1;
      }

      if ( gcrr[count - 1].End != num_glyphs - 1 )
      {
	if ( ALLOC_ARRAY( ngc[count],
			  ( num_glyphs - gcrr[count - 1].End + 2 ) / 4,
			  HB_UShort ) )
	    goto Fail1;
      }
  }
  else if ( num_glyphs > 0 )
  {
      if ( ALLOC_ARRAY( ngc[count],
			( num_glyphs + 3 ) / 4,
			HB_UShort ) )
	  goto Fail2;
  }
      
  gdef->LastGlyph = num_glyphs - 1;

  gdef->MarkAttachClassDef_offset = 0L;
  gdef->MarkAttachClassDef.loaded = FALSE;

  gcd->loaded = TRUE;

  return HB_Err_Ok;

Fail1:
  for ( m = 0; m < n; m++ )
    FREE( ngc[m] );

Fail2:
  FREE( gdef->NewGlyphClasses );

Fail3:
  FREE( gcd->cd.cd2.ClassRangeRecord );

Fail4:
  return error;
}


static void  Free_NewGlyphClasses( HB_GDEFHeader*  gdef )
{
  HB_UShort**  ngc;
  HB_UShort    n, count;


  if ( gdef->NewGlyphClasses )
  {
    count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount + 1;
    ngc   = gdef->NewGlyphClasses;

    for ( n = 0; n < count; n++ )
      FREE( ngc[n] );

    FREE( ngc );
  }
}


HB_INTERNAL HB_Error
_HB_GDEF_Add_Glyph_Property( HB_GDEFHeader* gdef,
			      HB_UShort        glyphID,
			      HB_UShort        property )
{
  HB_Error               error;
  HB_UShort              class, new_class, index = 0; /* shut compiler up */
  HB_UShort              byte, bits, mask;
  HB_UShort              array_index, glyph_index, count;

  HB_ClassRangeRecord*  gcrr;
  HB_UShort**            ngc;


  error = _HB_OPEN_Get_Class( &gdef->GlyphClassDef, glyphID, &class, &index );
  if ( error && error != HB_Err_Not_Covered )
    return error;

  /* we don't accept glyphs covered in `GlyphClassDef' */

  if ( !error )
    return HB_Err_Not_Covered;

  switch ( property )
  {
  case 0:
    new_class = UNCLASSIFIED_GLYPH;
    break;

  case HB_GDEF_BASE_GLYPH:
    new_class = SIMPLE_GLYPH;
    break;

  case HB_GDEF_LIGATURE:
    new_class = LIGATURE_GLYPH;
    break;

  case HB_GDEF_MARK:
    new_class = MARK_GLYPH;
    break;

  case HB_GDEF_COMPONENT:
    new_class = COMPONENT_GLYPH;
    break;

  default:
    return ERR(HB_Err_Invalid_Argument);
  }

  count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount;
  gcrr = gdef->GlyphClassDef.cd.cd2.ClassRangeRecord;
  ngc  = gdef->NewGlyphClasses;

  if ( index < count && glyphID < gcrr[index].Start )
  {
    array_index = index;
    if ( index == 0 )
      glyph_index = glyphID;
    else
      glyph_index = glyphID - gcrr[index - 1].End - 1;
  }
  else
  {
    array_index = index + 1;
    glyph_index = glyphID - gcrr[index].End - 1;
  }

  byte  = ngc[array_index][glyph_index / 4];
  bits  = byte >> ( 16 - ( glyph_index % 4 + 1 ) * 4 );
  class = bits & 0x000F;

  /* we don't overwrite existing entries */

  if ( !class )
  {
    bits = new_class << ( 16 - ( glyph_index % 4 + 1 ) * 4 );
    mask = ~( 0x000F << ( 16 - ( glyph_index % 4 + 1 ) * 4 ) );

    ngc[array_index][glyph_index / 4] &= mask;
    ngc[array_index][glyph_index / 4] |= bits;
  }

  return HB_Err_Ok;
}


HB_INTERNAL HB_Error
_HB_GDEF_Check_Property( HB_GDEFHeader* gdef,
			  HB_GlyphItem    gitem,
			  HB_UShort        flags,
			  HB_UShort*       property )
{
  HB_Error  error;

  if ( gdef )
  {
    HB_UShort basic_glyph_class;
    HB_UShort desired_attachment_class;

    if ( gitem->gproperties == HB_GLYPH_PROPERTIES_UNKNOWN )
    {
      error = HB_GDEF_Get_Glyph_Property( gdef, gitem->gindex, &gitem->gproperties );
      if ( error )
	return error;
    }

    *property = gitem->gproperties;

    /* If the glyph was found in the MarkAttachmentClass table,
     * then that class value is the high byte of the result,
     * otherwise the low byte contains the basic type of the glyph
     * as defined by the GlyphClassDef table.
     */
    if ( *property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS  )
      basic_glyph_class = HB_GDEF_MARK;
    else
      basic_glyph_class = *property;

    /* Return Not_Covered, if, for example, basic_glyph_class
     * is HB_GDEF_LIGATURE and LookFlags includes HB_LOOKUP_FLAG_IGNORE_LIGATURES
     */
    if ( flags & basic_glyph_class )
      return HB_Err_Not_Covered;
    
    /* The high byte of LookupFlags has the meaning
     * "ignore marks of attachment type different than
     * the attachment type specified."
     */
    desired_attachment_class = flags & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS;
    if ( desired_attachment_class )
    {
      if ( basic_glyph_class == HB_GDEF_MARK &&
	   *property != desired_attachment_class )
	return HB_Err_Not_Covered;
    }
  } else {
      *property = 0;
  }

  return HB_Err_Ok;
}

HB_INTERNAL HB_Error
_HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( HB_GDEFHeader* gdef,
						  HB_Stream      stream,
						  HB_Lookup*     lo,
						  HB_UShort      num_lookups)
{
  HB_Error   error = HB_Err_Ok;
  HB_UShort  i;

  /* We now check the LookupFlags for values larger than 0xFF to find
     out whether we need to load the `MarkAttachClassDef' field of the
     GDEF table -- this hack is necessary for OpenType 1.2 tables since
     the version field of the GDEF table hasn't been incremented.

     For constructed GDEF tables, we only load it if
     `MarkAttachClassDef_offset' is not zero (nevertheless, a build of
     a constructed mark attach table is not supported currently).       */

  if ( gdef &&
       gdef->MarkAttachClassDef_offset && !gdef->MarkAttachClassDef.loaded )
  {
    for ( i = 0; i < num_lookups; i++ )
    {

      if ( lo[i].LookupFlag & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
      {
	if ( FILE_Seek( gdef->MarkAttachClassDef_offset ) ||
	     ( error = _HB_OPEN_Load_ClassDefinition( &gdef->MarkAttachClassDef,
					     256, stream ) ) != HB_Err_Ok )
	  goto Done;

	break;
      }
    }
  }

Done:
  return error;
}

/* END */
