22#ifndef T1_CONFIG_OPTION_NO_AFM
37#define FT_COMPONENT afmparse
50 AFM_STREAM_STATUS_NORMAL,
51 AFM_STREAM_STATUS_EOC,
52 AFM_STREAM_STATUS_EOL,
74#define AFM_IS_NEWLINE( ch ) ( (ch) == '\r' || (ch) == '\n' )
76#define AFM_IS_EOF( ch ) ( (ch) == EOF || (ch) == '\x1a' )
77#define AFM_IS_SPACE( ch ) ( (ch) == ' ' || (ch) == '\t' )
80#define AFM_IS_SEP( ch ) ( (ch) == ';' )
83 ( ( (stream)->cursor < (stream)->limit ) ? *(stream)->cursor++ \
86#define AFM_STREAM_KEY_BEGIN( stream ) \
87 (char*)( (stream)->cursor - 1 )
89#define AFM_STREAM_KEY_LEN( stream, key ) \
90 (FT_Offset)( (char*)(stream)->cursor - key - 1 )
92#define AFM_STATUS_EOC( stream ) \
93 ( (stream)->status >= AFM_STREAM_STATUS_EOC )
95#define AFM_STATUS_EOL( stream ) \
96 ( (stream)->status >= AFM_STREAM_STATUS_EOL )
98#define AFM_STATUS_EOF( stream ) \
99 ( (stream)->status >= AFM_STREAM_STATUS_EOF )
103 afm_stream_skip_spaces( AFM_Stream stream )
108 if ( AFM_STATUS_EOC( stream ) )
114 if ( !AFM_IS_SPACE( ch ) )
118 if ( AFM_IS_NEWLINE( ch ) )
119 stream->status = AFM_STREAM_STATUS_EOL;
120 else if ( AFM_IS_SEP( ch ) )
121 stream->status = AFM_STREAM_STATUS_EOC;
122 else if ( AFM_IS_EOF( ch ) )
123 stream->status = AFM_STREAM_STATUS_EOF;
131 afm_stream_read_one( AFM_Stream stream )
136 afm_stream_skip_spaces( stream );
137 if ( AFM_STATUS_EOC( stream ) )
140 str = AFM_STREAM_KEY_BEGIN( stream );
147 if ( AFM_IS_SPACE( ch ) )
149 else if ( AFM_IS_NEWLINE( ch ) )
151 stream->status = AFM_STREAM_STATUS_EOL;
154 else if ( AFM_IS_SEP( ch ) )
156 stream->status = AFM_STREAM_STATUS_EOC;
159 else if ( AFM_IS_EOF( ch ) )
161 stream->status = AFM_STREAM_STATUS_EOF;
172 afm_stream_read_string( AFM_Stream stream )
177 afm_stream_skip_spaces( stream );
178 if ( AFM_STATUS_EOL( stream ) )
181 str = AFM_STREAM_KEY_BEGIN( stream );
189 if ( AFM_IS_NEWLINE( ch ) )
191 stream->status = AFM_STREAM_STATUS_EOL;
194 else if ( AFM_IS_EOF( ch ) )
196 stream->status = AFM_STREAM_STATUS_EOF;
212 typedef enum AFM_Token_
218 AFM_TOKEN_BLENDAXISTYPES,
219 AFM_TOKEN_BLENDDESIGNMAP,
220 AFM_TOKEN_BLENDDESIGNPOSITIONS,
226 AFM_TOKEN_CHARACTERSET,
227 AFM_TOKEN_CHARACTERS,
229 AFM_TOKEN_ENCODINGSCHEME,
231 AFM_TOKEN_ENDCHARMETRICS,
232 AFM_TOKEN_ENDCOMPOSITES,
233 AFM_TOKEN_ENDDIRECTION,
234 AFM_TOKEN_ENDFONTMETRICS,
235 AFM_TOKEN_ENDKERNDATA,
236 AFM_TOKEN_ENDKERNPAIRS,
237 AFM_TOKEN_ENDTRACKKERN,
239 AFM_TOKEN_FAMILYNAME,
243 AFM_TOKEN_ISBASEFONT,
245 AFM_TOKEN_ISFIXEDPITCH,
247 AFM_TOKEN_ITALICANGLE,
253 AFM_TOKEN_MAPPINGSCHEME,
254 AFM_TOKEN_METRICSSETS,
259 AFM_TOKEN_STARTCHARMETRICS,
260 AFM_TOKEN_STARTCOMPOSITES,
261 AFM_TOKEN_STARTDIRECTION,
262 AFM_TOKEN_STARTFONTMETRICS,
263 AFM_TOKEN_STARTKERNDATA,
264 AFM_TOKEN_STARTKERNPAIRS,
265 AFM_TOKEN_STARTKERNPAIRS0,
266 AFM_TOKEN_STARTKERNPAIRS1,
267 AFM_TOKEN_STARTTRACKKERN,
271 AFM_TOKEN_UNDERLINEPOSITION,
272 AFM_TOKEN_UNDERLINETHICKNESS,
286 AFM_TOKEN_WEIGHTVECTOR,
294 static const char*
const afm_key_table[N_AFM_TOKENS] =
302 "BlendDesignPositions",
354 "UnderlineThickness",
380 FT_LOCAL_DEF( FT_Int )
381 afm_parser_read_vals( AFM_Parser parser,
385 AFM_Stream stream = parser->stream;
390 if ( n > AFM_MAX_ARGUMENTS )
393 for ( i = 0; i < n; i++ )
396 AFM_Value val = vals + i;
399 if ( val->type == AFM_VALUE_TYPE_STRING )
400 str = afm_stream_read_string( stream );
402 str = afm_stream_read_one( stream );
407 len = AFM_STREAM_KEY_LEN( stream, str );
411 case AFM_VALUE_TYPE_STRING:
412 case AFM_VALUE_TYPE_NAME:
414 FT_Memory memory = parser->memory;
418 if ( !FT_QALLOC( val->u.s, len + 1 ) )
420 ft_memcpy( val->u.s, str, len );
421 val->u.s[len] =
'\0';
426 case AFM_VALUE_TYPE_FIXED:
427 val->u.f = PS_Conv_ToFixed( (FT_Byte**)(
void*)&str,
428 (FT_Byte*)str + len, 0 );
431 case AFM_VALUE_TYPE_INTEGER:
432 val->u.i = PS_Conv_ToInt( (FT_Byte**)(
void*)&str,
433 (FT_Byte*)str + len );
436 case AFM_VALUE_TYPE_BOOL:
437 val->u.b = FT_BOOL( len == 4 &&
438 !ft_strncmp( str,
"true", 4 ) );
441 case AFM_VALUE_TYPE_INDEX:
442 if ( parser->get_index )
443 val->u.i = parser->get_index( str, len, parser->user_data );
454 FT_LOCAL_DEF(
char* )
455 afm_parser_next_key( AFM_Parser parser,
459 AFM_Stream stream = parser->stream;
468 if ( !AFM_STATUS_EOL( stream ) )
469 afm_stream_read_string( stream );
471 stream->status = AFM_STREAM_STATUS_NORMAL;
472 key = afm_stream_read_one( stream );
476 !AFM_STATUS_EOF( stream ) &&
477 AFM_STATUS_EOL( stream ) )
488 while ( !AFM_STATUS_EOC( stream ) )
489 afm_stream_read_one( stream );
491 stream->status = AFM_STREAM_STATUS_NORMAL;
492 key = afm_stream_read_one( stream );
496 !AFM_STATUS_EOF( stream ) &&
497 AFM_STATUS_EOC( stream ) )
505 *len = ( key ) ? (FT_Offset)AFM_STREAM_KEY_LEN( stream, key )
513 afm_tokenize(
const char* key,
519 for ( n = 0; n < N_AFM_TOKENS; n++ )
521 if ( *( afm_key_table[n] ) == *key )
523 for ( ; n < N_AFM_TOKENS; n++ )
525 if ( *( afm_key_table[n] ) != *key )
526 return AFM_TOKEN_UNKNOWN;
528 if ( ft_strncmp( afm_key_table[n], key, len ) == 0 )
529 return (AFM_Token) n;
534 return AFM_TOKEN_UNKNOWN;
538 FT_LOCAL_DEF( FT_Error )
539 afm_parser_init( AFM_Parser parser,
544 AFM_Stream stream = NULL;
548 if ( FT_NEW( stream ) )
551 stream->cursor = stream->base = base;
552 stream->limit = limit;
555 stream->status = AFM_STREAM_STATUS_EOL;
557 parser->memory = memory;
558 parser->stream = stream;
559 parser->FontInfo = NULL;
560 parser->get_index = NULL;
567 afm_parser_done( AFM_Parser parser )
569 FT_Memory memory = parser->memory;
572 FT_FREE( parser->stream );
577 afm_parser_read_int( AFM_Parser parser,
583 val.type = AFM_VALUE_TYPE_INTEGER;
585 if ( afm_parser_read_vals( parser, &val, 1 ) == 1 )
592 return FT_THROW( Syntax_Error );
597 afm_parse_track_kern( AFM_Parser parser )
599 AFM_FontInfo fi = parser->FontInfo;
600 AFM_Stream stream = parser->stream;
609 if ( afm_parser_read_int( parser, &tmp ) )
614 FT_ERROR((
"afm_parse_track_kern: invalid number of track kerns\n" ));
618 fi->NumTrackKern = (FT_UInt)tmp;
619 FT_TRACE3((
"afm_parse_track_kern: %u track kern%s expected\n",
621 fi->NumTrackKern == 1 ?
"" :
"s" ));
625 if ( (FT_ULong)( stream->limit - stream->cursor ) / 20 <
628 FT_ERROR((
"afm_parse_track_kern:"
629 " number of track kern entries exceeds stream size\n" ));
633 if ( fi->NumTrackKern )
635 FT_Memory memory = parser->memory;
639 if ( FT_QNEW_ARRAY( fi->TrackKerns, fi->NumTrackKern ) )
643 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
645 AFM_ValueRec shared_vals[5];
648 switch ( afm_tokenize( key, len ) )
650 case AFM_TOKEN_TRACKKERN:
653 if ( n >= (
int)fi->NumTrackKern )
655 FT_ERROR((
"afm_parse_track_kern: too many track kern data\n" ));
659 tk = fi->TrackKerns + n;
661 shared_vals[0].type = AFM_VALUE_TYPE_INTEGER;
662 shared_vals[1].type = AFM_VALUE_TYPE_FIXED;
663 shared_vals[2].type = AFM_VALUE_TYPE_FIXED;
664 shared_vals[3].type = AFM_VALUE_TYPE_FIXED;
665 shared_vals[4].type = AFM_VALUE_TYPE_FIXED;
666 if ( afm_parser_read_vals( parser, shared_vals, 5 ) != 5 )
668 FT_ERROR((
"afm_parse_track_kern:"
669 " insufficient number of parameters for entry %d\n",
674 tk->degree = shared_vals[0].u.i;
675 tk->min_ptsize = shared_vals[1].u.f;
676 tk->min_kern = shared_vals[2].u.f;
677 tk->max_ptsize = shared_vals[3].u.f;
678 tk->max_kern = shared_vals[4].u.f;
682 case AFM_TOKEN_ENDTRACKKERN:
683 case AFM_TOKEN_ENDKERNDATA:
684 case AFM_TOKEN_ENDFONTMETRICS:
686 if ( (FT_UInt)tmp != fi->NumTrackKern )
688 FT_TRACE1((
"afm_parse_track_kern: %s%d track kern entr%s seen\n",
689 tmp == 0 ?
"" :
"only ",
691 tmp == 1 ?
"y" :
"ies" ));
692 fi->NumTrackKern = (FT_UInt)tmp;
695 FT_TRACE3((
"afm_parse_track_kern: %d track kern entr%s seen\n",
697 tmp == 1 ?
"y" :
"ies" ));
700 case AFM_TOKEN_UNKNOWN:
709 return FT_THROW( Syntax_Error );
714#define KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 )
718 FT_COMPARE_DEF(
int )
719 afm_compare_kern_pairs(
const void* a,
722 AFM_KernPair kp1 = (AFM_KernPair)a;
723 AFM_KernPair kp2 = (AFM_KernPair)b;
725 FT_ULong index1 = KERN_INDEX( kp1->index1, kp1->index2 );
726 FT_ULong index2 = KERN_INDEX( kp2->index1, kp2->index2 );
729 if ( index1 > index2 )
731 else if ( index1 < index2 )
739 afm_parse_kern_pairs( AFM_Parser parser )
741 AFM_FontInfo fi = parser->FontInfo;
742 AFM_Stream stream = parser->stream;
750 if ( afm_parser_read_int( parser, &tmp ) )
755 FT_ERROR((
"afm_parse_kern_pairs: invalid number of kern pairs\n" ));
759 fi->NumKernPair = (FT_UInt)tmp;
760 FT_TRACE3((
"afm_parse_kern_pairs: %u kern pair%s expected\n",
762 fi->NumKernPair == 1 ?
"" :
"s" ));
767 if ( (FT_ULong)( stream->limit - stream->cursor ) / 10 <
770 FT_ERROR((
"afm_parse_kern_pairs:"
771 " number of kern pairs exceeds stream size\n" ));
775 if ( fi->NumKernPair )
777 FT_Memory memory = parser->memory;
781 if ( FT_QNEW_ARRAY( fi->KernPairs, fi->NumKernPair ) )
785 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
787 AFM_Token token = afm_tokenize( key, len );
797 AFM_ValueRec shared_vals[4];
802 if ( n >= (
int)fi->NumKernPair )
804 FT_ERROR((
"afm_parse_kern_pairs: too many kern pairs\n" ));
808 kp = fi->KernPairs + n;
810 shared_vals[0].type = AFM_VALUE_TYPE_INDEX;
811 shared_vals[1].type = AFM_VALUE_TYPE_INDEX;
812 shared_vals[2].type = AFM_VALUE_TYPE_INTEGER;
813 shared_vals[3].type = AFM_VALUE_TYPE_INTEGER;
814 r = afm_parser_read_vals( parser, shared_vals, 4 );
817 FT_ERROR((
"afm_parse_kern_pairs:"
818 " insufficient number of parameters for entry %d\n",
824 kp->index1 = shared_vals[0].u.u;
825 kp->index2 = shared_vals[1].u.u;
826 if ( token == AFM_TOKEN_KPY )
829 kp->y = shared_vals[2].u.i;
833 kp->x = shared_vals[2].u.i;
834 kp->y = ( token == AFM_TOKEN_KP && r == 4 )
835 ? shared_vals[3].u.i : 0;
840 case AFM_TOKEN_ENDKERNPAIRS:
841 case AFM_TOKEN_ENDKERNDATA:
842 case AFM_TOKEN_ENDFONTMETRICS:
844 if ( (FT_UInt)tmp != fi->NumKernPair )
846 FT_TRACE1((
"afm_parse_kern_pairs: %s%d kern pair%s seen\n",
847 tmp == 0 ?
"" :
"only ",
849 tmp == 1 ?
"" :
"s" ));
850 fi->NumKernPair = (FT_UInt)tmp;
853 FT_TRACE3((
"afm_parse_kern_pairs: %d kern pair%s seen\n",
855 tmp == 1 ?
"" :
"s" ));
857 ft_qsort( fi->KernPairs, fi->NumKernPair,
858 sizeof ( AFM_KernPairRec ),
859 afm_compare_kern_pairs );
862 case AFM_TOKEN_UNKNOWN:
871 return FT_THROW( Syntax_Error );
876 afm_parse_kern_data( AFM_Parser parser )
882 int have_trackkern = 0;
883 int have_kernpairs = 0;
886 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
888 switch ( afm_tokenize( key, len ) )
890 case AFM_TOKEN_STARTTRACKKERN:
891 if ( have_trackkern )
893 FT_ERROR((
"afm_parse_kern_data:"
894 " invalid second horizontal track kern section\n" ));
898 error = afm_parse_track_kern( parser );
905 case AFM_TOKEN_STARTKERNPAIRS:
906 case AFM_TOKEN_STARTKERNPAIRS0:
907 if ( have_kernpairs )
909 FT_ERROR((
"afm_parse_kern_data:"
910 " invalid second horizontal kern pair section\n" ));
914 error = afm_parse_kern_pairs( parser );
921 case AFM_TOKEN_ENDKERNDATA:
922 case AFM_TOKEN_ENDFONTMETRICS:
925 case AFM_TOKEN_UNKNOWN:
934 return FT_THROW( Syntax_Error );
939 afm_parser_skip_section( AFM_Parser parser,
941 AFM_Token end_section )
949 key = afm_parser_next_key( parser, 1, NULL );
954 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
956 AFM_Token token = afm_tokenize( key, len );
959 if ( token == end_section || token == AFM_TOKEN_ENDFONTMETRICS )
964 return FT_THROW( Syntax_Error );
968 FT_LOCAL_DEF( FT_Error )
969 afm_parser_parse( AFM_Parser parser )
971 FT_Memory memory = parser->memory;
972 AFM_FontInfo fi = parser->FontInfo;
973 FT_Error error = FT_ERR( Syntax_Error );
976 FT_Int metrics_sets = 0;
980 return FT_THROW( Invalid_Argument );
982 key = afm_parser_next_key( parser, 1, &len );
983 if ( !key || len != 16 ||
984 ft_strncmp( key,
"StartFontMetrics", 16 ) != 0 )
985 return FT_THROW( Unknown_File_Format );
987 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
989 AFM_ValueRec shared_vals[4];
992 switch ( afm_tokenize( key, len ) )
994 case AFM_TOKEN_METRICSSETS:
995 if ( afm_parser_read_int( parser, &metrics_sets ) )
998 if ( metrics_sets != 0 && metrics_sets != 2 )
1000 error = FT_THROW( Unimplemented_Feature );
1006 case AFM_TOKEN_ISCIDFONT:
1007 shared_vals[0].type = AFM_VALUE_TYPE_BOOL;
1008 if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 )
1011 fi->IsCIDFont = shared_vals[0].u.b;
1014 case AFM_TOKEN_FONTBBOX:
1015 shared_vals[0].type = AFM_VALUE_TYPE_FIXED;
1016 shared_vals[1].type = AFM_VALUE_TYPE_FIXED;
1017 shared_vals[2].type = AFM_VALUE_TYPE_FIXED;
1018 shared_vals[3].type = AFM_VALUE_TYPE_FIXED;
1019 if ( afm_parser_read_vals( parser, shared_vals, 4 ) != 4 )
1022 fi->FontBBox.xMin = shared_vals[0].u.f;
1023 fi->FontBBox.yMin = shared_vals[1].u.f;
1024 fi->FontBBox.xMax = shared_vals[2].u.f;
1025 fi->FontBBox.yMax = shared_vals[3].u.f;
1028 case AFM_TOKEN_ASCENDER:
1029 shared_vals[0].type = AFM_VALUE_TYPE_FIXED;
1030 if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 )
1033 fi->Ascender = shared_vals[0].u.f;
1036 case AFM_TOKEN_DESCENDER:
1037 shared_vals[0].type = AFM_VALUE_TYPE_FIXED;
1038 if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 )
1041 fi->Descender = shared_vals[0].u.f;
1044 case AFM_TOKEN_STARTCHARMETRICS:
1049 if ( afm_parser_read_int( parser, &n ) )
1052 error = afm_parser_skip_section( parser, n,
1053 AFM_TOKEN_ENDCHARMETRICS );
1059 case AFM_TOKEN_STARTKERNDATA:
1060 error = afm_parse_kern_data( parser );
1066 case AFM_TOKEN_ENDFONTMETRICS:
1075 FT_FREE( fi->TrackKerns );
1076 fi->NumTrackKern = 0;
1078 FT_FREE( fi->KernPairs );
1079 fi->NumKernPair = 0;
1089 typedef int afm_parse_dummy_;