Hash :
76a5f623
        
        Author :
  
        
        Date :
2000-11-04T01:55:49
        
      
major reformatting of the sources: FT_EXPORT_DEF => FT_EXPORT FT_EXPORT_FUNC => FT_EXPORT_DEF BASE_DEF => FT_BASE BASE_FUNC => FT_BASE_DEF LOCAL_DEF => FT_LOCAL LOCAL_FUNC => FT_LOCAL_DEF LOCAL_FUNC_X => FT_CALLBACK_DEF LOCAL_DEF_X => FT_CALLBACK_TABLE FT_CPLUSPLUS => FT_CALLBACK_TABLE_DEF
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
/***************************************************************************/
/*                                                                         */
/*  t1afm.c                                                                */
/*                                                                         */
/*    AFM support for Type 1 fonts (body).                                 */
/*                                                                         */
/*  Copyright 1996-2000 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.                                        */
/*                                                                         */
/***************************************************************************/
#ifdef FT_FLAT_COMPILE
#include "t1afm.h"
#else
#include <type1/t1afm.h>
#endif
#include <freetype/internal/ftstream.h>
#include <freetype/internal/t1types.h>
#include <stdlib.h>  /* for qsort()   */
#include <string.h>  /* for strcmp()  */
#include <ctype.h>   /* for isalnum() */
  /*************************************************************************/
  /*                                                                       */
  /* 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_t1afm
  FT_LOCAL_DEF
  void  T1_Done_AFM( FT_Memory  memory,
                     T1_AFM*    afm )
  {
    FREE( afm->kern_pairs );
    afm->num_pairs = 0;
  }
#undef  IS_KERN_PAIR
#define IS_KERN_PAIR( p )  ( p[0] == 'K' && p[1] == 'P' )
#define IS_ALPHANUM( c )  ( isalnum( c ) || \
                            c == '_'     || \
                            c == '.'     )
  /* read a glyph name and return the equivalent glyph index */
  static
  FT_UInt  afm_atoindex( FT_Byte**  start,
                         FT_Byte*   limit,
                         T1_Font*   type1 )
  {
    FT_Byte*  p = *start;
    FT_Int    len;
    FT_UInt   result = 0;
    char      temp[64];
    /* skip whitespace */
    while ( ( *p == ' ' || *p == '\t' || *p == ':' || *p == ';' ) &&
            p < limit                                             )
      p++;
    *start = p;
    /* now, read glyph name */
    while ( IS_ALPHANUM( *p ) && p < limit )
      p++;
    len = p - *start;
    if ( len > 0 && len < 64 )
    {
      FT_Int  n;
      /* copy glyph name to intermediate array */
      MEM_Copy( temp, *start, len );
      temp[len] = 0;
      /* lookup glyph name in face array */
      for ( n = 0; n < type1->num_glyphs; n++ )
      {
        char*  gname = (char*)type1->glyph_names[n];
        if ( gname && gname[0] == temp[0] && strcmp( gname, temp ) == 0 )
        {
          result = n;
          break;
        }
      }
    }
    *start = p;
    return result;
  }
  /* read an integer */
  static
  int  afm_atoi( FT_Byte**  start,
                 FT_Byte*   limit )
  {
    FT_Byte*  p    = *start;
    int       sum  = 0;
    int       sign = 1;
    /* skip everything that is not a number */
    while ( p < limit && !isdigit( *p ) )
    {
      sign = 1;
      if ( *p == '-' )
        sign = -1;
      p++;
    }
    while ( p < limit && isdigit( *p ) )
    {
      sum = sum * 10 + ( *p - '0' );
      p++;
    }
    *start = p;
    return sum * sign;
  }
