]>
git.saurik.com Git - wxWidgets.git/blob - src/freetype/type1z/z1afm.c
1 /***************************************************************************/
5 /* AFM support for Type 1 fonts (body). */
7 /* Copyright 1996-2000 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
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. */
16 /***************************************************************************/
19 #ifdef FT_FLAT_COMPILE
25 #include <type1z/z1afm.h>
30 #include <freetype/internal/ftstream.h>
31 #include <freetype/internal/t1types.h>
33 #include <stdlib.h> /* for qsort() */
34 #include <string.h> /* for strcmp() */
35 #include <ctype.h> /* for isalnum() */
38 /*************************************************************************/
40 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
41 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
42 /* messages during execution. */
45 #define FT_COMPONENT trace_z1afm
49 void Z1_Done_AFM( FT_Memory memory
,
52 FREE( afm
->kern_pairs
);
58 #define IS_KERN_PAIR( p ) ( p[0] == 'K' && p[1] == 'P' )
60 #define IS_ALPHANUM( c ) ( isalnum( c ) || \
65 /* read a glyph name and return the equivalent glyph index */
67 FT_UInt
afm_atoindex( FT_Byte
** start
,
78 while ( ( *p
== ' ' || *p
== '\t' || *p
== ':' || *p
== ';' ) &&
83 /* now, read glyph name */
84 while ( IS_ALPHANUM( *p
) && p
< limit
)
89 if ( len
> 0 && len
< 64 )
94 /* copy glyph name to intermediate array */
95 MEM_Copy( temp
, *start
, len
);
98 /* lookup glyph name in face array */
99 for ( n
= 0; n
< type1
->num_glyphs
; n
++ )
101 char* gname
= (char*)type1
->glyph_names
[n
];
104 if ( gname
&& gname
[0] == temp
[0] && strcmp( gname
, temp
) == 0 )
116 /* read an integer */
118 int afm_atoi( FT_Byte
** start
,
126 /* skip everything that is not a number */
127 while ( p
< limit
&& !isdigit( *p
) )
136 while ( p
< limit
&& isdigit( *p
) )
138 sum
= sum
* 10 + ( *p
- '0' );
148 #define KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 )
151 /* compare two kerning pairs */
153 int compare_kern_pairs( const void* a
,
156 Z1_Kern_Pair
* pair1
= (Z1_Kern_Pair
*)a
;
157 Z1_Kern_Pair
* pair2
= (Z1_Kern_Pair
*)b
;
159 FT_ULong index1
= KERN_INDEX( pair1
->glyph1
, pair1
->glyph2
);
160 FT_ULong index2
= KERN_INDEX( pair2
->glyph1
, pair2
->glyph2
);
163 return ( index1
- index2
);
167 /* parse an AFM file -- for now, only read the kerning pairs */
169 FT_Error
Z1_Read_AFM( FT_Face t1_face
,
173 FT_Memory memory
= stream
->memory
;
179 T1_Font
* type1
= &((T1_Face
)t1_face
)->type1
;
183 if ( ACCESS_Frame( stream
->size
) )
186 start
= (FT_Byte
*)stream
->cursor
;
187 limit
= (FT_Byte
*)stream
->limit
;
190 /* we are now going to count the occurences of `KP' or `KPX' in */
193 for ( p
= start
; p
< limit
- 3; p
++ )
195 if ( IS_KERN_PAIR( p
) )
199 /* Actually, kerning pairs are simply optional! */
203 /* allocate the pairs */
204 if ( ALLOC( afm
, sizeof ( *afm
) ) ||
205 ALLOC_ARRAY( afm
->kern_pairs
, count
, Z1_Kern_Pair
) )
208 /* now, read each kern pair */
209 pair
= afm
->kern_pairs
;
210 afm
->num_pairs
= count
;
212 /* save in face object */
213 ((T1_Face
)t1_face
)->afm_data
= afm
;
215 for ( p
= start
; p
< limit
- 3; p
++ )
217 if ( IS_KERN_PAIR( p
) )
222 /* skip keyword (KP or KPX) */
227 pair
->glyph1
= afm_atoindex( &q
, limit
, type1
);
228 pair
->glyph2
= afm_atoindex( &q
, limit
, type1
);
229 pair
->kerning
.x
= afm_atoi( &q
, limit
);
233 pair
->kerning
.y
= afm_atoi( &q
, limit
);
239 /* now, sort the kern pairs according to their glyph indices */
240 qsort( afm
->kern_pairs
, count
, sizeof ( Z1_Kern_Pair
),
241 compare_kern_pairs
);
253 /* find the kerning for a given glyph pair */
255 void Z1_Get_Kerning( Z1_AFM
* afm
,
260 Z1_Kern_Pair
*min
, *mid
, *max
;
261 FT_ULong index
= KERN_INDEX( glyph1
, glyph2
);
264 /* simple binary search */
265 min
= afm
->kern_pairs
;
266 max
= min
+ afm
->num_pairs
- 1;
273 mid
= min
+ ( max
- min
) / 2;
274 midi
= KERN_INDEX( mid
->glyph1
, mid
->glyph2
);
278 *kerning
= mid
->kerning
;