00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <ft2build.h>
00020 #include "t1afm.h"
00021 #include "t1errors.h"
00022 #include FT_INTERNAL_STREAM_H
00023 #include FT_INTERNAL_POSTSCRIPT_AUX_H
00024
00025
00026
00027
00028
00029
00030
00031
00032 #undef FT_COMPONENT
00033 #define FT_COMPONENT trace_t1afm
00034
00035
00036 FT_LOCAL_DEF( void )
00037 T1_Done_Metrics( FT_Memory memory,
00038 AFM_FontInfo fi )
00039 {
00040 FT_FREE( fi->KernPairs );
00041 fi->NumKernPair = 0;
00042
00043 FT_FREE( fi->TrackKerns );
00044 fi->NumTrackKern = 0;
00045
00046 FT_FREE( fi );
00047 }
00048
00049
00050
00051 static FT_Int
00052 t1_get_index( const char* name,
00053 FT_Offset len,
00054 void* user_data )
00055 {
00056 T1_Font type1 = (T1_Font)user_data;
00057 FT_Int n;
00058
00059
00060
00061 if ( len > 0xFFFFU )
00062 return 0;
00063
00064 for ( n = 0; n < type1->num_glyphs; n++ )
00065 {
00066 char* gname = (char*)type1->glyph_names[n];
00067
00068
00069 if ( gname && gname[0] == name[0] &&
00070 ft_strlen( gname ) == len &&
00071 ft_strncmp( gname, name, len ) == 0 )
00072 return n;
00073 }
00074
00075 return 0;
00076 }
00077
00078
00079 #undef KERN_INDEX
00080 #define KERN_INDEX( g1, g2 ) ( ( (FT_ULong)(g1) << 16 ) | (g2) )
00081
00082
00083
00084 FT_CALLBACK_DEF( int )
00085 compare_kern_pairs( const void* a,
00086 const void* b )
00087 {
00088 AFM_KernPair pair1 = (AFM_KernPair)a;
00089 AFM_KernPair pair2 = (AFM_KernPair)b;
00090
00091 FT_ULong index1 = KERN_INDEX( pair1->index1, pair1->index2 );
00092 FT_ULong index2 = KERN_INDEX( pair2->index1, pair2->index2 );
00093
00094
00095 if ( index1 > index2 )
00096 return 1;
00097 else if ( index1 < index2 )
00098 return -1;
00099 else
00100 return 0;
00101 }
00102
00103
00104
00105 static FT_Error
00106 T1_Read_PFM( FT_Face t1_face,
00107 FT_Stream stream,
00108 AFM_FontInfo fi )
00109 {
00110 FT_Error error = T1_Err_Ok;
00111 FT_Memory memory = stream->memory;
00112 FT_Byte* start;
00113 FT_Byte* limit;
00114 FT_Byte* p;
00115 AFM_KernPair kp;
00116 FT_Int width_table_length;
00117 FT_CharMap oldcharmap;
00118 FT_CharMap charmap;
00119 FT_Int n;
00120
00121
00122 start = (FT_Byte*)stream->cursor;
00123 limit = (FT_Byte*)stream->limit;
00124 p = start;
00125
00126
00127
00128 p = start + 99;
00129 if ( p + 2 > limit )
00130 {
00131 error = T1_Err_Unknown_File_Format;
00132 goto Exit;
00133 }
00134 width_table_length = FT_PEEK_USHORT_LE( p );
00135
00136 p += 18 + width_table_length;
00137 if ( p + 0x12 > limit || FT_PEEK_USHORT_LE( p ) < 0x12 )
00138
00139 goto Exit;
00140
00141
00142 p += 14;
00143 p = start + FT_PEEK_ULONG_LE( p );
00144
00145 if ( p == start )
00146
00147 goto Exit;
00148
00149 if ( p + 2 > limit )
00150 {
00151 error = T1_Err_Unknown_File_Format;
00152 goto Exit;
00153 }
00154
00155 fi->NumKernPair = FT_PEEK_USHORT_LE( p );
00156 p += 2;
00157 if ( p + 4 * fi->NumKernPair > limit )
00158 {
00159 error = T1_Err_Unknown_File_Format;
00160 goto Exit;
00161 }
00162
00163
00164 if ( fi->NumKernPair == 0 )
00165 goto Exit;
00166
00167
00168 if ( FT_QNEW_ARRAY( fi->KernPairs, fi->NumKernPair ) )
00169 goto Exit;
00170
00171
00172 kp = fi->KernPairs;
00173 limit = p + 4 * fi->NumKernPair;
00174
00175
00176
00177
00178
00179 oldcharmap = t1_face->charmap;
00180 charmap = NULL;
00181
00182 for ( n = 0; n < t1_face->num_charmaps; n++ )
00183 {
00184 charmap = t1_face->charmaps[n];
00185
00186 if ( charmap->platform_id == 7 )
00187 {
00188 error = FT_Set_Charmap( t1_face, charmap );
00189 if ( error )
00190 goto Exit;
00191 break;
00192 }
00193 }
00194
00195
00196
00197
00198
00199
00200 for ( ; p < limit ; p += 4 )
00201 {
00202 kp->index1 = FT_Get_Char_Index( t1_face, p[0] );
00203 kp->index2 = FT_Get_Char_Index( t1_face, p[1] );
00204
00205 kp->x = (FT_Int)FT_PEEK_SHORT_LE(p + 2);
00206 kp->y = 0;
00207
00208 kp++;
00209 }
00210
00211 if ( oldcharmap != NULL )
00212 error = FT_Set_Charmap( t1_face, oldcharmap );
00213 if ( error )
00214 goto Exit;
00215
00216
00217 ft_qsort( fi->KernPairs, fi->NumKernPair, sizeof ( AFM_KernPairRec ),
00218 compare_kern_pairs );
00219
00220 Exit:
00221 if ( error )
00222 {
00223 FT_FREE( fi->KernPairs );
00224 fi->NumKernPair = 0;
00225 }
00226
00227 return error;
00228 }
00229
00230
00231
00232
00233 FT_LOCAL_DEF( FT_Error )
00234 T1_Read_Metrics( FT_Face t1_face,
00235 FT_Stream stream )
00236 {
00237 PSAux_Service psaux;
00238 FT_Memory memory = stream->memory;
00239 AFM_ParserRec parser;
00240 AFM_FontInfo fi;
00241 FT_Error error = T1_Err_Unknown_File_Format;
00242 T1_Font t1_font = &( (T1_Face)t1_face )->type1;
00243
00244
00245 if ( FT_NEW( fi ) ||
00246 FT_FRAME_ENTER( stream->size ) )
00247 goto Exit;
00248
00249 fi->FontBBox = t1_font->font_bbox;
00250 fi->Ascender = t1_font->font_bbox.yMax;
00251 fi->Descender = t1_font->font_bbox.yMin;
00252
00253 psaux = (PSAux_Service)( (T1_Face)t1_face )->psaux;
00254 if ( psaux && psaux->afm_parser_funcs )
00255 {
00256 error = psaux->afm_parser_funcs->init( &parser,
00257 stream->memory,
00258 stream->cursor,
00259 stream->limit );
00260
00261 if ( !error )
00262 {
00263 parser.FontInfo = fi;
00264 parser.get_index = t1_get_index;
00265 parser.user_data = t1_font;
00266
00267 error = psaux->afm_parser_funcs->parse( &parser );
00268 psaux->afm_parser_funcs->done( &parser );
00269 }
00270 }
00271
00272 if ( error == T1_Err_Unknown_File_Format )
00273 {
00274 FT_Byte* start = stream->cursor;
00275
00276
00277
00278 if ( stream->size > 6 &&
00279 start[1] < 4 &&
00280 FT_PEEK_ULONG_LE( start + 2 ) == stream->size )
00281 error = T1_Read_PFM( t1_face, stream, fi );
00282 }
00283
00284 if ( !error )
00285 {
00286 t1_font->font_bbox = fi->FontBBox;
00287
00288 t1_face->bbox.xMin = fi->FontBBox.xMin >> 16;
00289 t1_face->bbox.yMin = fi->FontBBox.yMin >> 16;
00290
00291 t1_face->bbox.xMax = ( fi->FontBBox.xMax + 0xFFFF ) >> 16;
00292 t1_face->bbox.yMax = ( fi->FontBBox.yMax + 0xFFFF ) >> 16;
00293
00294
00295 t1_face->ascender = (FT_Short)( ( fi->Ascender + 0x8000 ) >> 16 );
00296 t1_face->descender = (FT_Short)( ( fi->Descender + 0x8000 ) >> 16 );
00297
00298 if ( fi->NumKernPair )
00299 {
00300 t1_face->face_flags |= FT_FACE_FLAG_KERNING;
00301 ( (T1_Face)t1_face )->afm_data = fi;
00302 fi = NULL;
00303 }
00304 }
00305
00306 FT_FRAME_EXIT();
00307
00308 Exit:
00309 if ( fi != NULL )
00310 T1_Done_Metrics( memory, fi );
00311
00312 return error;
00313 }
00314
00315
00316
00317 FT_LOCAL_DEF( void )
00318 T1_Get_Kerning( AFM_FontInfo fi,
00319 FT_UInt glyph1,
00320 FT_UInt glyph2,
00321 FT_Vector* kerning )
00322 {
00323 AFM_KernPair min, mid, max;
00324 FT_ULong idx = KERN_INDEX( glyph1, glyph2 );
00325
00326
00327
00328 min = fi->KernPairs;
00329 max = min + fi->NumKernPair - 1;
00330
00331 while ( min <= max )
00332 {
00333 FT_ULong midi;
00334
00335
00336 mid = min + ( max - min ) / 2;
00337 midi = KERN_INDEX( mid->index1, mid->index2 );
00338
00339 if ( midi == idx )
00340 {
00341 kerning->x = mid->x;
00342 kerning->y = mid->y;
00343
00344 return;
00345 }
00346
00347 if ( midi < idx )
00348 min = mid + 1;
00349 else
00350 max = mid - 1;
00351 }
00352
00353 kerning->x = 0;
00354 kerning->y = 0;
00355 }
00356
00357
00358 FT_LOCAL_DEF( FT_Error )
00359 T1_Get_Track_Kerning( FT_Face face,
00360 FT_Fixed ptsize,
00361 FT_Int degree,
00362 FT_Fixed* kerning )
00363 {
00364 AFM_FontInfo fi = (AFM_FontInfo)( (T1_Face)face )->afm_data;
00365 FT_Int i;
00366
00367
00368 if ( !fi )
00369 return T1_Err_Invalid_Argument;
00370
00371 for ( i = 0; i < fi->NumTrackKern; i++ )
00372 {
00373 AFM_TrackKern tk = fi->TrackKerns + i;
00374
00375
00376 if ( tk->degree != degree )
00377 continue;
00378
00379 if ( ptsize < tk->min_ptsize )
00380 *kerning = tk->min_kern;
00381 else if ( ptsize > tk->max_ptsize )
00382 *kerning = tk->max_kern;
00383 else
00384 {
00385 *kerning = FT_MulDiv( ptsize - tk->min_ptsize,
00386 tk->max_kern - tk->min_kern,
00387 tk->max_ptsize - tk->min_ptsize ) +
00388 tk->min_kern;
00389 }
00390 }
00391
00392 return T1_Err_Ok;
00393 }
00394
00395
00396