#undef  KERN_INDEX
#define KERN_INDEX( g1, g2 )  ( ( (FT_ULong)g1 << 16 ) | g2 )
  /* compare two kerning pairs */
  FT_CALLBACK_DEF
  int  compare_kern_pairs( const void*  a,
                           const void*  b )
  {
    T1_Kern_Pair*  pair1 = (T1_Kern_Pair*)a;
    T1_Kern_Pair*  pair2 = (T1_Kern_Pair*)b;
    FT_ULong  index1 = KERN_INDEX( pair1->glyph1, pair1->glyph2 );
    FT_ULong  index2 = KERN_INDEX( pair2->glyph1, pair2->glyph2 );
    return ( index1 - index2 );
  }
  /* parse an AFM file -- for now, only read the kerning pairs */
  FT_LOCAL_DEF
  FT_Error  T1_Read_AFM( FT_Face    t1_face,
                         FT_Stream  stream )
  {
    FT_Error       error;
    FT_Memory      memory = stream->memory;
    FT_Byte*       start;
    FT_Byte*       limit;
    FT_Byte*       p;
    FT_Int         count = 0;
    T1_Kern_Pair*  pair;
    T1_Font*       type1 = &((T1_Face)t1_face)->type1;
    T1_AFM*        afm   = 0;
    if ( ACCESS_Frame( stream->size ) )
      return error;
    start = (FT_Byte*)stream->cursor;
    limit = (FT_Byte*)stream->limit;
    p     = start;
    /* we are now going to count the occurences of `KP' or `KPX' in */
    /* the AFM file                                                 */
    count = 0;
    for ( p = start; p < limit - 3; p++ )
    {
      if ( IS_KERN_PAIR( p ) )
        count++;
    }
    /* Actually, kerning pairs are simply optional! */
    if ( count == 0 )
      goto Exit;
    /* allocate the pairs */
    if ( ALLOC( afm, sizeof ( *afm ) )                       ||
         ALLOC_ARRAY( afm->kern_pairs, count, T1_Kern_Pair ) )
      goto Exit;
    /* now, read each kern pair */
    pair           = afm->kern_pairs;
    afm->num_pairs = count;
    /* save in face object */
    ((T1_Face)t1_face)->afm_data = afm;
    for ( p = start; p < limit - 3; p++ )
    {
      if ( IS_KERN_PAIR( p ) )
      {
        FT_Byte*  q;
        /* skip keyword (KP or KPX) */
        q = p + 2;
        if ( *q == 'X' )
          q++;
        pair->glyph1    = afm_atoindex( &q, limit, type1 );
        pair->glyph2    = afm_atoindex( &q, limit, type1 );
        pair->kerning.x = afm_atoi( &q, limit );
        pair->kerning.y = 0;
        if ( p[2] != 'X' )
          pair->kerning.y = afm_atoi( &q, limit );
        pair++;
      }
    }
    /* now, sort the kern pairs according to their glyph indices */
    qsort( afm->kern_pairs, count, sizeof ( T1_Kern_Pair ),
           compare_kern_pairs );
  Exit:
    if ( error )
      FREE( afm );
    FORGET_Frame();
    return error;
  }
  /* find the kerning for a given glyph pair */
  FT_LOCAL_DEF
  void  T1_Get_Kerning( T1_AFM*     afm,
                        FT_UInt     glyph1,
                        FT_UInt     glyph2,
                        FT_Vector*  kerning )
  {
    T1_Kern_Pair  *min, *mid, *max;
    FT_ULong      index = KERN_INDEX( glyph1, glyph2 );
    /* simple binary search */
    min = afm->kern_pairs;
    max = min + afm->num_pairs - 1;
    while ( min <= max )
    {
      FT_ULong  midi;
      mid  = min + ( max - min ) / 2;
      midi = KERN_INDEX( mid->glyph1, mid->glyph2 );
      if ( midi == index )
      {
        *kerning = mid->kerning;
        return;
      }
      if ( midi < index )
        min = mid + 1;
      else
        max = mid - 1;
    }
    kerning->x = 0;
    kerning->y = 0;
  }
/* END */