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

📄 harfbuzz-gpos.c

📁 Pango is a library for layout and rendering of text, with an emphasis on internationalization. Pang
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Copyright (C) 1998-2004  David Turner and Werner Lemberg * Copyright (C) 2006  Behdad Esfahbod * Copyright (C) 2007  Red Hat, Inc. * * 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. * * Red Hat Author(s): Behdad Esfahbod */#include "harfbuzz-impl.h"#include "harfbuzz-gpos-private.h"#include "harfbuzz-open-private.h"#include "harfbuzz-gdef-private.h"struct  GPOS_Instance_{  HB_GPOSHeader*  gpos;  HB_Font          font;  HB_Bool          dvi;  HB_UShort        load_flags;  /* how the glyph should be loaded */  HB_Bool          r2l;  HB_UShort        last;        /* the last valid glyph -- used				   with cursive positioning     */  HB_Fixed           anchor_x;    /* the coordinates of the anchor point */  HB_Fixed           anchor_y;    /* of the last valid glyph             */};typedef struct GPOS_Instance_  GPOS_Instance;static HB_Error  GPOS_Do_Glyph_Lookup( GPOS_Instance*    gpi,				       HB_UShort         lookup_index,				       HB_Buffer        buffer,				       HB_UShort         context_length,				       int               nesting_level );/* the client application must replace this with something more   meaningful if multiple master fonts are to be supported.     */static HB_Error  default_mmfunc( HB_Font      font,				 HB_UShort    metric_id,				 HB_Fixed*      metric_value,				 void*        data ){  HB_UNUSED(font);  HB_UNUSED(metric_id);  HB_UNUSED(metric_value);  HB_UNUSED(data);  return ERR(HB_Err_Not_Covered); /* ERR() call intended */}HB_Error  HB_Load_GPOS_Table( HB_Font          font,			      HB_GPOSHeader** retptr,			      HB_GDEFHeader*  gdef ){  HB_UInt         cur_offset, new_offset, base_offset;  HB_GPOSHeader*  gpos;  HB_Stream  stream = font->stream;  HB_Error   error;  if ( !retptr )    return ERR(HB_Err_Invalid_Argument);  if ( GOTO_Table( TTAG_GPOS ) )    return error;  base_offset = FILE_Pos();  if ( ALLOC ( gpos, sizeof( *gpos ) ) )    return error;  gpos->gfunc = FT_Load_Glyph;  gpos->mmfunc = default_mmfunc;  /* 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( &gpos->ScriptList,				  stream ) ) != HB_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( &gpos->FeatureList,				   stream ) ) != HB_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( &gpos->LookupList,				  stream, HB_Type_GPOS ) ) != HB_Err_Ok )    goto Fail2;  gpos->gdef = gdef;      /* can be NULL */  if ( ( error =  _HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( gdef, stream,								     gpos->LookupList.Lookup,								     gpos->LookupList.LookupCount ) ) )	  goto Fail1;  *retptr = gpos;  return HB_Err_Ok;Fail1:  _HB_OPEN_Free_LookupList( &gpos->LookupList, HB_Type_GPOS );Fail2:  _HB_OPEN_Free_FeatureList( &gpos->FeatureList );Fail3:  _HB_OPEN_Free_ScriptList( &gpos->ScriptList );Fail4:  FREE( gpos );  return error;}HB_Error  HB_Done_GPOS_Table( HB_GPOSHeader* gpos ){  _HB_OPEN_Free_LookupList( &gpos->LookupList, HB_Type_GPOS );  _HB_OPEN_Free_FeatureList( &gpos->FeatureList );  _HB_OPEN_Free_ScriptList( &gpos->ScriptList );  FREE( gpos );  return HB_Err_Ok;}/***************************** * SubTable related functions *****************************//* shared tables *//* ValueRecord *//* There is a subtle difference in the specs between a `table' and a   `record' -- offsets for device tables in ValueRecords are taken from   the parent table and not the parent record.                          */static HB_Error  Load_ValueRecord( HB_ValueRecord*  vr,				   HB_UShort         format,				   HB_UInt          base_offset,				   HB_Stream         stream ){  HB_Error  error;  HB_UInt cur_offset, new_offset;  if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT )  {    if ( ACCESS_Frame( 2L ) )      return error;    vr->XPlacement = GET_Short();    FORGET_Frame();  }  else    vr->XPlacement = 0;  if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT )  {    if ( ACCESS_Frame( 2L ) )      return error;    vr->YPlacement = GET_Short();    FORGET_Frame();  }  else    vr->YPlacement = 0;  if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE )  {    if ( ACCESS_Frame( 2L ) )      return error;    vr->XAdvance = GET_Short();    FORGET_Frame();  }  else    vr->XAdvance = 0;  if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE )  {    if ( ACCESS_Frame( 2L ) )      return error;    vr->YAdvance = GET_Short();    FORGET_Frame();  }  else    vr->YAdvance = 0;  if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )  {    if ( ACCESS_Frame( 2L ) )      return error;    new_offset = GET_UShort();    FORGET_Frame();    if ( new_offset )    {      new_offset += base_offset;      cur_offset = FILE_Pos();      if ( FILE_Seek( new_offset ) ||	   ( error = _HB_OPEN_Load_Device( &vr->XPlacementDevice,				  stream ) ) != HB_Err_Ok )	return error;      (void)FILE_Seek( cur_offset );    }    else      goto empty1;  }  else  {  empty1:    vr->XPlacementDevice.StartSize  = 0;    vr->XPlacementDevice.EndSize    = 0;    vr->XPlacementDevice.DeltaValue = NULL;  }  if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )  {    if ( ACCESS_Frame( 2L ) )      goto Fail3;    new_offset = GET_UShort();    FORGET_Frame();    if ( new_offset )    {      new_offset += base_offset;      cur_offset = FILE_Pos();      if ( FILE_Seek( new_offset ) ||	   ( error = _HB_OPEN_Load_Device( &vr->YPlacementDevice,				  stream ) ) != HB_Err_Ok )	goto Fail3;      (void)FILE_Seek( cur_offset );    }    else      goto empty2;  }  else  {  empty2:    vr->YPlacementDevice.StartSize  = 0;    vr->YPlacementDevice.EndSize    = 0;    vr->YPlacementDevice.DeltaValue = NULL;  }  if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )  {    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 = _HB_OPEN_Load_Device( &vr->XAdvanceDevice,				  stream ) ) != HB_Err_Ok )	goto Fail2;      (void)FILE_Seek( cur_offset );    }    else      goto empty3;  }  else  {  empty3:    vr->XAdvanceDevice.StartSize  = 0;    vr->XAdvanceDevice.EndSize    = 0;    vr->XAdvanceDevice.DeltaValue = NULL;  }  if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )  {    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 = _HB_OPEN_Load_Device( &vr->YAdvanceDevice,				  stream ) ) != HB_Err_Ok )	goto Fail1;      (void)FILE_Seek( cur_offset );    }    else      goto empty4;  }  else  {  empty4:    vr->YAdvanceDevice.StartSize  = 0;    vr->YAdvanceDevice.EndSize    = 0;    vr->YAdvanceDevice.DeltaValue = NULL;  }  if ( format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT )  {    if ( ACCESS_Frame( 2L ) )      goto Fail1;    vr->XIdPlacement = GET_UShort();    FORGET_Frame();  }  else    vr->XIdPlacement = 0;  if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT )  {    if ( ACCESS_Frame( 2L ) )      goto Fail1;    vr->YIdPlacement = GET_UShort();    FORGET_Frame();  }  else    vr->YIdPlacement = 0;  if ( format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE )  {    if ( ACCESS_Frame( 2L ) )      goto Fail1;    vr->XIdAdvance = GET_UShort();    FORGET_Frame();  }  else    vr->XIdAdvance = 0;  if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE )  {    if ( ACCESS_Frame( 2L ) )      goto Fail1;    vr->YIdAdvance = GET_UShort();    FORGET_Frame();  }  else    vr->YIdAdvance = 0;  return HB_Err_Ok;Fail1:  _HB_OPEN_Free_Device( &vr->YAdvanceDevice );Fail2:  _HB_OPEN_Free_Device( &vr->XAdvanceDevice );Fail3:  _HB_OPEN_Free_Device( &vr->YPlacementDevice );  return error;}static void  Free_ValueRecord( HB_ValueRecord*  vr,			       HB_UShort         format ){  if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )    _HB_OPEN_Free_Device( &vr->YAdvanceDevice );  if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )    _HB_OPEN_Free_Device( &vr->XAdvanceDevice );  if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )    _HB_OPEN_Free_Device( &vr->YPlacementDevice );  if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )    _HB_OPEN_Free_Device( &vr->XPlacementDevice );}static HB_Error  Get_ValueRecord( GPOS_Instance*    gpi,				  HB_ValueRecord*  vr,				  HB_UShort         format,				  HB_Position      gd ){  HB_Fixed           value;  HB_Short         pixel_value;  HB_Error         error = HB_Err_Ok;  HB_GPOSHeader*  gpos = gpi->gpos;  HB_UShort  x_ppem, y_ppem;  HB_16Dot16   x_scale, y_scale;  if ( !format )    return HB_Err_Ok;  x_ppem  = gpi->font->size->metrics.x_ppem;  y_ppem  = gpi->font->size->metrics.y_ppem;  x_scale = gpi->font->size->metrics.x_scale;  y_scale = gpi->font->size->metrics.y_scale;  /* design units -> fractional pixel */  if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT )    gd->x_pos += x_scale * vr->XPlacement / 0x10000;  if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT )    gd->y_pos += y_scale * vr->YPlacement / 0x10000;  if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE )    gd->x_advance += x_scale * vr->XAdvance / 0x10000;  if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE )    gd->y_advance += y_scale * vr->YAdvance / 0x10000;  if ( !gpi->dvi )  {    /* pixel -> fractional pixel */    if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )    {      _HB_OPEN_Get_Device( &vr->XPlacementDevice, x_ppem, &pixel_value );      gd->x_pos += pixel_value << 6;    }    if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )    {      _HB_OPEN_Get_Device( &vr->YPlacementDevice, y_ppem, &pixel_value );      gd->y_pos += pixel_value << 6;    }    if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )    {      _HB_OPEN_Get_Device( &vr->XAdvanceDevice, x_ppem, &pixel_value );      gd->x_advance += pixel_value << 6;    }    if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )    {      _HB_OPEN_Get_Device( &vr->YAdvanceDevice, y_ppem, &pixel_value );      gd->y_advance += pixel_value << 6;    }  }  /* values returned from mmfunc() are already in fractional pixels */  if ( format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT )  {    error = (gpos->mmfunc)( gpi->font, vr->XIdPlacement,			    &value, gpos->data );    if ( error )      return error;    gd->x_pos += value;  }  if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT )  {    error = (gpos->mmfunc)( gpi->font, vr->YIdPlacement,			    &value, gpos->data );    if ( error )      return error;    gd->y_pos += value;  }  if ( format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE )  {    error = (gpos->mmfunc)( gpi->font, vr->XIdAdvance,			    &value, gpos->data );    if ( error )      return error;    gd->x_advance += value;  }  if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE )  {    error = (gpos->mmfunc)( gpi->font, vr->YIdAdvance,			    &value, gpos->data );    if ( error )      return error;    gd->y_advance += value;  }  return error;}/* AnchorFormat1 *//* AnchorFormat2 *//* AnchorFormat3 *//* AnchorFormat4 */static HB_Error  Load_Anchor( HB_Anchor*  an,			      HB_Stream    stream ){  HB_Error  error;  HB_UInt cur_offset, new_offset, base_offset;  base_offset = FILE_Pos();  if ( ACCESS_Frame( 2L ) )    return error;  an->PosFormat = GET_UShort();  FORGET_Frame();  switch ( an->PosFormat )  {  case 1:    if ( ACCESS_Frame( 4L ) )      return error;    an->af.af1.XCoordinate = GET_Short();    an->af.af1.YCoordinate = GET_Short();    FORGET_Frame();    break;  case 2:    if ( ACCESS_Frame( 6L ) )      return error;    an->af.af2.XCoordinate = GET_Short();    an->af.af2.YCoordinate = GET_Short();    an->af.af2.AnchorPoint = GET_UShort();    FORGET_Frame();    break;  case 3:    if ( ACCESS_Frame( 6L ) )      return error;    an->af.af3.XCoordinate = GET_Short();    an->af.af3.YCoordinate = GET_Short();

⌨️ 快捷键说明

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