⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 harfbuzz-gsub.c

📁 GTK+-2.0源码之pango-1.15.6.tar.gz
💻 C
📖 第 1 页 / 共 5 页
字号:
/******************************************************************* * *  Copyright 1996-2000 by *  David Turner, Robert Wilhelm, and Werner Lemberg. * *  Copyright 2006  Behdad Esfahbod * *  This is part of HarfBuzz, an OpenType Layout engine library. * *  See the file name COPYING for licensing information. * ******************************************************************/#include "harfbuzz-impl.h"#include "harfbuzz-gsub-private.h"#include "harfbuzz-open-private.h"#include "harfbuzz-gdef-private.h"static FT_Error  GSUB_Do_Glyph_Lookup( HB_GSUBHeader*   gsub,				       FT_UShort         lookup_index,				       HB_Buffer        buffer,				       FT_UShort         context_length,				       int               nesting_level );/********************** * Auxiliary functions **********************/FT_Error  HB_Load_GSUB_Table( FT_Face          face,			      HB_GSUBHeader** retptr,			      HB_GDEFHeader*  gdef ){  FT_Stream        stream = face->stream;  FT_Memory        memory = face->memory;  FT_Error         error;  FT_ULong         cur_offset, new_offset, base_offset;  FT_UShort        i, num_lookups;  HB_GSUBHeader*  gsub;  HB_Lookup*      lo;  if ( !retptr )    return FT_Err_Invalid_Argument;  if (( error = _hb_ftglue_face_goto_table( face, TTAG_GSUB, stream ) ))    return error;  base_offset = FILE_Pos();  if ( ALLOC ( gsub, sizeof( *gsub ) ) )    return error;  gsub->memory = memory;  /* skip version */  if ( FILE_Seek( base_offset + 4L ) ||       ACCESS_Frame( 2L ) )    goto Fail4;  new_offset = GET_UShort() + base_offset;  FORGET_Frame();  cur_offset = FILE_Pos();  if ( FILE_Seek( new_offset ) ||       ( error = _HB_OPEN_Load_ScriptList( &gsub->ScriptList,				  stream ) ) != FT_Err_Ok )    goto Fail4;  (void)FILE_Seek( cur_offset );  if ( ACCESS_Frame( 2L ) )    goto Fail3;  new_offset = GET_UShort() + base_offset;  FORGET_Frame();  cur_offset = FILE_Pos();  if ( FILE_Seek( new_offset ) ||       ( error = _HB_OPEN_Load_FeatureList( &gsub->FeatureList,				   stream ) ) != FT_Err_Ok )    goto Fail3;  (void)FILE_Seek( cur_offset );  if ( ACCESS_Frame( 2L ) )    goto Fail2;  new_offset = GET_UShort() + base_offset;  FORGET_Frame();  cur_offset = FILE_Pos();  if ( FILE_Seek( new_offset ) ||       ( error = _HB_OPEN_Load_LookupList( &gsub->LookupList,				  stream, HB_Type_GSUB ) ) != FT_Err_Ok )    goto Fail2;  gsub->gdef = gdef;      /* can be NULL */  /* 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 )  {    lo          = gsub->LookupList.Lookup;    num_lookups = gsub->LookupList.LookupCount;    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 ) ) != FT_Err_Ok )	  goto Fail1;	break;      }    }  }  *retptr = gsub;  return FT_Err_Ok;Fail1:  _HB_OPEN_Free_LookupList( &gsub->LookupList, HB_Type_GSUB, memory );Fail2:  _HB_OPEN_Free_FeatureList( &gsub->FeatureList, memory );Fail3:  _HB_OPEN_Free_ScriptList( &gsub->ScriptList, memory );Fail4:  FREE ( gsub );  return error;}FT_Error   HB_Done_GSUB_Table( HB_GSUBHeader* gsub ){  FT_Memory memory = gsub->memory;  _HB_OPEN_Free_LookupList( &gsub->LookupList, HB_Type_GSUB, memory );  _HB_OPEN_Free_FeatureList( &gsub->FeatureList, memory );  _HB_OPEN_Free_ScriptList( &gsub->ScriptList, memory );  FREE( gsub );  return FT_Err_Ok;}/***************************** * SubTable related functions *****************************/static FT_Error  Lookup_DefaultSubst( HB_GSUBHeader*    gsub,				      HB_GSUB_SubTable* st,				      HB_Buffer         buffer,				      FT_UShort          flags,				      FT_UShort          context_length,				      int                nesting_level ){  FT_UNUSED(gsub);  FT_UNUSED(st);  FT_UNUSED(buffer);  FT_UNUSED(flags);  FT_UNUSED(context_length);  FT_UNUSED(nesting_level);  return HB_Err_Not_Covered;}/* LookupType 1 *//* SingleSubstFormat1 *//* SingleSubstFormat2 */static FT_Error  Load_SingleSubst( HB_GSUB_SubTable* st,				   FT_Stream         stream ){  FT_Error error;  FT_Memory memory = stream->memory;  HB_SingleSubst*  ss = &st->single;  FT_UShort n, count;  FT_ULong cur_offset, new_offset, base_offset;  FT_UShort*  s;  base_offset = FILE_Pos();  if ( ACCESS_Frame( 4L ) )    return error;  ss->SubstFormat = GET_UShort();  new_offset      = GET_UShort() + base_offset;  FORGET_Frame();  cur_offset = FILE_Pos();  if ( FILE_Seek( new_offset ) ||       ( error = _HB_OPEN_Load_Coverage( &ss->Coverage, stream ) ) != FT_Err_Ok )    return error;  (void)FILE_Seek( cur_offset );  switch ( ss->SubstFormat )  {  case 1:    if ( ACCESS_Frame( 2L ) )      goto Fail2;    ss->ssf.ssf1.DeltaGlyphID = GET_UShort();    FORGET_Frame();    break;  case 2:    if ( ACCESS_Frame( 2L ) )      goto Fail2;    count = ss->ssf.ssf2.GlyphCount = GET_UShort();    FORGET_Frame();    ss->ssf.ssf2.Substitute = NULL;    if ( ALLOC_ARRAY( ss->ssf.ssf2.Substitute, count, FT_UShort ) )      goto Fail2;    s = ss->ssf.ssf2.Substitute;    if ( ACCESS_Frame( count * 2L ) )      goto Fail1;    for ( n = 0; n < count; n++ )      s[n] = GET_UShort();    FORGET_Frame();    break;  default:    return HB_Err_Invalid_GSUB_SubTable_Format;  }  return FT_Err_Ok;Fail1:  FREE( s );Fail2:  _HB_OPEN_Free_Coverage( &ss->Coverage, memory );  return error;}static void  Free_SingleSubst( HB_GSUB_SubTable* st,			       FT_Memory         memory ){  HB_SingleSubst*  ss = &st->single;  switch ( ss->SubstFormat )  {  case 1:    break;  case 2:    FREE( ss->ssf.ssf2.Substitute );    break;  }  _HB_OPEN_Free_Coverage( &ss->Coverage, memory );}static FT_Error  Lookup_SingleSubst( HB_GSUBHeader*   gsub,				     HB_GSUB_SubTable* st,				     HB_Buffer        buffer,				     FT_UShort         flags,				     FT_UShort         context_length,				     int               nesting_level ){  FT_UShort index, value, property;  FT_Error  error;  HB_SingleSubst*  ss = &st->single;  HB_GDEFHeader*   gdef = gsub->gdef;  FT_UNUSED(nesting_level);  if ( context_length != 0xFFFF && context_length < 1 )    return HB_Err_Not_Covered;  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )    return error;  error = _HB_OPEN_Coverage_Index( &ss->Coverage, IN_CURGLYPH(), &index );  if ( error )    return error;  switch ( ss->SubstFormat )  {  case 1:	  value = ( IN_CURGLYPH() + ss->ssf.ssf1.DeltaGlyphID ) & 0xFFFF;    if ( ADD_Glyph( buffer, value, 0xFFFF, 0xFFFF ) )      return error;    break;  case 2:    if ( index >= ss->ssf.ssf2.GlyphCount )      return HB_Err_Invalid_GSUB_SubTable;    value = ss->ssf.ssf2.Substitute[index];    if ( ADD_Glyph( buffer, value, 0xFFFF, 0xFFFF ) )      return error;    break;  default:    return HB_Err_Invalid_GSUB_SubTable;  }  if ( gdef && gdef->NewGlyphClasses )  {    /* we inherit the old glyph class to the substituted glyph */    error = _HB_GDEF_Add_Glyph_Property( gdef, value, property );    if ( error && error != HB_Err_Not_Covered )      return error;  }  return FT_Err_Ok;}/* LookupType 2 *//* Sequence */static FT_Error  Load_Sequence( HB_Sequence*  s,				FT_Stream      stream ){  FT_Error error;  FT_Memory memory = stream->memory;  FT_UShort n, count;  FT_UShort*  sub;  if ( ACCESS_Frame( 2L ) )    return error;  count = s->GlyphCount = GET_UShort();  FORGET_Frame();  s->Substitute = NULL;  if ( count )  {    if ( ALLOC_ARRAY( s->Substitute, count, FT_UShort ) )      return error;    sub = s->Substitute;    if ( ACCESS_Frame( count * 2L ) )    {      FREE( sub );      return error;    }    for ( n = 0; n < count; n++ )      sub[n] = GET_UShort();    FORGET_Frame();  }  return FT_Err_Ok;}static void  Free_Sequence( HB_Sequence*  s,			    FT_Memory      memory ){  FREE( s->Substitute );}/* MultipleSubstFormat1 */static FT_Error  Load_MultipleSubst( HB_GSUB_SubTable* st,				     FT_Stream         stream ){  FT_Error error;  FT_Memory memory = stream->memory;  HB_MultipleSubst*  ms = &st->multiple;  FT_UShort      n = 0, m, count;  FT_ULong       cur_offset, new_offset, base_offset;  HB_Sequence*  s;  base_offset = FILE_Pos();  if ( ACCESS_Frame( 4L ) )    return error;  ms->SubstFormat = GET_UShort();             /* should be 1 */  new_offset      = GET_UShort() + base_offset;  FORGET_Frame();  cur_offset = FILE_Pos();  if ( FILE_Seek( new_offset ) ||       ( error = _HB_OPEN_Load_Coverage( &ms->Coverage, stream ) ) != FT_Err_Ok )    return error;  (void)FILE_Seek( cur_offset );  if ( ACCESS_Frame( 2L ) )    goto Fail2;  count = ms->SequenceCount = GET_UShort();  FORGET_Frame();  ms->Sequence = NULL;  if ( ALLOC_ARRAY( ms->Sequence, count, HB_Sequence ) )    goto Fail2;  s = ms->Sequence;  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_Sequence( &s[n], stream ) ) != FT_Err_Ok )      goto Fail1;    (void)FILE_Seek( cur_offset );  }  return FT_Err_Ok;Fail1:  for ( m = 0; m < n; m++ )    Free_Sequence( &s[m], memory );  FREE( s );Fail2:  _HB_OPEN_Free_Coverage( &ms->Coverage, memory );  return error;}static void  Free_MultipleSubst( HB_GSUB_SubTable* st,				 FT_Memory         memory ){  FT_UShort      n, count;  HB_MultipleSubst*  ms = &st->multiple;  HB_Sequence*  s;  if ( ms->Sequence )  {    count = ms->SequenceCount;    s     = ms->Sequence;    for ( n = 0; n < count; n++ )      Free_Sequence( &s[n], memory );    FREE( s );  }  _HB_OPEN_Free_Coverage( &ms->Coverage, memory );}static FT_Error  Lookup_MultipleSubst( HB_GSUBHeader*    gsub,				       HB_GSUB_SubTable* st,				       HB_Buffer         buffer,				       FT_UShort          flags,				       FT_UShort          context_length,				       int                nesting_level ){  FT_Error  error;  FT_UShort index, property, n, count;  FT_UShort*s;  HB_MultipleSubst*  ms = &st->multiple;  HB_GDEFHeader*     gdef = gsub->gdef;  FT_UNUSED(nesting_level);  if ( context_length != 0xFFFF && context_length < 1 )    return HB_Err_Not_Covered;  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )    return error;  error = _HB_OPEN_Coverage_Index( &ms->Coverage, IN_CURGLYPH(), &index );  if ( error )    return error;  if ( index >= ms->SequenceCount )    return HB_Err_Invalid_GSUB_SubTable;  count = ms->Sequence[index].GlyphCount;  s     = ms->Sequence[index].Substitute;  if ( ADD_String( buffer, 1, count, s, 0xFFFF, 0xFFFF ) )    return error;  if ( gdef && gdef->NewGlyphClasses )  {    /* this is a guess only ... */    if ( property == HB_GDEF_LIGATURE )      property = HB_GDEF_BASE_GLYPH;    for ( n = 0; n < count; n++ )    {      error = _HB_GDEF_Add_Glyph_Property( gdef, s[n], property );      if ( error && error != HB_Err_Not_Covered )	return error;    }  }  return FT_Err_Ok;}/* LookupType 3 *//* AlternateSet */static FT_Error  Load_AlternateSet( HB_AlternateSet*  as,				    FT_Stream          stream ){  FT_Error error;  FT_Memory memory = stream->memory;  FT_UShort n, count;  FT_UShort*  a;  if ( ACCESS_Frame( 2L ) )    return error;  count = as->GlyphCount = GET_UShort();  FORGET_Frame();  as->Alternate = NULL;  if ( ALLOC_ARRAY( as->Alternate, count, FT_UShort ) )    return error;  a = as->Alternate;  if ( ACCESS_Frame( count * 2L ) )  {    FREE( a );    return error;  }  for ( n = 0; n < count; n++ )    a[n] = GET_UShort();  FORGET_Frame();  return FT_Err_Ok;}static void  Free_AlternateSet( HB_AlternateSet*  as,				FT_Memory          memory ){  FREE( as->Alternate );}/* AlternateSubstFormat1 */static FT_Error  Load_AlternateSubst( HB_GSUB_SubTable* st,				      FT_Stream         stream ){  FT_Error error;  FT_Memory memory = stream->memory;  HB_AlternateSubst* as = &st->alternate;  FT_UShort          n = 0, m, count;  FT_ULong           cur_offset, new_offset, base_offset;  HB_AlternateSet*  aset;  base_offset = FILE_Pos();  if ( ACCESS_Frame( 4L ) )    return error;  as->SubstFormat = GET_UShort();             /* should be 1 */  new_offset      = GET_UShort() + base_offset;  FORGET_Frame();  cur_offset = FILE_Pos();  if ( FILE_Seek( new_offset ) ||       ( error = _HB_OPEN_Load_Coverage( &as->Coverage, stream ) ) != FT_Err_Ok )    return error;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -