📄 afmparse.c
字号:
AFM_STATUS_EOC( stream ) ) continue; break; } } if ( len ) *len = ( key ) ? AFM_STREAM_KEY_LEN( stream, key ) : 0; return key; } static AFM_Token afm_tokenize( const char* key, FT_UInt len ) { int n; for ( n = 0; n < N_AFM_TOKENS; n++ ) { if ( *( afm_key_table[n] ) == *key ) { for ( ; n < N_AFM_TOKENS; n++ ) { if ( *( afm_key_table[n] ) != *key ) return AFM_TOKEN_UNKNOWN; if ( ft_strncmp( afm_key_table[n], key, len ) == 0 ) return (AFM_Token) n; } } } return AFM_TOKEN_UNKNOWN; } FT_LOCAL_DEF( FT_Error ) afm_parser_init( AFM_Parser parser, FT_Memory memory, FT_Byte* base, FT_Byte* limit ) { AFM_Stream stream; FT_Error error; if ( FT_NEW( stream ) ) return error; stream->cursor = stream->base = base; stream->limit = limit; /* don't skip the first line during the first call */ stream->status = AFM_STREAM_STATUS_EOL; parser->memory = memory; parser->stream = stream; parser->FontInfo = NULL; parser->get_index = NULL; return PSaux_Err_Ok; } FT_LOCAL( void ) afm_parser_done( AFM_Parser parser ) { FT_Memory memory = parser->memory; FT_FREE( parser->stream ); } FT_LOCAL_DEF( FT_Error ) afm_parser_read_int( AFM_Parser parser, FT_Int* aint ) { AFM_ValueRec val; val.type = AFM_VALUE_TYPE_INTEGER; if ( afm_parser_read_vals( parser, &val, 1 ) == 1 ) { *aint = val.u.i; return PSaux_Err_Ok; } else return PSaux_Err_Syntax_Error; } static FT_Error afm_parse_track_kern( AFM_Parser parser ) { AFM_FontInfo fi = parser->FontInfo; AFM_TrackKern tk; char* key; FT_UInt len; int n = -1; if ( afm_parser_read_int( parser, &fi->NumTrackKern ) ) goto Fail; if ( fi->NumTrackKern ) { FT_Memory memory = parser->memory; FT_Error error; if ( FT_QNEW_ARRAY( fi->TrackKerns, fi->NumTrackKern ) ) return error; } while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) { AFM_ValueRec shared_vals[5]; switch ( afm_tokenize( key, len ) ) { case AFM_TOKEN_TRACKKERN: n++; if ( n >= fi->NumTrackKern ) goto Fail; tk = fi->TrackKerns + n; shared_vals[0].type = AFM_VALUE_TYPE_INTEGER; shared_vals[1].type = AFM_VALUE_TYPE_FIXED; shared_vals[2].type = AFM_VALUE_TYPE_FIXED; shared_vals[3].type = AFM_VALUE_TYPE_FIXED; shared_vals[4].type = AFM_VALUE_TYPE_FIXED; if ( afm_parser_read_vals( parser, shared_vals, 5 ) != 5 ) goto Fail; tk->degree = shared_vals[0].u.i; tk->min_ptsize = shared_vals[1].u.f; tk->min_kern = shared_vals[2].u.f; tk->max_ptsize = shared_vals[3].u.f; tk->max_kern = shared_vals[4].u.f; /* is this correct? */ if ( tk->degree < 0 && tk->min_kern > 0 ) tk->min_kern = -tk->min_kern; break; case AFM_TOKEN_ENDTRACKKERN: case AFM_TOKEN_ENDKERNDATA: case AFM_TOKEN_ENDFONTMETRICS: fi->NumTrackKern = n + 1; return PSaux_Err_Ok; break; case AFM_TOKEN_UNKNOWN: break; default: goto Fail; break; } } Fail: return PSaux_Err_Syntax_Error; }#undef KERN_INDEX#define KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 ) /* compare two kerning pairs */ FT_CALLBACK_DEF( int ) afm_compare_kern_pairs( const void* a, const void* b ) { AFM_KernPair kp1 = (AFM_KernPair)a; AFM_KernPair kp2 = (AFM_KernPair)b; FT_ULong index1 = KERN_INDEX( kp1->index1, kp1->index2 ); FT_ULong index2 = KERN_INDEX( kp2->index1, kp2->index2 ); return (int)( index1 - index2 ); } static FT_Error afm_parse_kern_pairs( AFM_Parser parser ) { AFM_FontInfo fi = parser->FontInfo; AFM_KernPair kp; char* key; FT_UInt len; int n = -1; if ( afm_parser_read_int( parser, &fi->NumKernPair ) ) goto Fail; if ( fi->NumKernPair ) { FT_Memory memory = parser->memory; FT_Error error; if ( FT_QNEW_ARRAY( fi->KernPairs, fi->NumKernPair ) ) return error; } while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) { AFM_Token token = afm_tokenize( key, len ); switch ( token ) { case AFM_TOKEN_KP: case AFM_TOKEN_KPX: case AFM_TOKEN_KPY: { FT_Int r; AFM_ValueRec shared_vals[4]; n++; if ( n >= fi->NumKernPair ) goto Fail; kp = fi->KernPairs + n; shared_vals[0].type = AFM_VALUE_TYPE_INDEX; shared_vals[1].type = AFM_VALUE_TYPE_INDEX; shared_vals[2].type = AFM_VALUE_TYPE_INTEGER; shared_vals[3].type = AFM_VALUE_TYPE_INTEGER; r = afm_parser_read_vals( parser, shared_vals, 4 ); if ( r < 3 ) goto Fail; kp->index1 = shared_vals[0].u.i; kp->index2 = shared_vals[1].u.i; if ( token == AFM_TOKEN_KPY ) { kp->x = 0; kp->y = shared_vals[2].u.i; } else { kp->x = shared_vals[2].u.i; kp->y = ( token == AFM_TOKEN_KP && r == 4 ) ? shared_vals[3].u.i : 0; } } break; case AFM_TOKEN_ENDKERNPAIRS: case AFM_TOKEN_ENDKERNDATA: case AFM_TOKEN_ENDFONTMETRICS: fi->NumKernPair = n + 1; ft_qsort( fi->KernPairs, fi->NumKernPair, sizeof( AFM_KernPairRec ), afm_compare_kern_pairs ); return PSaux_Err_Ok; case AFM_TOKEN_UNKNOWN: break; default: goto Fail; break; } } Fail: return PSaux_Err_Syntax_Error; } static FT_Error afm_parse_kern_data( AFM_Parser parser ) { FT_Error error; char* key; FT_UInt len; while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) { switch ( afm_tokenize( key, len ) ) { case AFM_TOKEN_STARTTRACKKERN: error = afm_parse_track_kern( parser ); if ( error ) return error; break; case AFM_TOKEN_STARTKERNPAIRS: case AFM_TOKEN_STARTKERNPAIRS0: error = afm_parse_kern_pairs( parser ); if ( error ) return error; break; case AFM_TOKEN_ENDKERNDATA: case AFM_TOKEN_ENDFONTMETRICS: return PSaux_Err_Ok; case AFM_TOKEN_UNKNOWN: break; default: goto Fail; break; } } Fail: return PSaux_Err_Syntax_Error; } static FT_Error afm_parser_skip_section( AFM_Parser parser, FT_UInt n, AFM_Token end_section ) { char* key; FT_UInt len; while ( n-- > 0 ) { key = afm_parser_next_key( parser, 1, NULL ); if ( !key ) goto Fail; } while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) { AFM_Token token = afm_tokenize( key, len ); if ( token == end_section || token == AFM_TOKEN_ENDFONTMETRICS ) return PSaux_Err_Ok; } Fail: return PSaux_Err_Syntax_Error; } FT_LOCAL_DEF( FT_Error ) afm_parser_parse( AFM_Parser parser ) { FT_Memory memory = parser->memory; AFM_FontInfo fi = parser->FontInfo; FT_Error error = PSaux_Err_Syntax_Error; char* key; FT_UInt len; FT_Int metrics_sets = 0; if ( !fi ) return PSaux_Err_Invalid_Argument; key = afm_parser_next_key( parser, 1, &len ); if ( !key || len != 16 || ft_strncmp( key, "StartFontMetrics", 16 ) != 0 ) return PSaux_Err_Unknown_File_Format; while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) { AFM_ValueRec shared_vals[4]; switch ( afm_tokenize( key, len ) ) { case AFM_TOKEN_METRICSSETS: if ( afm_parser_read_int( parser, &metrics_sets ) ) goto Fail; if ( metrics_sets != 0 && metrics_sets != 2 ) { error = PSaux_Err_Unimplemented_Feature; goto Fail; } break; case AFM_TOKEN_ISCIDFONT: shared_vals[0].type = AFM_VALUE_TYPE_BOOL; if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 ) goto Fail; fi->IsCIDFont = shared_vals[0].u.b; break; case AFM_TOKEN_FONTBBOX: shared_vals[0].type = AFM_VALUE_TYPE_FIXED; shared_vals[1].type = AFM_VALUE_TYPE_FIXED; shared_vals[2].type = AFM_VALUE_TYPE_FIXED; shared_vals[3].type = AFM_VALUE_TYPE_FIXED; if ( afm_parser_read_vals( parser, shared_vals, 4 ) != 4 ) goto Fail; fi->FontBBox.xMin = shared_vals[0].u.f; fi->FontBBox.yMin = shared_vals[1].u.f; fi->FontBBox.xMax = shared_vals[2].u.f; fi->FontBBox.yMax = shared_vals[3].u.f; break; case AFM_TOKEN_ASCENDER: shared_vals[0].type = AFM_VALUE_TYPE_FIXED; if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 ) goto Fail; fi->Ascender = shared_vals[0].u.f; break; case AFM_TOKEN_DESCENDER: shared_vals[0].type = AFM_VALUE_TYPE_FIXED; if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 ) goto Fail; fi->Descender = shared_vals[0].u.f; break; case AFM_TOKEN_STARTCHARMETRICS: { FT_Int n; if ( afm_parser_read_int( parser, &n ) ) goto Fail; error = afm_parser_skip_section( parser, n, AFM_TOKEN_ENDCHARMETRICS ); if ( error ) return error; } break; case AFM_TOKEN_STARTKERNDATA: error = afm_parse_kern_data( parser ); if ( error ) goto Fail; /* fall through since we only support kern data */ case AFM_TOKEN_ENDFONTMETRICS: return PSaux_Err_Ok; break; default: break; } } Fail: FT_FREE( fi->TrackKerns ); fi->NumTrackKern = 0; FT_FREE( fi->KernPairs ); fi->NumKernPair = 0; fi->IsCIDFont = 0; return error; }/* END */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -