~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/3rdparty/freetype/src/type1/t1afm.c

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************/
 
2
/*                                                                         */
 
3
/*  t1afm.c                                                                */
 
4
/*                                                                         */
 
5
/*    AFM support for Type 1 fonts (body).                                 */
 
6
/*                                                                         */
 
7
/*  Copyright 1996-2001, 2002, 2003 by                                     */
 
8
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 
9
/*                                                                         */
 
10
/*  This file is part of the FreeType project, and may only be used,       */
 
11
/*  modified, and distributed under the terms of the FreeType project      */
 
12
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
 
13
/*  this file you indicate that you have read the license and              */
 
14
/*  understand and accept it fully.                                        */
 
15
/*                                                                         */
 
16
/***************************************************************************/
 
17
 
 
18
 
 
19
#include <ft2build.h>
 
20
#include "t1afm.h"
 
21
#include FT_INTERNAL_STREAM_H
 
22
#include FT_INTERNAL_TYPE1_TYPES_H
 
23
 
 
24
 
 
25
  /*************************************************************************/
 
26
  /*                                                                       */
 
27
  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
 
28
  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
 
29
  /* messages during execution.                                            */
 
30
  /*                                                                       */
 
31
#undef  FT_COMPONENT
 
32
#define FT_COMPONENT  trace_t1afm
 
33
 
 
34
 
 
35
  FT_LOCAL_DEF( void )
 
36
  T1_Done_AFM( FT_Memory  memory,
 
37
               T1_AFM*    afm )
 
38
  {
 
39
    FT_FREE( afm->kern_pairs );
 
40
    afm->num_pairs = 0;
 
41
    FT_FREE( afm );
 
42
  }
 
43
 
 
44
 
 
45
#undef  IS_KERN_PAIR
 
46
#define IS_KERN_PAIR( p )  ( p[0] == 'K' && p[1] == 'P' )
 
47
 
 
48
#define IS_ALPHANUM( c )  ( ft_isalnum( c ) || \
 
49
                            c == '_'        || \
 
50
                            c == '.'        )
 
51
 
 
52
 
 
53
  /* read a glyph name and return the equivalent glyph index */
 
54
  static FT_UInt
 
55
  afm_atoindex( FT_Byte**  start,
 
56
                FT_Byte*   limit,
 
57
                T1_Font    type1 )
 
58
  {
 
59
    FT_Byte*    p = *start;
 
60
    FT_PtrDist  len;
 
61
    FT_UInt     result = 0;
 
62
    char        temp[64];
 
63
 
 
64
 
 
65
    /* skip whitespace */
 
66
    while ( ( *p == ' ' || *p == '\t' || *p == ':' || *p == ';' ) &&
 
67
            p < limit                                             )
 
68
      p++;
 
69
    *start = p;
 
70
 
 
71
    /* now, read glyph name */
 
72
    while ( IS_ALPHANUM( *p ) && p < limit )
 
73
      p++;
 
74
 
 
75
    len = p - *start;
 
76
 
 
77
    if ( len > 0 && len < 64 )
 
78
    {
 
79
      FT_Int  n;
 
80
 
 
81
 
 
82
      /* copy glyph name to intermediate array */
 
83
      FT_MEM_COPY( temp, *start, len );
 
84
      temp[len] = 0;
 
85
 
 
86
      /* lookup glyph name in face array */
 
87
      for ( n = 0; n < type1->num_glyphs; n++ )
 
88
      {
 
89
        char*  gname = (char*)type1->glyph_names[n];
 
90
 
 
91
 
 
92
        if ( gname && gname[0] == temp[0] && ft_strcmp( gname, temp ) == 0 )
 
93
        {
 
94
          result = n;
 
95
          break;
 
96
        }
 
97
      }
 
98
    }
 
99
    *start = p;
 
100
    return result;
 
101
  }
 
102
 
 
103
 
 
104
  /* read an integer */
 
105
  static int
 
106
  afm_atoi( FT_Byte**  start,
 
107
            FT_Byte*   limit )
 
108
  {
 
109
    FT_Byte*  p    = *start;
 
110
    int       sum  = 0;
 
111
    int       sign = 1;
 
112
 
 
113
 
 
114
    /* skip everything that is not a number */
 
115
    while ( p < limit && !isdigit( *p ) )
 
116
    {
 
117
      sign = 1;
 
118
      if ( *p == '-' )
 
119
        sign = -1;
 
120
 
 
121
      p++;
 
122
    }
 
123
 
 
124
    while ( p < limit && isdigit( *p ) )
 
125
    {
 
126
      sum = sum * 10 + ( *p - '0' );
 
127
      p++;
 
128
    }
 
129
    *start = p;
 
130
 
 
131
    return sum * sign;
 
132
  }
 
133
 
 
134
 
 
135
#undef  KERN_INDEX
 
136
#define KERN_INDEX( g1, g2 )  ( ( (FT_ULong)g1 << 16 ) | g2 )
 
137
 
 
138
 
 
139
  /* compare two kerning pairs */
 
140
  FT_CALLBACK_DEF( int )
 
141
  compare_kern_pairs( const void*  a,
 
142
                      const void*  b )
 
