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

📄 harfbuzz-gpos.c

📁 GTK+-2.0源码之pango-1.15.6.tar.gz
💻 C
📖 第 1 页 / 共 5 页
字号:
  }  _HB_OPEN_Free_Coverage( &cp->Coverage, memory );}static FT_Error  Lookup_CursivePos( GPOS_Instance*    gpi,				    HB_GPOS_SubTable* st,				    HB_Buffer        buffer,				    FT_UShort         flags,				    FT_UShort         context_length,				    int               nesting_level ){  FT_UShort        index, property;  FT_Error         error;  HB_GPOSHeader*  gpos = gpi->gpos;  HB_CursivePos*  cp = &st->cursive;  HB_EntryExitRecord*  eer;  FT_Pos                entry_x, entry_y;  FT_Pos                exit_x, exit_y;  FT_UNUSED(nesting_level);  if ( context_length != 0xFFFF && context_length < 1 )  {    gpi->last = 0xFFFF;    return HB_Err_Not_Covered;  }  /* Glyphs not having the right GDEF properties will be ignored, i.e.,     gpi->last won't be reset (contrary to user defined properties). */  if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )    return error;  /* We don't handle mark glyphs here.  According to Andrei, this isn't     possible, but who knows...                                         */  if ( property == HB_GDEF_MARK )  {    gpi->last = 0xFFFF;    return HB_Err_Not_Covered;  }  error = _HB_OPEN_Coverage_Index( &cp->Coverage, IN_CURGLYPH(), &index );  if ( error )  {    gpi->last = 0xFFFF;    return error;  }  if ( index >= cp->EntryExitCount )    return HB_Err_Invalid_GPOS_SubTable;  eer = &cp->EntryExitRecord[index];  /* Now comes the messiest part of the whole OpenType     specification.  At first glance, cursive connections seem easy     to understand, but there are pitfalls!  The reason is that     the specs don't mention how to compute the advance values     resp. glyph offsets.  I was told it would be an omission, to     be fixed in the next OpenType version...  Again many thanks to     Andrei Burago <andreib@microsoft.com> for clarifications.     Consider the following example:		      |  xadv1    |		       +---------+		       |         |		 +-----+--+ 1    |		 |     | .|      |		 |    0+--+------+		 |   2    |		 |        |		0+--------+		|  xadv2   |       glyph1: advance width = 12	       anchor point = (3,1)       glyph2: advance width = 11	       anchor point = (9,4)       LSB is 1 for both glyphs (so the boxes drawn above are glyph       bboxes).  Writing direction is R2L; `0' denotes the glyph's       coordinate origin.     Now the surprising part: The advance width of the *left* glyph     (resp. of the *bottom* glyph) will be modified, no matter     whether the writing direction is L2R or R2L (resp. T2B or     B2T)!  This assymetry is caused by the fact that the glyph's     coordinate origin is always the lower left corner for all     writing directions.     Continuing the above example, we can compute the new     (horizontal) advance width of glyph2 as       9 - 3 = 6  ,     and the new vertical offset of glyph2 as       1 - 4 = -3  .     Vertical writing direction is far more complicated:     a) Assuming that we recompute the advance height of the lower glyph:				  --		       +---------+	      --       |         |		 +-----+--+ 1    | yadv1		 |     | .|      |	   yadv2 |    0+--+------+        -- BSB1  --		 |   2    |       --      --        y_offset		 |        |   BSB2 --      0+--------+                        --	--    --       glyph1: advance height = 6	       anchor point = (3,1)       glyph2: advance height = 7	       anchor point = (9,4)       TSB is 1 for both glyphs; writing direction is T2B.	 BSB1     = yadv1 - (TSB1 + ymax1)	 BSB2     = yadv2 - (TSB2 + ymax2)	 y_offset = y2 - y1       vertical advance width of glyph2	 = y_offset + BSB2 - BSB1	 = (y2 - y1) + (yadv2 - (TSB2 + ymax2)) - (yadv1 - (TSB1 + ymax1))	 = y2 - y1 + yadv2 - TSB2 - ymax2 - (yadv1 - TSB1 - ymax1)	 = y2 - y1 + yadv2 - TSB2 - ymax2 - yadv1 + TSB1 + ymax1     b) Assuming that we recompute the advance height of the upper glyph:				  --      --		       +---------+        -- TSB1	--    --       |         |   TSB2 --       +-----+--+ 1    | yadv1   ymax1		 |     | .|      |	   yadv2 |    0+--+------+        --       --    ymax2        |   2    |       --                y_offset		 |        |	--      0+--------+                        --	      --       glyph1: advance height = 6	       anchor point = (3,1)       glyph2: advance height = 7	       anchor point = (9,4)       TSB is 1 for both glyphs; writing direction is T2B.       y_offset = y2 - y1       vertical advance width of glyph2	 = TSB1 + ymax1 + y_offset - (TSB2 + ymax2)	 = TSB1 + ymax1 + y2 - y1 - TSB2 - ymax2     Comparing a) with b) shows that b) is easier to compute.  I'll wait     for a reply from Andrei to see what should really be implemented...     Since horizontal advance widths or vertical advance heights     can be used alone but not together, no ambiguity occurs.        */  if ( gpi->last == 0xFFFF )    goto end;  /* Get_Anchor() returns HB_Err_Not_Covered if there is no anchor     table.                                                         */  error = Get_Anchor( gpi, &eer->EntryAnchor, IN_CURGLYPH(),		      &entry_x, &entry_y );  if ( error == HB_Err_Not_Covered )    goto end;  if ( error )    return error;  if ( gpi->r2l )  {    POSITION( buffer->in_pos )->x_advance   = entry_x - gpi->anchor_x;    POSITION( buffer->in_pos )->new_advance = TRUE;  }  else  {    POSITION( gpi->last )->x_advance   = gpi->anchor_x - entry_x;    POSITION( gpi->last )->new_advance = TRUE;  }  if ( flags & HB_LOOKUP_FLAG_RIGHT_TO_LEFT )  {    POSITION( gpi->last )->cursive_chain = gpi->last - buffer->in_pos;    POSITION( gpi->last )->y_pos = entry_y - gpi->anchor_y;  }  else  {    POSITION( buffer->in_pos )->cursive_chain = buffer->in_pos - gpi->last;    POSITION( buffer->in_pos )->y_pos = gpi->anchor_y - entry_y;  }end:  error = Get_Anchor( gpi, &eer->ExitAnchor, IN_CURGLYPH(),		      &exit_x, &exit_y );  if ( error == HB_Err_Not_Covered )    gpi->last = 0xFFFF;  else  {    gpi->last     = buffer->in_pos;    gpi->anchor_x = exit_x;    gpi->anchor_y = exit_y;  }  if ( error )    return error;  (buffer->in_pos)++;  return FT_Err_Ok;}/* LookupType 4 *//* BaseArray */static FT_Error  Load_BaseArray( HB_BaseArray*  ba,				 FT_UShort       num_classes,				 FT_Stream       stream ){  FT_Error  error;  FT_Memory memory = stream->memory;  FT_UShort        m, n, k, count;  FT_ULong         cur_offset, new_offset, base_offset;  HB_BaseRecord*  br;  HB_Anchor*      ban;  base_offset = FILE_Pos();  if ( ACCESS_Frame( 2L ) )    return error;  count = ba->BaseCount = GET_UShort();  FORGET_Frame();  ba->BaseRecord = NULL;  if ( ALLOC_ARRAY( ba->BaseRecord, count, HB_BaseRecord ) )    return error;  br = ba->BaseRecord;  for ( m = 0; m < count; m++ )  {    br[m].BaseAnchor = NULL;    if ( ALLOC_ARRAY( br[m].BaseAnchor, num_classes, HB_Anchor ) )      goto Fail;    ban = br[m].BaseAnchor;    for ( n = 0; n < num_classes; n++ )    {      if ( ACCESS_Frame( 2L ) )	goto Fail0;      new_offset = GET_UShort() + base_offset;      FORGET_Frame();      if (new_offset == base_offset) {	/* Doulos SIL Regular is buggy and has zer offsets here.  Skip */	ban[n].PosFormat = 0;	continue;      }      cur_offset = FILE_Pos();      if ( FILE_Seek( new_offset ) ||	   ( error = Load_Anchor( &ban[n], stream ) ) != FT_Err_Ok )	goto Fail0;      (void)FILE_Seek( cur_offset );    }    continue;  Fail0:    for ( k = 0; k < n; k++ )      Free_Anchor( &ban[k], memory );    goto Fail;  }  return FT_Err_Ok;Fail:  for ( k = 0; k < m; k++ )  {    ban = br[k].BaseAnchor;    for ( n = 0; n < num_classes; n++ )      Free_Anchor( &ban[n], memory );    FREE( ban );  }  FREE( br );  return error;}static void  Free_BaseArray( HB_BaseArray*  ba,			     FT_UShort       num_classes,			     FT_Memory       memory ){  FT_UShort        m, n, count;  HB_BaseRecord*  br;  HB_Anchor*      ban;  if ( ba->BaseRecord )  {    count = ba->BaseCount;    br    = ba->BaseRecord;    for ( m = 0; m < count; m++ )    {      ban = br[m].BaseAnchor;      for ( n = 0; n < num_classes; n++ )	Free_Anchor( &ban[n], memory );      FREE( ban );    }    FREE( br );  }}/* MarkBasePosFormat1 */static FT_Error  Load_MarkBasePos( HB_GPOS_SubTable* st,				   FT_Stream         stream ){  FT_Error  error;  FT_Memory memory = stream->memory;  HB_MarkBasePos* mbp = &st->markbase;  FT_ULong  cur_offset, new_offset, base_offset;  base_offset = FILE_Pos();  if ( ACCESS_Frame( 4L ) )    return error;  mbp->PosFormat = GET_UShort();  new_offset     = GET_UShort() + base_offset;  FORGET_Frame();  if (mbp->PosFormat != 1)    return HB_Err_Invalid_SubTable_Format;  cur_offset = FILE_Pos();  if ( FILE_Seek( new_offset ) ||       ( error = _HB_OPEN_Load_Coverage( &mbp->MarkCoverage, stream ) ) != FT_Err_Ok )    return error;  (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_Coverage( &mbp->BaseCoverage, stream ) ) != FT_Err_Ok )    goto Fail3;  (void)FILE_Seek( cur_offset );  if ( ACCESS_Frame( 4L ) )    goto Fail2;  mbp->ClassCount = GET_UShort();  new_offset      = GET_UShort() + base_offset;  FORGET_Frame();  cur_offset = FILE_Pos();  if ( FILE_Seek( new_offset ) ||       ( error = Load_MarkArray( &mbp->MarkArray, stream ) ) != FT_Err_Ok )    goto Fail2;  (void)FILE_Seek( cur_offset );  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_BaseArray( &mbp->BaseArray, mbp->ClassCount,				 stream ) ) != FT_Err_Ok )    goto Fail1;  return FT_Err_Ok;Fail1:  Free_MarkArray( &mbp->MarkArray, memory );Fail2:  _HB_OPEN_Free_Coverage( &mbp->BaseCoverage, memory );Fail3:  _HB_OPEN_Free_Coverage( &mbp->MarkCoverage, memory );  return error;}static void  Free_MarkBasePos( HB_GPOS_SubTable* st,			       FT_Memory         memory ){  HB_MarkBasePos* mbp = &st->markbase;  Free_BaseArray( &mbp->BaseArray, mbp->ClassCount, memory );  Free_MarkArray( &mbp->MarkArray, memory );  _HB_OPEN_Free_Coverage( &mbp->BaseCoverage, memory );  _HB_OPEN_Free_Coverage( &mbp->MarkCoverage, memory );}static FT_Error  Lookup_MarkBasePos( GPOS_Instance*    gpi,				     HB_GPOS_SubTable* st,				     HB_Buffer        buffer,				     FT_UShort         flags,				     FT_UShort         context_length,				     int               nesting_level ){  FT_UShort        i, j, mark_index, base_index, property, class;  FT_Pos           x_mark_value, y_mark_value, x_base_value, y_base_value;  FT_Error         error;  HB_GPOSHeader*  gpos = gpi->gpos;  HB_MarkBasePos* mbp = &st->markbase;  HB_MarkArray*   ma;  HB_BaseArray*   ba;  HB_BaseRecord*  br;  HB_Anchor*      mark_anchor;  HB_Anchor*      base_anchor;  HB_Position     o;  FT_UNUSED(nesting_level);  if ( context_length != 0xFFFF && context_length < 1 )    return HB_Err_Not_Covered;  if ( flags & HB_LOOKUP_FLAG_IGNORE_BASE_GLYPHS )    return HB_Err_Not_Covered;  if ( CHECK_Property( gpos->gdef, IN_CURITEM(),		       flags, &property ) )    return error;  error = _HB_OPEN_Coverage_Index( &mbp->MarkCoverage, IN_CURGLYPH(),			  &mark_index );  if ( error )    return error;  /* now we search backwards for a non-mark glyph */  i = 1;  j = buffer->in_pos - 1;  while ( i <= buffer->in_pos )  {    error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),					&property );    if ( error )      return error;    if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )      break;    i++;    j--;  }  /* The following assertion is too strong -- at least for mangal.ttf. */#if 0  if ( property != HB_GDEF_BASE_GLYPH )    return HB_Err_Not_Covered;#endif  if ( i > buffer->in_pos )    return HB_Err_Not_Covered;  error = _HB_OPEN_Coverage_Index( &mbp->BaseCoverage, IN_GLYPH( j ),			  &base_index );  if ( error )    return error;  ma = &mbp->MarkArray;  if ( mark_index >= ma->MarkCount )    return HB_Err_Invalid_GPOS_SubTable;  class       = ma->MarkRecord[mark_index].Class;  mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor;  if ( class >= mbp->ClassCount )    return HB_Err_Invalid_GPOS_SubTable;  ba = &mbp->BaseArray;  if ( base_index >= ba->BaseCount )    return HB_Err_Invalid_GPOS_SubTable;  br          = &ba->BaseRecord[base_index];  base_anchor = &br->BaseAnchor[class];  error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH(),		      &x_mark_value, &y_mark_value );  if ( error )    return error;  error = Get_Anchor( gpi, base_anchor, IN_GLYPH( j ),		      &x_base_value, &y_base_value );  if ( error )    return error;  /* anchor points are not cumulative */  o = POSITION( buffer->in_pos );  o->x_pos     = x_base_value - x_mark_value;  o->y_pos     = y_base_value - y_mark_value;  o->x_advance = 0;  o->y_advance = 0;  o->back      = i;  (buffer->in_pos)++;  return FT_Err_Ok;}/* LookupType 5 *//* LigatureAttach */static FT_Error  Load_LigatureAttach( HB_LigatureAttach*  lat,				      FT_UShort            num_classes,				      FT_Stream            stream ){  FT_Error  error;  FT_Memory memory = stream->memory;  FT_UShort             m, n, k, count;  FT_ULong              cur_offset, new_offset, base_offset;  HB_ComponentRecord*  cr;  HB_Anchor*           lan;  base_offset = FILE_Pos();  if ( ACCESS_Frame( 2L ) )    return error;  count = lat->ComponentCount = GET_UShort();  FORGET_Frame();  lat->ComponentRecord = NULL;  if ( ALLOC_ARRAY( lat->ComponentRecord, count, HB_ComponentRecord ) )    return error;  cr = lat->ComponentRecord;  for ( m = 0; m < count; m++ )  {    cr[m].LigatureAnchor = NULL;

⌨️ 快捷键说明

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