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

📄 ftxkern.c

📁 字体缩放显示
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************* * *  ftxkern.c                                                    1.0 * *    Kerning support extension. * *  Copyright 1996-2002 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. * * *  The kerning support is currently part of the engine extensions. * ******************************************************************/#include "ftxkern.h"#include "ttextend.h"#include "tttypes.h"#include "ttdebug.h"#include "ttload.h"#include "ttmemory.h"#include "ttfile.h"#include "ttobjs.h"#include "tttags.h"/* Required by the tracing mode */#undef  TT_COMPONENT#define TT_COMPONENT  trace_any#define KERNING_ID  Build_Extension_ID( 'k', 'e', 'r', 'n' )#undef  KERN_INDEX#define KERN_INDEX(g1,g2)   (((TT_ULong)g1 << 16) | g2)  /* compare two kerning pairs, for sorting */  static int  compare_kern_pairs( const void* a, const void* b )  {    TT_Kern_0_Pair*  pair1 = (TT_Kern_0_Pair*)a;    TT_Kern_0_Pair*  pair2 = (TT_Kern_0_Pair*)b;    TT_ULong  index1 = KERN_INDEX( pair1->left, pair1->right );    TT_ULong  index2 = KERN_INDEX( pair2->left, pair2->right );    return ( index1 < index2 ? -1 :           ( index1 > index2 ?  1 : 0 ));  }  /* a simple shell sort algorithm to avoid calling qsort */  /* (since this creates problems on 16-bit machines)     */  static void  sort_kern_pairs( TT_Kern_0_Pair*  pairs,                   int              count )  {    TT_Kern_0_Pair  *i, *j, *limit = pairs + count;    TT_Kern_0_Pair  temp;    int             gap;    /* compute initial gap */    for ( gap = 0; ++gap < count; gap *= 3 )      ;    while ( gap /= 3 )    {      for ( i = pairs + gap; i < limit; i++ )      {        for ( j = i - gap; ; j -= gap )        {          TT_Kern_0_Pair*  k = j + gap;          if ( compare_kern_pairs( j, k ) < 0 )            break;          temp = *j;          *j   = *k;          *k   = temp;          if ( j < pairs + gap )            break;        }      }    }  }  /* check whether the kern table is sorted */  static int  is_sorted( TT_Kern_0_Pair* table, TT_ULong num_pairs )  {    TT_ULong  i;    for ( i=1; i<num_pairs; i++ )    {      if ( compare_kern_pairs(&table[i-1], &table[i]) != -1 )        return 0;    }    return 1;  }/******************************************************************* * *  Function    :  SubTable_Load_0 * *  Description :  Loads a format 0 kerning subtable data. * *  Input  :  kern0   pointer to the kerning subtable * *  Output :  error code * *  Notes  :  - Assumes that the stream is already `used' * *            - the file cursor must be set by the caller * *            - in case of error, the function _must_ destroy *              the data it allocates! * ******************************************************************/  static TT_Error  Subtable_Load_0( TT_Kern_0*  kern0,                   PFace       input )  {    DEFINE_LOAD_LOCALS( input->stream );    UShort  num_pairs, n;    if ( ACCESS_Frame( 8L ) )      return error;    num_pairs            = GET_UShort();    kern0->nPairs        = 0;    kern0->searchRange   = GET_UShort();    kern0->entrySelector = GET_UShort();    kern0->rangeShift    = GET_UShort();    /* we only set kern0->nPairs if the subtable has been loaded */    FORGET_Frame();    if ( ALLOC_ARRAY( kern0->pairs, num_pairs, TT_Kern_0_Pair ) )      return error;    if ( ACCESS_Frame( num_pairs * 6L ) )      goto Fail;    for ( n = 0; n < num_pairs; n++ )    {      kern0->pairs[n].left  = GET_UShort();      kern0->pairs[n].right = GET_UShort();      kern0->pairs[n].value = GET_UShort();      if ( kern0->pairs[n].left >= input->numGlyphs ||           kern0->pairs[n].right >= input->numGlyphs )      {        FORGET_Frame();        error = TT_Err_Invalid_Kerning_Table;        goto Fail;      }    }    FORGET_Frame();    /* we're ok, set the pairs count */    kern0->nPairs = num_pairs;    /* the spec says that the kerning pairs must be sorted,       but some brain damaged font producers don't do that correctly.. (JvR 3/4/2000) */    if ( !is_sorted( kern0->pairs, num_pairs ) )      sort_kern_pairs( kern0->pairs, num_pairs );    return TT_Err_Ok;    Fail:      FREE( kern0->pairs );      return error;  }/******************************************************************* * *  Function    :  SubTable_Load_2 * *  Description :  Loads a format 2 kerning subtable data. * *  Input  :  kern2   pointer to the kerning subtable *            length  subtable length.  This is required as *                    the subheader doesn't give any indication *                    of the size of the `array' table. * *  Output :  error code * *  Notes  :  - Assumes that the stream is already `used' * *            - the file cursor must be set by the caller * *            - in case of error, the function _must_ destroy *              the data it allocates! * ******************************************************************/  static TT_Error  Subtable_Load_2( TT_Kern_2*  kern2,                   PFace       input )  {    DEFINE_LOAD_LOCALS( input->stream );    Long  table_base;    UShort  left_offset, right_offset, array_offset;    ULong   array_size;    UShort  left_max, right_max, n;    /* record the table offset */    table_base = FILE_Pos();    if ( ACCESS_Frame( 8L ) )      return error;    kern2->rowWidth = GET_UShort();    left_offset     = GET_UShort();    right_offset    = GET_UShort();    array_offset    = GET_UShort();    FORGET_Frame();    /* first load left and right glyph classes */    if ( FILE_Seek( table_base + left_offset ) ||         ACCESS_Frame( 4L ) )      return error;    kern2->leftClass.firstGlyph = GET_UShort();    kern2->leftClass.nGlyphs    = GET_UShort();    FORGET_Frame();    if ( ALLOC_ARRAY( kern2->leftClass.classes,                      kern2->leftClass.nGlyphs,                      UShort ) )      return error;    /* load left offsets */    if ( ACCESS_Frame( kern2->leftClass.nGlyphs * 2L ) )      goto Fail_Left;    for ( n = 0; n < kern2->leftClass.nGlyphs; n++ )      kern2->leftClass.classes[n] = GET_UShort();    FORGET_Frame();    /* right class */    if ( FILE_Seek( table_base + right_offset ) ||         ACCESS_Frame( 4L ) )      goto Fail_Left;    kern2->rightClass.firstGlyph = GET_UShort();    kern2->rightClass.nGlyphs    = GET_UShort();    FORGET_Frame();    if ( ALLOC_ARRAY( kern2->rightClass.classes,                      kern2->rightClass.nGlyphs,                      UShort ) )      goto Fail_Left;    /* load right offsets */    if ( ACCESS_Frame( kern2->rightClass.nGlyphs * 2L ) )      goto Fail_Right;    for ( n = 0; n < kern2->rightClass.nGlyphs; n++ )      kern2->rightClass.classes[n] = GET_UShort();    FORGET_Frame();    /* Now load the kerning array.  We don't have its size, we */    /* must compute it from what we know.                      */    /* We thus compute the maximum left and right offsets and  */    /* add them to get the array size.                         */    left_max = right_max = 0;    for ( n = 0; n < kern2->leftClass.nGlyphs; n++ )      left_max = MAX( left_max, kern2->leftClass.classes[n] );    for ( n = 0; n < kern2->rightClass.nGlyphs; n++ )      right_max = MAX( right_max, kern2->leftClass.classes[n] );    array_size = left_max + right_max + 2;    if ( ALLOC( kern2->array, array_size ) )      goto Fail_Right;    if ( ACCESS_Frame( array_size ) )      goto Fail_Array;    for ( n = 0; (UInt)n < array_size/2; n++ )      kern2->array[n] = GET_Short();    FORGET_Frame();    /* we're good now */    return TT_Err_Ok;  Fail_Array:    FREE( kern2->array );

⌨️ 快捷键说明

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