Ejemplo n.º 1
0
pfr_face_get_kerning( FT_Face     pfrface,        /* PFR_Face */
                      FT_UInt     glyph1,
                      FT_UInt     glyph2,
                      FT_Vector*  kerning )
{
    PFR_Face     face     = (PFR_Face)pfrface;
    FT_Error     error    = FT_Err_Ok;
    PFR_PhyFont  phy_font = &face->phy_font;
    FT_UInt32    code1, code2, pair;


    kerning->x = 0;
    kerning->y = 0;

    if ( glyph1 > 0 )
        glyph1--;

    if ( glyph2 > 0 )
        glyph2--;

    /* convert glyph indices to character codes */
    if ( glyph1 > phy_font->num_chars ||
            glyph2 > phy_font->num_chars )
        goto Exit;

    code1 = phy_font->chars[glyph1].char_code;
    code2 = phy_font->chars[glyph2].char_code;
    pair  = PFR_KERN_INDEX( code1, code2 );

    /* now search the list of kerning items */
    {
        PFR_KernItem  item   = phy_font->kern_items;
        FT_Stream     stream = pfrface->stream;


        for ( ; item; item = item->next )
        {
            if ( pair >= item->pair1 && pair <= item->pair2 )
                goto FoundPair;
        }
        goto Exit;

FoundPair: /* we found an item, now parse it and find the value if any */
        if ( FT_STREAM_SEEK( item->offset )                       ||
                FT_FRAME_ENTER( item->pair_count * item->pair_size ) )
            goto Exit;

        {
            FT_UInt    count       = item->pair_count;
            FT_UInt    size        = item->pair_size;
            FT_UInt    power       = 1 << FT_MSB( count );
            FT_UInt    probe       = power * size;
            FT_UInt    extra       = count - power;
            FT_Byte*   base        = stream->cursor;
            FT_Bool    twobytes    = FT_BOOL( item->flags & 1 );
            FT_Bool    twobyte_adj = FT_BOOL( item->flags & 2 );
            FT_Byte*   p;
            FT_UInt32  cpair;


            if ( extra > 0 )
            {
                p = base + extra * size;

                if ( twobytes )
                    cpair = FT_NEXT_ULONG( p );
                else
                    cpair = PFR_NEXT_KPAIR( p );

                if ( cpair == pair )
                    goto Found;

                if ( cpair < pair )
                {
                    if ( twobyte_adj )
                        p += 2;
                    else
                        p++;
                    base = p;
                }
            }

            while ( probe > size )
            {
                probe >>= 1;
                p       = base + probe;

                if ( twobytes )
                    cpair = FT_NEXT_ULONG( p );
                else
                    cpair = PFR_NEXT_KPAIR( p );

                if ( cpair == pair )
                    goto Found;

                if ( cpair < pair )
                    base += probe;
            }

            p = base;

            if ( twobytes )
                cpair = FT_NEXT_ULONG( p );
            else
                cpair = PFR_NEXT_KPAIR( p );

            if ( cpair == pair )
            {
                FT_Int  value;


Found:
                if ( twobyte_adj )
                    value = FT_PEEK_SHORT( p );
                else
                    value = p[0];

                kerning->x = item->base_adj + value;
            }
        }

        FT_FRAME_EXIT();
    }

Exit:
    return error;
}
Ejemplo n.º 2
0
  tt_face_get_kerning( TT_Face  face,
                       FT_UInt  left_glyph,
                       FT_UInt  right_glyph )
  {
    FT_Int    result = 0;
    FT_UInt   count, mask;
    FT_Byte*  p       = face->kern_table;
    FT_Byte*  p_limit = p + face->kern_table_size;


    p   += 4;
    mask = 0x0001;

    for ( count = face->num_kern_tables;
          count > 0 && p + 6 <= p_limit;
          count--, mask <<= 1 )
    {
      FT_Byte* base     = p;
      FT_Byte* next;
      FT_UInt  version  = FT_NEXT_USHORT( p );
      FT_UInt  length   = FT_NEXT_USHORT( p );
      FT_UInt  coverage = FT_NEXT_USHORT( p );
      FT_UInt  num_pairs;
      FT_Int   value    = 0;

      FT_UNUSED( version );


      next = base + length;

      if ( next > p_limit )  /* handle broken table */
        next = p_limit;

      if ( ( face->kern_avail_bits & mask ) == 0 )
        goto NextTable;

      if ( p + 8 > next )
        goto NextTable;

      num_pairs = FT_NEXT_USHORT( p );
      p        += 6;

      if ( ( next - p ) < 6 * (int)num_pairs )  /* handle broken count  */
        num_pairs = (FT_UInt)( ( next - p ) / 6 );

      switch ( coverage >> 8 )
      {
      case 0:
        {
          FT_ULong  key0 = TT_KERN_INDEX( left_glyph, right_glyph );


          if ( face->kern_order_bits & mask )   /* binary search */
          {
            FT_UInt   min = 0;
            FT_UInt   max = num_pairs;


            while ( min < max )
            {
              FT_UInt   mid = ( min + max ) >> 1;
              FT_Byte*  q   = p + 6 * mid;
              FT_ULong  key;


              key = FT_NEXT_ULONG( q );

              if ( key == key0 )
              {
                value = FT_PEEK_SHORT( q );
                goto Found;
              }
              if ( key < key0 )
                min = mid + 1;
              else
                max = mid;
            }
          }
          else /* linear search */
          {
            FT_UInt  count2;


            for ( count2 = num_pairs; count2 > 0; count2-- )
            {
              FT_ULong  key = FT_NEXT_ULONG( p );


              if ( key == key0 )
              {
                value = FT_PEEK_SHORT( p );
                goto Found;
              }
              p += 2;
            }
          }
        }
        break;

       /*
        *  We don't support format 2 because we haven't seen a single font
        *  using it in real life...
        */

      default:
        ;
      }
Ejemplo n.º 3
0
  tt_face_get_metrics( TT_Face     face,
                       FT_Bool     vertical,
                       FT_UInt     gindex,
                       FT_Short   *abearing,
                       FT_UShort  *aadvance )
  {
    TT_HoriHeader*  header;
    FT_Byte*        p;
    FT_Byte*        limit;
    FT_UShort       k;


    if ( vertical )
    {
      header = (TT_HoriHeader*)&face->vertical;
      p      = face->vert_metrics;
      limit  = p + face->vert_metrics_size;
    }
    else
    {
      header = &face->horizontal;
      p      = face->horz_metrics;
      limit  = p + face->horz_metrics_size;
    }

    k = header->number_Of_HMetrics;

    if ( k > 0 )
    {
      if ( gindex < (FT_UInt)k )
      {
        p += 4 * gindex;
        if ( p + 4 > limit )
          goto NoData;

        *aadvance = FT_NEXT_USHORT( p );
        *abearing = FT_NEXT_SHORT( p );
      }
      else
      {
        p += 4 * ( k - 1 );
        if ( p + 4 > limit )
          goto NoData;

        *aadvance = FT_NEXT_USHORT( p );
        p += 2 + 2 * ( gindex - k );
        if ( p + 2 > limit )
          *abearing = 0;
        else
          *abearing = FT_PEEK_SHORT( p );
      }
    }
    else
    {
    NoData:
      *abearing = 0;
      *aadvance = 0;
    }

    return SFNT_Err_Ok;
  }