143
  {
 
144
    T1_Kern_Pair*  pair1 = (T1_Kern_Pair*)a;
 
145
    T1_Kern_Pair*  pair2 = (T1_Kern_Pair*)b;
 
146
 
 
147
    FT_ULong  index1 = KERN_INDEX( pair1->glyph1, pair1->glyph2 );
 
148
    FT_ULong  index2 = KERN_INDEX( pair2->glyph1, pair2->glyph2 );
 
149
 
 
150
 
 
151
    return (int)( index1 - index2 );
 
152
  }
 
153
 
 
154
 
 
155
  /* parse an AFM file -- for now, only read the kerning pairs */
 
156
  FT_LOCAL_DEF( FT_Error )
 
157
  T1_Read_AFM( FT_Face    t1_face,
 
158
               FT_Stream  stream )
 
159
  {
 
160
    FT_Error       error;
 
161
    FT_Memory      memory = stream->memory;
 
162
    FT_Byte*       start;
 
163
    FT_Byte*       limit;
 
164
    FT_Byte*       p;
 
165
    FT_Int         count = 0;
 
166
    T1_Kern_Pair*  pair;
 
167
    T1_Font        type1 = &((T1_Face)t1_face)->type1;
 
168
    T1_AFM*        afm   = 0;
 
169
 
 
170
 
 
171
    if ( FT_FRAME_ENTER( stream->size ) )
 
172
      return error;
 
173
 
 
174
    start = (FT_Byte*)stream->cursor;
 
175
    limit = (FT_Byte*)stream->limit;
 
176
    p     = start;
 
177
 
 
178
    /* we are now going to count the occurences of `KP' or `KPX' in */
 
179
    /* the AFM file                                                 */
 
180
    count = 0;
 
181
    for ( p = start; p < limit - 3; p++ )
 
182
    {
 
183
      if ( IS_KERN_PAIR( p ) )
 
184
        count++;
 
185
    }
 
186
 
 
187
    /* Actually, kerning pairs are simply optional! */
 
188
    if ( count == 0 )
 
189
      goto Exit;
 
190
 
 
191
    /* allocate the pairs */
 
192
    if ( FT_NEW( afm ) || FT_NEW_ARRAY( afm->kern_pairs, count ) )
 
193
      goto Exit;
 
194
 
 
195
    /* now, read each kern pair */
 
196
    pair           = afm->kern_pairs;
 
197
    afm->num_pairs = count;
 
198
 
 
199
    /* save in face object */
 
200
    ((T1_Face)t1_face)->afm_data = afm;
 
201
 
 
202
    t1_face->face_flags |= FT_FACE_FLAG_KERNING;
 
203
 
 
204
    for ( p = start; p < limit - 3; p++ )
 
205
    {
 
206
      if ( IS_KERN_PAIR( p ) )
 
207
      {
 
208
        FT_Byte*  q;
 
209
 
 
210
 
 
211
        /* skip keyword (KP or KPX) */
 
212
        q = p + 2;
 
213
        if ( *q == 'X' )
 
214
          q++;
 
215
 
 
216
        pair->glyph1    = afm_atoindex( &q, limit, type1 );
 
217
        pair->glyph2    = afm_atoindex( &q, limit, type1 );
 
218
        pair->kerning.x = afm_atoi( &q, limit );
 
219
 
 
220
        pair->kerning.y = 0;
 
221
        if ( p[2] != 'X' )
 
222
          pair->kerning.y = afm_atoi( &q, limit );
 
223
 
 
224
        pair++;
 
225
      }
 
226
    }
 
227
 
 
228
    /* now, sort the kern pairs according to their glyph indices */
 
229
    ft_qsort( afm->kern_pairs, count, sizeof ( T1_Kern_Pair ),
 
230
              compare_kern_pairs );
 
231
 
 
232
  Exit:
 
233
    if ( error )
 
234
      FT_FREE( afm );
 
235
 
 
236
    FT_FRAME_EXIT();
 
237
 
 
238
    return error;
 
239
  }
 
240
 
 
241
 
 
242
  /* find the kerning for a given glyph pair */
 
243
  FT_LOCAL_DEF( void )
 
244
  T1_Get_Kerning( T1_AFM*     afm,
 
245
                  FT_UInt     glyph1,
 
246
                  FT_UInt     glyph2,
 
247
                  FT_Vector*  kerning )
 
248
  {
 
249
    T1_Kern_Pair  *min, *mid, *max;
 
250
    FT_ULong      idx = KERN_INDEX( glyph1, glyph2 );
 
251
 
 
252
 
 
253
    /* simple binary search */
 
254
    min = afm->kern_pairs;
 
255
    max = min + afm->num_pairs - 1;
 
256
 
 
257
    while ( min <= max )
 
258
    {
 
259
      FT_ULong  midi;
 
260
 
 
261
 
 
262
      mid  = min + ( max - min ) / 2;
 
263
      midi = KERN_INDEX( mid->glyph1, mid->glyph2 );
 
264
 
 
265
      if ( midi == idx )
 
266
      {
 
267
        *kerning = mid->kerning;
 
268
        return;
 
269
      }
 
270
 
 
271
      if ( midi < idx )
 
272
        min = mid + 1;
 
273
      else
 
274
        max = mid - 1;
 
275
    }
 
276
 
 
277
    kerning->x = 0;
 
278
    kerning->y = 0;
 
279
  }
 
280
 
 
281
 
 
282
/* END */