26#ifndef T1_CONFIG_OPTION_NO_AFM
35#define FT_COMPONENT t1afm
39 T1_Done_Metrics( FT_Memory memory,
42 FT_FREE( fi->KernPairs );
45 FT_FREE( fi->TrackKerns );
54 t1_get_index(
const char* name,
58 T1_Font type1 = (T1_Font)user_data;
66 for ( n = 0; n < type1->num_glyphs; n++ )
68 char* gname = (
char*)type1->glyph_names[n];
71 if ( gname && gname[0] == name[0] &&
72 ft_strlen( gname ) == len &&
73 ft_strncmp( gname, name, len ) == 0 )
82#define KERN_INDEX( g1, g2 ) ( ( (FT_ULong)(g1) << 16 ) | (g2) )
87 compare_kern_pairs(
const void* a,
90 AFM_KernPair pair1 = (AFM_KernPair)a;
91 AFM_KernPair pair2 = (AFM_KernPair)b;
93 FT_ULong index1 = KERN_INDEX( pair1->index1, pair1->index2 );
94 FT_ULong index2 = KERN_INDEX( pair2->index1, pair2->index2 );
97 if ( index1 > index2 )
99 else if ( index1 < index2 )
108 T1_Read_PFM( FT_Face t1_face,
112 FT_Error error = FT_Err_Ok;
113 FT_Memory memory = stream->memory;
118 FT_Int width_table_length;
119 FT_CharMap oldcharmap;
124 start = (FT_Byte*)stream->cursor;
125 limit = (FT_Byte*)stream->limit;
132 error = FT_THROW( Unknown_File_Format );
135 width_table_length = FT_PEEK_USHORT_LE( p );
137 p += 18 + width_table_length;
138 if ( p + 0x12 > limit || FT_PEEK_USHORT_LE( p ) < 0x12 )
144 p = start + FT_PEEK_ULONG_LE( p );
152 error = FT_THROW( Unknown_File_Format );
156 fi->NumKernPair = FT_PEEK_USHORT_LE( p );
158 if ( p + 4 * fi->NumKernPair > limit )
160 error = FT_THROW( Unknown_File_Format );
165 if ( fi->NumKernPair == 0 )
169 if ( FT_QNEW_ARRAY( fi->KernPairs, fi->NumKernPair ) )
174 limit = p + 4 * fi->NumKernPair;
180 oldcharmap = t1_face->charmap;
182 for ( n = 0; n < t1_face->num_charmaps; n++ )
184 charmap = t1_face->charmaps[n];
186 if ( charmap->platform_id == 7 )
188 t1_face->charmap = charmap;
198 for ( ; p < limit; p += 4 )
200 kp->index1 = FT_Get_Char_Index( t1_face, p[0] );
201 kp->index2 = FT_Get_Char_Index( t1_face, p[1] );
203 kp->x = (FT_Int)FT_PEEK_SHORT_LE( p + 2 );
209 t1_face->charmap = oldcharmap;
212 ft_qsort( fi->KernPairs, fi->NumKernPair, sizeof ( AFM_KernPairRec ),
213 compare_kern_pairs );
218 FT_FREE( fi->KernPairs );
228 FT_LOCAL_DEF( FT_Error )
229 T1_Read_Metrics( FT_Face t1_face,
233 FT_Memory memory = stream->memory;
234 AFM_ParserRec parser;
235 AFM_FontInfo fi = NULL;
236 FT_Error error = FT_ERR( Unknown_File_Format );
237 T1_Face face = (T1_Face)t1_face;
238 T1_Font t1_font = &face->type1;
241 if ( face->afm_data )
243 FT_TRACE1((
"T1_Read_Metrics:"
244 " Freeing previously attached metrics data.\n" ));
245 T1_Done_Metrics( memory, (AFM_FontInfo)face->afm_data );
247 face->afm_data = NULL;
251 FT_FRAME_ENTER( stream->size ) )
254 fi->FontBBox = t1_font->font_bbox;
255 fi->Ascender = t1_font->font_bbox.yMax;
256 fi->Descender = t1_font->font_bbox.yMin;
258 psaux = (PSAux_Service)face->psaux;
259 if ( psaux->afm_parser_funcs )
261 error = psaux->afm_parser_funcs->init( &parser,
268 parser.FontInfo = fi;
269 parser.get_index = t1_get_index;
270 parser.user_data = t1_font;
272 error = psaux->afm_parser_funcs->parse( &parser );
273 psaux->afm_parser_funcs->done( &parser );
277 if ( FT_ERR_EQ( error, Unknown_File_Format ) )
279 FT_Byte* start = stream->cursor;
283 if ( stream->size > 6 &&
285 FT_PEEK_ULONG_LE( start + 2 ) == stream->size )
286 error = T1_Read_PFM( t1_face, stream, fi );
291 t1_font->font_bbox = fi->FontBBox;
293 t1_face->bbox.xMin = fi->FontBBox.xMin >> 16;
294 t1_face->bbox.yMin = fi->FontBBox.yMin >> 16;
296 t1_face->bbox.xMax = ( fi->FontBBox.xMax + 0xFFFF ) >> 16;
297 t1_face->bbox.yMax = ( fi->FontBBox.yMax + 0xFFFF ) >> 16;
301 if ( fi->Ascender > fi->Descender )
304 t1_face->ascender = (FT_Short)( ( fi->Ascender + 0x8000 ) >> 16 );
305 t1_face->descender = (FT_Short)( ( fi->Descender + 0x8000 ) >> 16 );
308 if ( fi->NumKernPair )
310 t1_face->face_flags |= FT_FACE_FLAG_KERNING;
320 T1_Done_Metrics( memory, fi );
328 T1_Get_Kerning( AFM_FontInfo fi,
333 AFM_KernPair min, mid, max;
334 FT_ULong idx = KERN_INDEX( glyph1, glyph2 );
339 max = min + fi->NumKernPair - 1;
346 mid = min + ( max - min ) / 2;
347 midi = KERN_INDEX( mid->index1, mid->index2 );
368 FT_LOCAL_DEF( FT_Error )
369 T1_Get_Track_Kerning( FT_Face face,
374 AFM_FontInfo fi = (AFM_FontInfo)( (T1_Face)face )->afm_data;
379 return FT_THROW( Invalid_Argument );
381 for ( i = 0; i < fi->NumTrackKern; i++ )
383 AFM_TrackKern tk = fi->TrackKerns + i;
386 if ( tk->degree != degree )
389 if ( ptsize < tk->min_ptsize )
390 *kerning = tk->min_kern;
391 else if ( ptsize > tk->max_ptsize )
392 *kerning = tk->max_kern;
395 *kerning = FT_MulDiv( ptsize - tk->min_ptsize,
396 tk->max_kern - tk->min_kern,
397 tk->max_ptsize - tk->min_ptsize ) +
408 typedef int t1_afm_dummy_;