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

📄 ftxgpos.c

📁 字体缩放显示
💻 C
📖 第 1 页 / 共 5 页
字号:
    if ( !pvr )      return TTO_Err_Invalid_GPOS_SubTable;    glyph2 = in->string[in->pos];    for ( numpvr = ppf1->PairSet[index].PairValueCount;          numpvr;          numpvr--, pvr++ )    {      if ( glyph2 == pvr->SecondGlyph )      {        error = Get_ValueRecord( gpi, &pvr->Value1, format1,                                 &out[first_pos] );        if ( error )          return error;        return Get_ValueRecord( gpi, &pvr->Value2, format2,                                &out[in->pos] );      }    }    return TTO_Err_Not_Covered;  }  static TT_Error  Lookup_PairPos2( GPOS_Instance*       gpi,                                    TTO_PairPosFormat2*  ppf2,                                    TTO_GSUB_String*     in,                                    TTO_GPOS_Data*       out,                                    UShort               first_pos,                                    UShort               format1,                                    UShort               format2 )  {    TT_Error           error;    UShort             cl1, cl2;    TTO_Class1Record*  c1r;    TTO_Class2Record*  c2r;    error = Get_Class( &ppf2->ClassDef1, in->string[first_pos],                       &cl1, NULL );    if ( error )      return error;    error = Get_Class( &ppf2->ClassDef2, in->string[in->pos],                       &cl2, NULL );    if ( error )      return error;    c1r = &ppf2->Class1Record[cl1];    if ( !c1r )      return TTO_Err_Invalid_GPOS_SubTable;    c2r = &c1r->Class2Record[cl2];    error = Get_ValueRecord( gpi, &c2r->Value1, format1, &out[first_pos] );    if ( error )      return error;    return Get_ValueRecord( gpi, &c2r->Value2, format2, &out[in->pos] );  }  static TT_Error  Lookup_PairPos( GPOS_Instance*    gpi,                                   TTO_PairPos*      pp,                                   TTO_GSUB_String*  in,                                   TTO_GPOS_Data*    out,                                   UShort            flags,                                   UShort            context_length )  {    TT_Error         error;    UShort           index, property, first_pos;    TTO_GPOSHeader*  gpos = gpi->gpos;    if ( in->pos >= in->length - 1 )      return TTO_Err_Not_Covered;           /* Not enough glyphs in input */    if ( context_length != 0xFFFF && context_length < 2 )      return TTO_Err_Not_Covered;    if ( CHECK_Property( gpos->gdef, in->string[in->pos], flags, &property ) )      return error;    error = Coverage_Index( &pp->Coverage, in->string[in->pos], &index );    if ( error )      return error;    /* second glyph */    first_pos = in->pos;    (in->pos)++;    while ( CHECK_Property( gpos->gdef, in->string[in->pos],                            flags, &property ) )    {      if ( error && error != TTO_Err_Not_Covered )        return error;      if ( in->pos < in->length )        (in->pos)++;      else        break;    }    switch ( pp->PosFormat )    {    case 1:      error = Lookup_PairPos1( gpi, &pp->ppf.ppf1, in, out,                               first_pos, index,                               pp->ValueFormat1, pp->ValueFormat2 );      break;    case 2:      error = Lookup_PairPos2( gpi, &pp->ppf.ppf2, in, out, first_pos,                               pp->ValueFormat1, pp->ValueFormat2 );      break;    default:      return TTO_Err_Invalid_GPOS_SubTable_Format;    }    /* adjusting the `next' glyph */    if ( pp->ValueFormat2 )      (in->pos)++;    return error;  }  /* LookupType 3 */  /* CursivePosFormat1 */  TT_Error  Load_CursivePos( TTO_CursivePos*  cp,                             PFace            input )  {    DEFINE_LOAD_LOCALS( input->stream );    UShort                n, count;    ULong                 cur_offset, new_offset, base_offset;    TTO_EntryExitRecord*  eer;    base_offset = FILE_Pos();    if ( ACCESS_Frame( 4L ) )      return error;    cp->PosFormat = GET_UShort();    new_offset    = GET_UShort() + base_offset;    FORGET_Frame();    cur_offset = FILE_Pos();    if ( FILE_Seek( new_offset ) ||         ( error = Load_Coverage( &cp->Coverage, input ) ) != TT_Err_Ok )      return error;    (void)FILE_Seek( cur_offset );    if ( ACCESS_Frame( 2L ) )      goto Fail2;    count = cp->EntryExitCount = GET_UShort();    FORGET_Frame();    cp->EntryExitRecord = NULL;    if ( ALLOC_ARRAY( cp->EntryExitRecord, count, TTO_EntryExitRecord ) )      goto Fail2;    eer = cp->EntryExitRecord;    for ( n = 0; n < count; n++ )    {      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 = Load_Anchor( &eer[n].EntryAnchor,                                    input ) ) != TT_Err_Ok )          goto Fail1;        (void)FILE_Seek( cur_offset );      }      else        eer[n].EntryAnchor.PosFormat   = 0;      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 = Load_Anchor( &eer[n].ExitAnchor,                                    input ) ) != TT_Err_Ok )          goto Fail1;        (void)FILE_Seek( cur_offset );      }      else        eer[n].ExitAnchor.PosFormat   = 0;    }    return TT_Err_Ok;  Fail1:    for ( n = 0; n < count; n++ )    {      Free_Anchor( &eer[n].EntryAnchor );      Free_Anchor( &eer[n].ExitAnchor );    }    FREE( eer );  Fail2:    Free_Coverage( &cp->Coverage );    return error;  }  void  Free_CursivePos( TTO_CursivePos*  cp )  {    UShort                n, count;    TTO_EntryExitRecord*  eer;    if ( cp->EntryExitRecord )    {      count = cp->EntryExitCount;      eer   = cp->EntryExitRecord;      for ( n = 0; n < count; n++ )      {        Free_Anchor( &eer[n].EntryAnchor );        Free_Anchor( &eer[n].ExitAnchor );      }      FREE( eer );    }    Free_Coverage( &cp->Coverage );  }  static TT_Error  Lookup_CursivePos( GPOS_Instance*    gpi,                                      TTO_CursivePos*   cp,                                      TTO_GSUB_String*  in,                                      TTO_GPOS_Data*    out,                                      UShort            flags,                                      UShort            context_length )  {    UShort           index, property;    TT_Error         error;    TTO_GPOSHeader*  gpos = gpi->gpos;    TTO_EntryExitRecord*  eer;    TT_Pos                entry_x, entry_y;    TT_Pos                exit_x, exit_y;    if ( context_length != 0xFFFF && context_length < 1 )    {      gpi->last = 0xFFFF;      return TTO_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->string[in->pos], flags, &property ) )      return error;    /* We don't handle mark glyphs here.  According to Andrei, this isn't       possible, but who knows...                                         */    if ( property == MARK_GLYPH )    {      gpi->last = 0xFFFF;      return TTO_Err_Not_Covered;    }    error = Coverage_Index( &cp->Coverage, in->string[in->pos], &index );    if ( error )    {      gpi->last = 0xFFFF;      return error;    }    if ( index >= cp->EntryExitCount )      return TTO_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 TTO_Err_Not_Covered if there is no anchor       table.                                                         */    error = Get_Anchor( gpi, &eer->EntryAnchor, in->string[in->pos],                        &entry_x, &entry_y );    if ( error == TTO_Err_Not_Covered )      goto end;    if ( error )      return error;    if ( gpi->r2l )    {      out[in->pos].x_advance   = entry_x - gpi->anchor_x;      out[in->pos].new_advance = TRUE;    }    else    {      out[gpi->last].x_advance   = gpi->anchor_x - entry_x;      out[gpi->last].new_advance = TRUE;    }    out[in->pos].y_pos = gpi->anchor_y - entry_y + out[gpi->last].y_pos;  end:    error = Get_Anchor( gpi, &eer->ExitAnchor, in->string[in->pos],                        &exit_x, &exit_y );    if ( error == TTO_Err_Not_Covered )      gpi->last = 0xFFFF;    else    {      if ( gpi->first == 0xFFFF )        gpi->first  = in->pos;      gpi->last     = in->pos;      gpi->anchor_x = exit_x;      gpi->anchor_y = exit_y;    }    if ( error )      return error;    (in->pos)++;    return TT_Err_Ok;  }  /* LookupType 4 */  /* BaseArray */  static TT_Error  Load_BaseArray( TTO_BaseArray*  ba,                                   UShort          num_classes,                                   PFace           input )  {    DEFINE_LOAD_LOCALS( input->stream );    UShort           m, n, count;    ULong            cur_offset, new_offset, base_offset;    TTO_BaseRecord*  br;    TTO_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, TTO_BaseRecord ) )      return error;    br = ba->BaseRecord;    for ( m = 0; m < count; m++ )    {      br[m].BaseAnchor = NULL;      if ( ALLOC_ARRAY( br[m].BaseAnchor, num_classes, TTO_Anchor ) )        goto Fail;      ban = br[m].BaseAnchor;      for ( n = 0; n < num_classes; 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_Anchor( &ban[n], input ) ) != TT_Err_Ok )          goto Fail;        (void)FILE_Seek( cur_offset );      }    }    return TT_Err_Ok;  Fail:    for ( m = 0; m < count; m++ )    {

⌨️ 快捷键说明

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