1 /***************************************************************************/
5 /* AFM parser (body). */
7 /* Copyright 2006-2010, 2012 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 #include FT_FREETYPE_H
20 #include FT_INTERNAL_POSTSCRIPT_AUX_H
28 /***************************************************************************/
32 /* The use of AFM_Stream is largely inspired by parseAFM.[ch] from t1lib. */
38 AFM_STREAM_STATUS_NORMAL,
39 AFM_STREAM_STATUS_EOC,
40 AFM_STREAM_STATUS_EOL,
45 typedef struct AFM_StreamRec_
61 /* this works because empty lines are ignored */
62 #define AFM_IS_NEWLINE( ch ) ( (ch) == '\r' || (ch) == '\n' )
64 #define AFM_IS_EOF( ch ) ( (ch) == EOF || (ch) == '\x1a' )
65 #define AFM_IS_SPACE( ch ) ( (ch) == ' ' || (ch) == '\t' )
67 /* column separator; there is no `column' in the spec actually */
68 #define AFM_IS_SEP( ch ) ( (ch) == ';' )
71 ( ( (stream)->cursor < (stream)->limit ) ? *(stream)->cursor++ \
74 #define AFM_STREAM_KEY_BEGIN( stream ) \
75 (char*)( (stream)->cursor - 1 )
77 #define AFM_STREAM_KEY_LEN( stream, key ) \
78 ( (char*)(stream)->cursor - key - 1 )
80 #define AFM_STATUS_EOC( stream ) \
81 ( (stream)->status >= AFM_STREAM_STATUS_EOC )
83 #define AFM_STATUS_EOL( stream ) \
84 ( (stream)->status >= AFM_STREAM_STATUS_EOL )
86 #define AFM_STATUS_EOF( stream ) \
87 ( (stream)->status >= AFM_STREAM_STATUS_EOF )
91 afm_stream_skip_spaces( AFM_Stream stream )
93 int ch = 0; /* make stupid compiler happy */
96 if ( AFM_STATUS_EOC( stream ) )
102 if ( !AFM_IS_SPACE( ch ) )
106 if ( AFM_IS_NEWLINE( ch ) )
107 stream->status = AFM_STREAM_STATUS_EOL;
108 else if ( AFM_IS_SEP( ch ) )
109 stream->status = AFM_STREAM_STATUS_EOC;
110 else if ( AFM_IS_EOF( ch ) )
111 stream->status = AFM_STREAM_STATUS_EOF;
117 /* read a key or value in current column */
119 afm_stream_read_one( AFM_Stream stream )
125 afm_stream_skip_spaces( stream );
126 if ( AFM_STATUS_EOC( stream ) )
129 str = AFM_STREAM_KEY_BEGIN( stream );
134 if ( AFM_IS_SPACE( ch ) )
136 else if ( AFM_IS_NEWLINE( ch ) )
138 stream->status = AFM_STREAM_STATUS_EOL;
141 else if ( AFM_IS_SEP( ch ) )
143 stream->status = AFM_STREAM_STATUS_EOC;
146 else if ( AFM_IS_EOF( ch ) )
148 stream->status = AFM_STREAM_STATUS_EOF;
157 /* read a string (i.e., read to EOL) */
159 afm_stream_read_string( AFM_Stream stream )
165 afm_stream_skip_spaces( stream );
166 if ( AFM_STATUS_EOL( stream ) )
169 str = AFM_STREAM_KEY_BEGIN( stream );
175 if ( AFM_IS_NEWLINE( ch ) )
177 stream->status = AFM_STREAM_STATUS_EOL;
180 else if ( AFM_IS_EOF( ch ) )
182 stream->status = AFM_STREAM_STATUS_EOF;
191 /*************************************************************************/
197 /* all keys defined in Ch. 7-10 of 5004.AFM_Spec.pdf */
198 typedef enum AFM_Token_
204 AFM_TOKEN_BLENDAXISTYPES,
205 AFM_TOKEN_BLENDDESIGNMAP,
206 AFM_TOKEN_BLENDDESIGNPOSITIONS,
212 AFM_TOKEN_CHARACTERSET,
213 AFM_TOKEN_CHARACTERS,
215 AFM_TOKEN_ENCODINGSCHEME,
217 AFM_TOKEN_ENDCHARMETRICS,
218 AFM_TOKEN_ENDCOMPOSITES,
219 AFM_TOKEN_ENDDIRECTION,
220 AFM_TOKEN_ENDFONTMETRICS,
221 AFM_TOKEN_ENDKERNDATA,
222 AFM_TOKEN_ENDKERNPAIRS,
223 AFM_TOKEN_ENDTRACKKERN,
225 AFM_TOKEN_FAMILYNAME,
229 AFM_TOKEN_ISBASEFONT,
231 AFM_TOKEN_ISFIXEDPITCH,
233 AFM_TOKEN_ITALICANGLE,
239 AFM_TOKEN_MAPPINGSCHEME,
240 AFM_TOKEN_METRICSSETS,
245 AFM_TOKEN_STARTCHARMETRICS,
246 AFM_TOKEN_STARTCOMPOSITES,
247 AFM_TOKEN_STARTDIRECTION,
248 AFM_TOKEN_STARTFONTMETRICS,
249 AFM_TOKEN_STARTKERNDATA,
250 AFM_TOKEN_STARTKERNPAIRS,
251 AFM_TOKEN_STARTKERNPAIRS0,
252 AFM_TOKEN_STARTKERNPAIRS1,
253 AFM_TOKEN_STARTTRACKKERN,
257 AFM_TOKEN_UNDERLINEPOSITION,
258 AFM_TOKEN_UNDERLINETHICKNESS,
272 AFM_TOKEN_WEIGHTVECTOR,
280 static const char* const afm_key_table[N_AFM_TOKENS] =
288 "BlendDesignPositions",
340 "UnderlineThickness",
360 * `afm_parser_read_vals' and `afm_parser_next_key' provide
361 * high-level operations to an AFM_Stream. The rest of the
362 * parser functions should use them without accessing the
363 * AFM_Stream directly.
366 FT_LOCAL_DEF( FT_Int )
367 afm_parser_read_vals( AFM_Parser parser,
371 AFM_Stream stream = parser->stream;
376 if ( n > AFM_MAX_ARGUMENTS )
379 for ( i = 0; i < n; i++ )
382 AFM_Value val = vals + i;
385 if ( val->type == AFM_VALUE_TYPE_STRING )
386 str = afm_stream_read_string( stream );
388 str = afm_stream_read_one( stream );
393 len = AFM_STREAM_KEY_LEN( stream, str );
397 case AFM_VALUE_TYPE_STRING:
398 case AFM_VALUE_TYPE_NAME:
400 FT_Memory memory = parser->memory;
404 if ( !FT_QALLOC( val->u.s, len + 1 ) )
406 ft_memcpy( val->u.s, str, len );
407 val->u.s[len] = '\0';
412 case AFM_VALUE_TYPE_FIXED:
413 val->u.f = PS_Conv_ToFixed( (FT_Byte**)(void*)&str,
414 (FT_Byte*)str + len, 0 );
417 case AFM_VALUE_TYPE_INTEGER:
418 val->u.i = PS_Conv_ToInt( (FT_Byte**)(void*)&str,
419 (FT_Byte*)str + len );
422 case AFM_VALUE_TYPE_BOOL:
423 val->u.b = FT_BOOL( len == 4 &&
424 !ft_strncmp( str, "true", 4 ) );
427 case AFM_VALUE_TYPE_INDEX:
428 if ( parser->get_index )
429 val->u.i = parser->get_index( str, len, parser->user_data );
440 FT_LOCAL_DEF( char* )
441 afm_parser_next_key( AFM_Parser parser,
445 AFM_Stream stream = parser->stream;
446 char* key = 0; /* make stupid compiler happy */
453 /* skip current line */
454 if ( !AFM_STATUS_EOL( stream ) )
455 afm_stream_read_string( stream );
457 stream->status = AFM_STREAM_STATUS_NORMAL;
458 key = afm_stream_read_one( stream );
460 /* skip empty line */
462 !AFM_STATUS_EOF( stream ) &&
463 AFM_STATUS_EOL( stream ) )
473 /* skip current column */
474 while ( !AFM_STATUS_EOC( stream ) )
475 afm_stream_read_one( stream );
477 stream->status = AFM_STREAM_STATUS_NORMAL;
478 key = afm_stream_read_one( stream );
480 /* skip empty column */
482 !AFM_STATUS_EOF( stream ) &&
483 AFM_STATUS_EOC( stream ) )
491 *len = ( key ) ? (FT_Offset)AFM_STREAM_KEY_LEN( stream, key )
499 afm_tokenize( const char* key,
505 for ( n = 0; n < N_AFM_TOKENS; n++ )
507 if ( *( afm_key_table[n] ) == *key )
509 for ( ; n < N_AFM_TOKENS; n++ )
511 if ( *( afm_key_table[n] ) != *key )
512 return AFM_TOKEN_UNKNOWN;
514 if ( ft_strncmp( afm_key_table[n], key, len ) == 0 )
515 return (AFM_Token) n;
520 return AFM_TOKEN_UNKNOWN;
524 FT_LOCAL_DEF( FT_Error )
525 afm_parser_init( AFM_Parser parser,
530 AFM_Stream stream = NULL;
534 if ( FT_NEW( stream ) )
537 stream->cursor = stream->base = base;
538 stream->limit = limit;
540 /* don't skip the first line during the first call */
541 stream->status = AFM_STREAM_STATUS_EOL;
543 parser->memory = memory;
544 parser->stream = stream;
545 parser->FontInfo = NULL;
546 parser->get_index = NULL;
553 afm_parser_done( AFM_Parser parser )
555 FT_Memory memory = parser->memory;
558 FT_FREE( parser->stream );
562 FT_LOCAL_DEF( FT_Error )
563 afm_parser_read_int( AFM_Parser parser,
569 val.type = AFM_VALUE_TYPE_INTEGER;
571 if ( afm_parser_read_vals( parser, &val, 1 ) == 1 )
578 return PSaux_Err_Syntax_Error;
583 afm_parse_track_kern( AFM_Parser parser )
585 AFM_FontInfo fi = parser->FontInfo;
592 if ( afm_parser_read_int( parser, &fi->NumTrackKern ) )
595 if ( fi->NumTrackKern )
597 FT_Memory memory = parser->memory;
601 if ( FT_QNEW_ARRAY( fi->TrackKerns, fi->NumTrackKern ) )
605 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
607 AFM_ValueRec shared_vals[5];
610 switch ( afm_tokenize( key, len ) )
612 case AFM_TOKEN_TRACKKERN:
615 if ( n >= fi->NumTrackKern )
618 tk = fi->TrackKerns + n;
620 shared_vals[0].type = AFM_VALUE_TYPE_INTEGER;
621 shared_vals[1].type = AFM_VALUE_TYPE_FIXED;
622 shared_vals[2].type = AFM_VALUE_TYPE_FIXED;
623 shared_vals[3].type = AFM_VALUE_TYPE_FIXED;
624 shared_vals[4].type = AFM_VALUE_TYPE_FIXED;
625 if ( afm_parser_read_vals( parser, shared_vals, 5 ) != 5 )
628 tk->degree = shared_vals[0].u.i;
629 tk->min_ptsize = shared_vals[1].u.f;
630 tk->min_kern = shared_vals[2].u.f;
631 tk->max_ptsize = shared_vals[3].u.f;
632 tk->max_kern = shared_vals[4].u.f;
636 case AFM_TOKEN_ENDTRACKKERN:
637 case AFM_TOKEN_ENDKERNDATA:
638 case AFM_TOKEN_ENDFONTMETRICS:
639 fi->NumTrackKern = n + 1;
642 case AFM_TOKEN_UNKNOWN:
651 return PSaux_Err_Syntax_Error;
656 #define KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 )
659 /* compare two kerning pairs */
660 FT_CALLBACK_DEF( int )
661 afm_compare_kern_pairs( const void* a,
664 AFM_KernPair kp1 = (AFM_KernPair)a;
665 AFM_KernPair kp2 = (AFM_KernPair)b;
667 FT_ULong index1 = KERN_INDEX( kp1->index1, kp1->index2 );
668 FT_ULong index2 = KERN_INDEX( kp2->index1, kp2->index2 );
671 if ( index1 > index2 )
673 else if ( index1 < index2 )
681 afm_parse_kern_pairs( AFM_Parser parser )
683 AFM_FontInfo fi = parser->FontInfo;
690 if ( afm_parser_read_int( parser, &fi->NumKernPair ) )
693 if ( fi->NumKernPair )
695 FT_Memory memory = parser->memory;
699 if ( FT_QNEW_ARRAY( fi->KernPairs, fi->NumKernPair ) )
703 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
705 AFM_Token token = afm_tokenize( key, len );
715 AFM_ValueRec shared_vals[4];
720 if ( n >= fi->NumKernPair )
723 kp = fi->KernPairs + n;
725 shared_vals[0].type = AFM_VALUE_TYPE_INDEX;
726 shared_vals[1].type = AFM_VALUE_TYPE_INDEX;
727 shared_vals[2].type = AFM_VALUE_TYPE_INTEGER;
728 shared_vals[3].type = AFM_VALUE_TYPE_INTEGER;
729 r = afm_parser_read_vals( parser, shared_vals, 4 );
733 kp->index1 = shared_vals[0].u.i;
734 kp->index2 = shared_vals[1].u.i;
735 if ( token == AFM_TOKEN_KPY )
738 kp->y = shared_vals[2].u.i;
742 kp->x = shared_vals[2].u.i;
743 kp->y = ( token == AFM_TOKEN_KP && r == 4 )
744 ? shared_vals[3].u.i : 0;
749 case AFM_TOKEN_ENDKERNPAIRS:
750 case AFM_TOKEN_ENDKERNDATA:
751 case AFM_TOKEN_ENDFONTMETRICS:
752 fi->NumKernPair = n + 1;
753 ft_qsort( fi->KernPairs, fi->NumKernPair,
754 sizeof ( AFM_KernPairRec ),
755 afm_compare_kern_pairs );
758 case AFM_TOKEN_UNKNOWN:
767 return PSaux_Err_Syntax_Error;
772 afm_parse_kern_data( AFM_Parser parser )
779 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
781 switch ( afm_tokenize( key, len ) )
783 case AFM_TOKEN_STARTTRACKKERN:
784 error = afm_parse_track_kern( parser );
789 case AFM_TOKEN_STARTKERNPAIRS:
790 case AFM_TOKEN_STARTKERNPAIRS0:
791 error = afm_parse_kern_pairs( parser );
796 case AFM_TOKEN_ENDKERNDATA:
797 case AFM_TOKEN_ENDFONTMETRICS:
800 case AFM_TOKEN_UNKNOWN:
809 return PSaux_Err_Syntax_Error;
814 afm_parser_skip_section( AFM_Parser parser,
816 AFM_Token end_section )
824 key = afm_parser_next_key( parser, 1, NULL );
829 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
831 AFM_Token token = afm_tokenize( key, len );
834 if ( token == end_section || token == AFM_TOKEN_ENDFONTMETRICS )
839 return PSaux_Err_Syntax_Error;
843 FT_LOCAL_DEF( FT_Error )
844 afm_parser_parse( AFM_Parser parser )
846 FT_Memory memory = parser->memory;
847 AFM_FontInfo fi = parser->FontInfo;
848 FT_Error error = PSaux_Err_Syntax_Error;
851 FT_Int metrics_sets = 0;
855 return PSaux_Err_Invalid_Argument;
857 key = afm_parser_next_key( parser, 1, &len );
858 if ( !key || len != 16 ||
859 ft_strncmp( key, "StartFontMetrics", 16 ) != 0 )
860 return PSaux_Err_Unknown_File_Format;
862 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
864 AFM_ValueRec shared_vals[4];
867 switch ( afm_tokenize( key, len ) )
869 case AFM_TOKEN_METRICSSETS:
870 if ( afm_parser_read_int( parser, &metrics_sets ) )
873 if ( metrics_sets != 0 && metrics_sets != 2 )
875 error = PSaux_Err_Unimplemented_Feature;
881 case AFM_TOKEN_ISCIDFONT:
882 shared_vals[0].type = AFM_VALUE_TYPE_BOOL;
883 if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 )
886 fi->IsCIDFont = shared_vals[0].u.b;
889 case AFM_TOKEN_FONTBBOX:
890 shared_vals[0].type = AFM_VALUE_TYPE_FIXED;
891 shared_vals[1].type = AFM_VALUE_TYPE_FIXED;
892 shared_vals[2].type = AFM_VALUE_TYPE_FIXED;
893 shared_vals[3].type = AFM_VALUE_TYPE_FIXED;
894 if ( afm_parser_read_vals( parser, shared_vals, 4 ) != 4 )
897 fi->FontBBox.xMin = shared_vals[0].u.f;
898 fi->FontBBox.yMin = shared_vals[1].u.f;
899 fi->FontBBox.xMax = shared_vals[2].u.f;
900 fi->FontBBox.yMax = shared_vals[3].u.f;
903 case AFM_TOKEN_ASCENDER:
904 shared_vals[0].type = AFM_VALUE_TYPE_FIXED;
905 if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 )
908 fi->Ascender = shared_vals[0].u.f;
911 case AFM_TOKEN_DESCENDER:
912 shared_vals[0].type = AFM_VALUE_TYPE_FIXED;
913 if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 )
916 fi->Descender = shared_vals[0].u.f;
919 case AFM_TOKEN_STARTCHARMETRICS:
924 if ( afm_parser_read_int( parser, &n ) )
927 error = afm_parser_skip_section( parser, n,
928 AFM_TOKEN_ENDCHARMETRICS );
934 case AFM_TOKEN_STARTKERNDATA:
935 error = afm_parse_kern_data( parser );
938 /* fall through since we only support kern data */
940 case AFM_TOKEN_ENDFONTMETRICS:
949 FT_FREE( fi->TrackKerns );
950 fi->NumTrackKern = 0;
952 FT_FREE( fi->KernPairs );