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

📄 ttkern.c

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 C
字号:
/***************************************************************************//*                                                                         *//*  ttkern.c                                                               *//*                                                                         *//*    Load the basic TrueType kerning table.  This doesn't handle          *//*    kerning data within the GPOS table at the moment.                    *//*                                                                         *//*  Copyright 1996-2001, 2002, 2003, 2004, 2005 by                         *//*  David Turner, Robert Wilhelm, and Werner Lemberg.                      *//*                                                                         *//*  This file is part of the FreeType project, and may only be used,       *//*  modified, and distributed under the terms of the FreeType project      *//*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     *//*  this file you indicate that you have read the license and              *//*  understand and accept it fully.                                        *//*                                                                         *//***************************************************************************/#include <ft2build.h>#include FT_INTERNAL_DEBUG_H#include FT_INTERNAL_STREAM_H#include FT_TRUETYPE_TAGS_H#include "ttkern.h"#include "ttload.h"#include "sferrors.h"  /*************************************************************************/  /*                                                                       */  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */  /* messages during execution.                                            */  /*                                                                       */#undef  FT_COMPONENT#define FT_COMPONENT  trace_ttkern#undef  TT_KERN_INDEX#define TT_KERN_INDEX( g1, g2 )  ( ( (FT_ULong)(g1) << 16 ) | (g2) )#ifdef FT_OPTIMIZE_MEMORY  FT_LOCAL_DEF( FT_Error )  tt_face_load_kern( TT_Face    face,                     FT_Stream  stream )  {    FT_Error   error;    FT_ULong   table_size;    FT_Byte*   p;    FT_Byte*   p_limit;    FT_UInt    nn, num_tables;    FT_UInt32  avail = 0, ordered = 0;    /* the kern table is optional; exit silently if it is missing */    error = face->goto_table( face, TTAG_kern, stream, &table_size );    if ( error )      goto Exit;    if ( table_size < 4 )  /* the case of a malformed table */    {      FT_ERROR(( "kerning table is too small - ignored\n" ));      error = SFNT_Err_Table_Missing;      goto Exit;    }    if ( FT_FRAME_EXTRACT( table_size, face->kern_table ) )    {      FT_ERROR(( "could not extract kerning table\n" ));      goto Exit;    }    face->kern_table_size = table_size;    p       = face->kern_table;    p_limit = p + table_size;    p         += 2; /* skip version */    num_tables = FT_NEXT_USHORT( p );    if ( num_tables > 32 ) /* we only support up to 32 sub-tables */      num_tables = 32;    for ( nn = 0; nn < num_tables; nn++ )    {      FT_UInt    num_pairs, version, length, coverage;      FT_Byte*   p_next;      FT_UInt32  mask = 1UL << nn;      if ( p + 6 > p_limit )        break;      p_next = p;      version  = FT_NEXT_USHORT( p );      length   = FT_NEXT_USHORT( p );      coverage = FT_NEXT_USHORT( p );      if ( length <= 6 )        break;      p_next += length;      /* only use horizontal kerning tables */      if ( ( coverage & ~8 ) != 0x0001 ||           p + 8 > p_limit             )        goto NextTable;      num_pairs = FT_NEXT_USHORT( p );      p        += 6;      if ( p + 6 * num_pairs > p_limit )        goto NextTable;      avail |= mask;      /*       *  Now check whether the pairs in this table are ordered.       *  We then can use binary search.       */      if ( num_pairs > 0 )      {        FT_UInt  count;        FT_UInt  old_pair;        old_pair = FT_NEXT_ULONG( p );        p       += 2;        for ( count = num_pairs - 1; count > 0; count-- )        {          FT_UInt32  cur_pair;          cur_pair = FT_NEXT_ULONG( p );          if ( cur_pair <= old_pair )            break;          p += 2;          old_pair = cur_pair;        }        if ( count == 0 )          ordered |= mask;      }    NextTable:      p = p_next;    }    face->num_kern_tables = nn;    face->kern_avail_bits = avail;    face->kern_order_bits = ordered;  Exit:    return error;  }  FT_LOCAL_DEF( void )  tt_face_done_kern( TT_Face  face )  {    FT_Stream  stream = face->root.stream;    FT_FRAME_RELEASE( face->kern_table );    face->kern_table_size = 0;    face->num_kern_tables = 0;    face->kern_avail_bits = 0;    face->kern_order_bits = 0;  }  FT_LOCAL_DEF( FT_Int )  tt_face_get_kerning( TT_Face  face,                       FT_UInt  left_glyph,                       FT_UInt  right_glyph )  {    FT_Int    result = 0;    FT_UInt   count, mask = 1;    FT_Byte*  p       = face->kern_table;    p   += 4;    mask = 0x0001;    for ( count = face->num_kern_tables; count > 0; count--, mask <<= 1 )    {      FT_Byte* base     = p;      FT_Byte* next     = base;      FT_UInt  version  = FT_NEXT_USHORT( p );      FT_UInt  length   = FT_NEXT_USHORT( p );      FT_UInt  coverage = FT_NEXT_USHORT( p );      FT_Int   value    = 0;      FT_UNUSED( version );      next = base + length;      if ( ( face->kern_avail_bits & mask ) == 0 )        goto NextTable;      if ( p + 8 > next )        goto NextTable;      switch ( coverage >> 8 )      {      case 0:        {          FT_UInt   num_pairs = FT_NEXT_USHORT( p );          FT_ULong  key0      = TT_KERN_INDEX( left_glyph, right_glyph );          p += 6;          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 */          {            for ( count = num_pairs; count > 0; count-- )            {              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've never seen a single font        *  using it in real life...        */      default:        ;      }      goto NextTable;    Found:      if ( coverage & 8 ) /* overide or add */        result = value;      else        result += value;    NextTable:      p = next;    }    return result;  }#else /* !OPTIMIZE_MEMORY */  FT_CALLBACK_DEF( int )  tt_kern_pair_compare( const void*  a,                        const void*  b );  FT_LOCAL_DEF( FT_Error )  tt_face_load_kern( TT_Face    face,                     FT_Stream  stream )  {    FT_Error   error;    FT_Memory  memory = stream->memory;    FT_UInt    n, num_tables;    /* the kern table is optional; exit silently if it is missing */    error = face->goto_table( face, TTAG_kern, stream, 0 );    if ( error )      return SFNT_Err_Ok;    if ( FT_FRAME_ENTER( 4L ) )      goto Exit;    (void)FT_GET_USHORT();         /* version */    num_tables = FT_GET_USHORT();    FT_FRAME_EXIT();    for ( n = 0; n < num_tables; n++ )    {      FT_UInt  coverage;      FT_UInt  length;      if ( FT_FRAME_ENTER( 6L ) )        goto Exit;      (void)FT_GET_USHORT();           /* version                 */      length   = FT_GET_USHORT() - 6;  /* substract header length */      coverage = FT_GET_USHORT();      FT_FRAME_EXIT();      if ( coverage == 0x0001 )      {        FT_UInt        num_pairs;        TT_Kern0_Pair  pair;        TT_Kern0_Pair  limit;        /* found a horizontal format 0 kerning table! */        if ( FT_FRAME_ENTER( 8L ) )          goto Exit;        num_pairs = FT_GET_USHORT();        /* skip the rest */        FT_FRAME_EXIT();        /* allocate array of kerning pairs */        if ( FT_QNEW_ARRAY( face->kern_pairs, num_pairs ) ||             FT_FRAME_ENTER( 6L * num_pairs )             )          goto Exit;        pair  = face->kern_pairs;        limit = pair + num_pairs;        for ( ; pair < limit; pair++ )        {          pair->left  = FT_GET_USHORT();          pair->right = FT_GET_USHORT();          pair->value = FT_GET_USHORT();        }        FT_FRAME_EXIT();        face->num_kern_pairs   = num_pairs;        face->kern_table_index = n;        /* ensure that the kerning pair table is sorted (yes, some */        /* fonts have unsorted tables!)                            */        if ( num_pairs > 0 )        {          TT_Kern0_Pair  pair0 = face->kern_pairs;          FT_ULong       prev  = TT_KERN_INDEX( pair0->left, pair0->right );          for ( pair0++; pair0 < limit; pair0++ )          {            FT_ULong  next = TT_KERN_INDEX( pair0->left, pair0->right );            if ( next < prev )              goto SortIt;            prev = next;          }          goto Exit;        SortIt:          ft_qsort( (void*)face->kern_pairs, (int)num_pairs,                    sizeof ( TT_Kern0_PairRec ), tt_kern_pair_compare );        }        goto Exit;      }      if ( FT_STREAM_SKIP( length ) )        goto Exit;    }    /* no kern table found -- doesn't matter */    face->kern_table_index = -1;    face->num_kern_pairs   = 0;    face->kern_pairs       = NULL;  Exit:    return error;  }  FT_CALLBACK_DEF( int )  tt_kern_pair_compare( const void*  a,                        const void*  b )  {    TT_Kern0_Pair  pair1 = (TT_Kern0_Pair)a;    TT_Kern0_Pair  pair2 = (TT_Kern0_Pair)b;    FT_ULong  index1 = TT_KERN_INDEX( pair1->left, pair1->right );    FT_ULong  index2 = TT_KERN_INDEX( pair2->left, pair2->right );    return index1 < index2 ? -1                           : ( index1 > index2 ? 1                                               : 0 );  }  FT_LOCAL_DEF( void )  tt_face_done_kern( TT_Face  face )  {    FT_Memory  memory = face->root.stream->memory;    FT_FREE( face->kern_pairs );    face->num_kern_pairs = 0;  }  FT_LOCAL_DEF( FT_Int )  tt_face_get_kerning( TT_Face  face,                       FT_UInt  left_glyph,                       FT_UInt  right_glyph )  {    FT_Int         result = 0;    TT_Kern0_Pair  pair;    if ( face && face->kern_pairs )    {      /* there are some kerning pairs in this font file! */      FT_ULong  search_tag = TT_KERN_INDEX( left_glyph, right_glyph );      FT_Long   left, right;      left  = 0;      right = face->num_kern_pairs - 1;      while ( left <= right )      {        FT_Long   middle = left + ( ( right - left ) >> 1 );        FT_ULong  cur_pair;        pair     = face->kern_pairs + middle;        cur_pair = TT_KERN_INDEX( pair->left, pair->right );        if ( cur_pair == search_tag )          goto Found;        if ( cur_pair < search_tag )          left = middle + 1;        else          right = middle - 1;      }    }  Exit:    return result;  Found:    result = pair->value;    goto Exit;  }#endif /* !OPTIMIZE_MEMORY */#undef TT_KERN_INDEX/* END */

⌨️ 快捷键说明

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