1 /***************************************************************************/
5 /* Experimental Type 1 font loader (body). */
7 /* Copyright 1996-2000 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 /*************************************************************************/
21 /* This is the new and improved Type 1 data loader for FreeType 2. The */
22 /* old loader has several problems: it is slow, complex, difficult to */
23 /* maintain, and contains incredible hacks to make it accept some */
24 /* ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5% of */
25 /* the Type 1 fonts on my machine still aren't loaded correctly by it. */
27 /* This version is much simpler, much faster and also easier to read and */
28 /* maintain by a great order of magnitude. The idea behind it is to */
29 /* _not_ try to read the Type 1 token stream with a state machine (i.e. */
30 /* a Postscript-like interpreter) but rather to perform simple pattern */
33 /* Indeed, nearly all data definitions follow a simple pattern like */
35 /* ... /Field <data> ... */
37 /* where <data> can be a number, a boolean, a string, or an array of */
38 /* numbers. There are a few exceptions, namely the encoding, font name, */
39 /* charstrings, and subrs; they are handled with a special pattern */
40 /* matching routine. */
42 /* All other common cases are handled very simply. The matching rules */
43 /* are defined in the file `t1tokens.h' through the use of several */
44 /* macros calls PARSE_XXX. */
46 /* This file is included twice here; the first time to generate parsing */
47 /* callback functions, the second to generate a table of keywords (with */
48 /* pointers to the associated callback). */
50 /* The function `parse_dict' simply scans *linearly* a given dictionary */
51 /* (either the top-level or private one) and calls the appropriate */
52 /* callback when it encounters an immediate keyword. */
54 /* This is by far the fastest way one can find to parse and read all */
57 /* This led to tremendous code size reduction. Note that later, the */
58 /* glyph loader will also be _greatly_ simplified, and the automatic */
59 /* hinter will replace the clumsy `t1hinter'. */
61 /*************************************************************************/
64 #include <freetype/internal/ftdebug.h>
65 #include <freetype/config/ftconfig.h>
66 #include <freetype/ftmm.h>
68 #include <freetype/internal/t1types.h>
69 #include <freetype/internal/t1errors.h>
72 #ifdef FT_FLAT_COMPILE
78 #include <type1z/z1load.h>
83 #include <string.h> /* for strncmp(), strcmp() */
84 #include <ctype.h> /* for isalnum() */
87 /*************************************************************************/
89 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
90 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
91 /* messages during execution. */
94 #define FT_COMPONENT trace_z1load
97 #ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
100 /*************************************************************************/
101 /*************************************************************************/
103 /***** MULTIPLE MASTERS SUPPORT *****/
105 /*************************************************************************/
106 /*************************************************************************/
109 FT_Error
t1_allocate_blend( T1_Face face
,
114 FT_Memory memory
= face
->root
.memory
;
121 if ( ALLOC( blend
, sizeof ( *blend
) ) )
127 /* allocate design data if needed */
128 if ( num_designs
> 0 )
130 if ( blend
->num_designs
== 0 )
135 /* allocate the blend `private' and `font_info' dictionaries */
136 if ( ALLOC_ARRAY( blend
->font_infos
[1], num_designs
, T1_FontInfo
) ||
137 ALLOC_ARRAY( blend
->privates
[1], num_designs
, T1_Private
) ||
138 ALLOC_ARRAY( blend
->weight_vector
, num_designs
* 2, FT_Fixed
) )
141 blend
->default_weight_vector
= blend
->weight_vector
+ num_designs
;
143 blend
->font_infos
[0] = &face
->type1
.font_info
;
144 blend
->privates
[0] = &face
->type1
.private_dict
;
146 for ( nn
= 2; nn
<= num_designs
; nn
++ )
148 blend
->privates
[nn
] = blend
->privates
[nn
- 1] + 1;
149 blend
->font_infos
[nn
] = blend
->font_infos
[nn
- 1] + 1;
152 blend
->num_designs
= num_designs
;
154 else if ( blend
->num_designs
!= num_designs
)
158 /* allocate axis data if needed */
161 if ( blend
->num_axis
!= 0 && blend
->num_axis
!= num_axis
)
164 blend
->num_axis
= num_axis
;
167 /* allocate the blend design pos table if needed */
168 num_designs
= blend
->num_designs
;
169 num_axis
= blend
->num_axis
;
170 if ( num_designs
&& num_axis
&& blend
->design_pos
[0] == 0 )
175 if ( ALLOC_ARRAY( blend
->design_pos
[0],
176 num_designs
* num_axis
, FT_Fixed
) )
179 for ( n
= 1; n
< num_designs
; n
++ )
180 blend
->design_pos
[n
] = blend
->design_pos
[0] + num_axis
* n
;
193 FT_Error
Z1_Get_Multi_Master( T1_Face face
,
194 FT_Multi_Master
* master
)
196 T1_Blend
* blend
= face
->blend
;
201 error
= T1_Err_Invalid_Argument
;
205 master
->num_axis
= blend
->num_axis
;
206 master
->num_designs
= blend
->num_designs
;
208 for ( n
= 0; n
< blend
->num_axis
; n
++ )
210 FT_MM_Axis
* axis
= master
->axis
+ n
;
211 T1_DesignMap
* map
= blend
->design_map
+ n
;
214 axis
->name
= blend
->axis_names
[n
];
215 axis
->minimum
= map
->design_points
[0];
216 axis
->maximum
= map
->design_points
[map
->num_points
- 1];
225 FT_Error
Z1_Set_MM_Blend( T1_Face face
,
229 T1_Blend
* blend
= face
->blend
;
234 error
= T1_Err_Invalid_Argument
;
236 if ( blend
&& blend
->num_axis
== num_coords
)
238 /* recompute the weight vector from the blend coordinates */
241 for ( n
= 0; n
< blend
->num_designs
; n
++ )
243 FT_Fixed result
= 0x10000L
; /* 1.0 fixed */
246 for ( m
= 0; m
< blend
->num_axis
; m
++ )
251 /* get current blend axis position */
253 if ( factor
< 0 ) factor
= 0;
254 if ( factor
> 0x10000L
) factor
= 0x10000L
;
256 if ( ( n
& ( 1 << m
) ) == 0 )
257 factor
= 0x10000L
- factor
;
259 result
= FT_MulFix( result
, factor
);
261 blend
->weight_vector
[n
] = result
;
271 FT_Error
Z1_Set_MM_Design( T1_Face face
,
275 T1_Blend
* blend
= face
->blend
;
280 error
= T1_Err_Invalid_Argument
;
281 if ( blend
&& blend
->num_axis
== num_coords
)
283 /* compute the blend coordinates through the blend design map */
284 FT_Fixed final_blends
[T1_MAX_MM_DESIGNS
];
287 for ( n
= 0; n
< blend
->num_axis
; n
++ )
289 FT_Long design
= coords
[n
];
291 T1_DesignMap
* map
= blend
->design_map
+ n
;
292 FT_Fixed
* designs
= map
->design_points
;
293 FT_Fixed
* blends
= map
->blend_points
;
294 FT_Int before
= -1, after
= -1;
296 for ( p
= 0; p
< map
->num_points
; p
++ )
298 FT_Fixed p_design
= designs
[p
];
302 if ( design
== p_design
)
304 the_blend
= blends
[p
];
308 if ( design
< p_design
)
317 /* now, interpolate if needed */
319 the_blend
= blends
[0];
321 else if ( after
< 0 )
322 the_blend
= blends
[map
->num_points
- 1];
325 the_blend
= FT_MulDiv( design
- designs
[before
],
326 blends
[after
] - blends
[before
],
327 designs
[after
] - designs
[before
] );
330 final_blends
[n
] = the_blend
;
333 error
= Z1_Set_MM_Blend( face
, num_coords
, final_blends
);
341 void Z1_Done_Blend( T1_Face face
)
343 FT_Memory memory
= face
->root
.memory
;
344 T1_Blend
* blend
= face
->blend
;
349 FT_UInt num_designs
= blend
->num_designs
;
350 FT_UInt num_axis
= blend
->num_axis
;
354 /* release design pos table */
355 FREE( blend
->design_pos
[0] );
356 for ( n
= 1; n
< num_designs
; n
++ )
357 blend
->design_pos
[n
] = 0;
359 /* release blend `private' and `font info' dictionaries */
360 FREE( blend
->privates
[1] );
361 FREE( blend
->font_infos
[1] );
363 for ( n
= 0; n
< num_designs
; n
++ )
365 blend
->privates
[n
] = 0;
366 blend
->font_infos
[n
] = 0;
369 /* release weight vectors */
370 FREE( blend
->weight_vector
);
371 blend
->default_weight_vector
= 0;
373 /* release axis names */
374 for ( n
= 0; n
< num_axis
; n
++ )
375 FREE( blend
->axis_names
[n
] );
377 /* release design map */
378 for ( n
= 0; n
< num_axis
; n
++ )
380 T1_DesignMap
* dmap
= blend
->design_map
+ n
;
383 FREE( dmap
->design_points
);
384 dmap
->num_points
= 0;
393 void parse_blend_axis_types( T1_Face face
,
396 Z1_Token_Rec axis_tokens
[ T1_MAX_MM_AXIS
];
403 /* take an array of objects */
404 Z1_ToTokenArray( &loader
->parser
, axis_tokens
,
405 T1_MAX_MM_AXIS
, &num_axis
);
406 if ( num_axis
<= 0 || num_axis
> T1_MAX_MM_AXIS
)
408 FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n",
410 error
= T1_Err_Invalid_File_Format
;
414 /* allocate blend if necessary */
415 error
= t1_allocate_blend( face
, 0, (FT_UInt
)num_axis
);
420 memory
= face
->root
.memory
;
422 /* each token is an immediate containing the name of the axis */
423 for ( n
= 0; n
< num_axis
; n
++ )
425 Z1_Token_Rec
* token
= axis_tokens
+ n
;
429 /* skip first slash, if any */
430 if (token
->start
[0] == '/')
433 len
= token
->limit
- token
->start
;
436 error
= T1_Err_Invalid_File_Format
;
440 if ( ALLOC( blend
->axis_names
[n
], len
+ 1 ) )
443 name
= (FT_Byte
*)blend
->axis_names
[n
];
444 MEM_Copy( name
, token
->start
, len
);
449 loader
->parser
.error
= error
;
454 void parse_blend_design_positions( T1_Face face
,
457 Z1_Token_Rec design_tokens
[ T1_MAX_MM_DESIGNS
];
460 Z1_Parser
* parser
= &loader
->parser
;
466 /* get the array of design tokens - compute number of designs */
467 Z1_ToTokenArray( parser
, design_tokens
, T1_MAX_MM_DESIGNS
, &num_designs
);
468 if ( num_designs
<= 0 || num_designs
> T1_MAX_MM_DESIGNS
)
470 FT_ERROR(( "parse_blend_design_positions:" ));
471 FT_ERROR(( " incorrect number of designs: %d\n",
473 error
= T1_Err_Invalid_File_Format
;
478 FT_Byte
* old_cursor
= parser
->cursor
;
479 FT_Byte
* old_limit
= parser
->limit
;
484 num_axis
= 0; /* make compiler happy */
486 for ( n
= 0; n
< (FT_UInt
)num_designs
; n
++ )
488 Z1_Token_Rec axis_tokens
[ T1_MAX_MM_DESIGNS
];
493 /* read axis/coordinates tokens */
494 token
= design_tokens
+ n
;
495 parser
->cursor
= token
->start
- 1;
496 parser
->limit
= token
->limit
+ 1;
497 Z1_ToTokenArray( parser
, axis_tokens
, T1_MAX_MM_AXIS
, &n_axis
);
502 error
= t1_allocate_blend( face
, num_designs
, num_axis
);
507 else if ( n_axis
!= num_axis
)
509 FT_ERROR(( "parse_blend_design_positions: incorrect table\n" ));
510 error
= T1_Err_Invalid_File_Format
;
514 /* now, read each axis token into the design position */
515 for ( axis
= 0; axis
< n_axis
; axis
++ )
517 Z1_Token_Rec
* token2
= axis_tokens
+ axis
;
520 parser
->cursor
= token2
->start
;
521 parser
->limit
= token2
->limit
;
522 blend
->design_pos
[n
][axis
] = Z1_ToFixed( parser
, 0 );
526 loader
->parser
.cursor
= old_cursor
;
527 loader
->parser
.limit
= old_limit
;
531 loader
->parser
.error
= error
;
536 void parse_blend_design_map( T1_Face face
,
540 Z1_Parser
* parser
= &loader
->parser
;
542 Z1_Token_Rec axis_tokens
[ T1_MAX_MM_AXIS
];
546 FT_Memory memory
= face
->root
.memory
;
549 Z1_ToTokenArray( parser
, axis_tokens
, T1_MAX_MM_AXIS
, &num_axis
);
550 if ( num_axis
<= 0 || num_axis
> T1_MAX_MM_AXIS
)
552 FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n",
554 error
= T1_Err_Invalid_File_Format
;
557 old_cursor
= parser
->cursor
;
558 old_limit
= parser
->limit
;
560 error
= t1_allocate_blend( face
, 0, num_axis
);
565 /* now, read each axis design map */
566 for ( n
= 0; n
< num_axis
; n
++ )
568 T1_DesignMap
* map
= blend
->design_map
+ n
;
570 FT_Int p
, num_points
;
573 token
= axis_tokens
+ n
;
574 parser
->cursor
= token
->start
;
575 parser
->limit
= token
->limit
;
577 /* count the number of map points */
579 FT_Byte
* p
= token
->start
;
580 FT_Byte
* limit
= token
->limit
;
584 for ( ; p
< limit
; p
++ )
588 if ( num_points
<= 0 || num_points
> T1_MAX_MM_MAP_POINTS
)
590 FT_ERROR(( "parse_blend_design_map: incorrect table\n" ));
591 error
= T1_Err_Invalid_File_Format
;
595 /* allocate design map data */
596 if ( ALLOC_ARRAY( map
->design_points
, num_points
* 2, FT_Fixed
) )
598 map
->blend_points
= map
->design_points
+ num_points
;
599 map
->num_points
= (FT_Byte
)num_points
;
601 for ( p
= 0; p
< num_points
; p
++ )
603 map
->design_points
[p
] = Z1_ToInt( parser
);
604 map
->blend_points
[p
] = Z1_ToFixed( parser
, 0 );
608 parser
->cursor
= old_cursor
;
609 parser
->limit
= old_limit
;
612 parser
->error
= error
;
617 void parse_weight_vector( T1_Face face
,
621 Z1_Parser
* parser
= &loader
->parser
;
622 T1_Blend
* blend
= face
->blend
;
629 if ( !blend
|| blend
->num_designs
== 0 )
631 FT_ERROR(( "parse_weight_vector: too early!\n" ));
632 error
= T1_Err_Invalid_File_Format
;
636 Z1_ToToken( parser
, &master
);
637 if ( master
.type
!= t1_token_array
)
639 FT_ERROR(( "parse_weight_vector: incorrect format!\n" ));
640 error
= T1_Err_Invalid_File_Format
;
644 old_cursor
= parser
->cursor
;
645 old_limit
= parser
->limit
;
647 parser
->cursor
= master
.start
;
648 parser
->limit
= master
.limit
;
650 for ( n
= 0; n
< blend
->num_designs
; n
++ )
652 blend
->default_weight_vector
[n
] =
653 blend
->weight_vector
[n
] = Z1_ToFixed( parser
, 0 );
656 parser
->cursor
= old_cursor
;
657 parser
->limit
= old_limit
;
660 parser
->error
= error
;
664 /* the keyword `/shareddict' appears in some multiple master fonts */
665 /* with a lot of Postscript garbage behind it (that's completely out */
666 /* of spec!); we detect it and terminate the parsing */
669 void parse_shared_dict( T1_Face face
,
672 Z1_Parser
* parser
= &loader
->parser
;
677 parser
->cursor
= parser
->limit
;
681 #endif /* Z1_CONFIG_OPTION_NO_MM_SUPPORT */
684 /*************************************************************************/
685 /*************************************************************************/
687 /***** TYPE 1 SYMBOL PARSING *****/
689 /*************************************************************************/
690 /*************************************************************************/
693 /*************************************************************************/
695 /* First of all, define the token field static variables. This is a set */
696 /* of Z1_Field_Rec variables used later. */
698 /*************************************************************************/
700 #define Z1_NEW_STRING( _name, _field ) \
702 const Z1_Field_Rec t1_field_ ## _field = \
703 Z1_FIELD_STRING( T1TYPE, _field );
705 #define Z1_NEW_BOOL( _name, _field ) \
707 const Z1_Field_Rec t1_field_ ## _field = \
708 Z1_FIELD_BOOL( T1TYPE, _field );
710 #define Z1_NEW_NUM( _name, _field ) \
712 const Z1_Field_Rec t1_field_ ## _field = \
713 Z1_FIELD_NUM( T1TYPE, _field );
715 #define Z1_NEW_FIXED( _name, _field ) \
717 const Z1_Field_Rec t1_field_ ## _field = \
718 Z1_FIELD_FIXED( T1TYPE, _field, _power );
720 #define Z1_NEW_NUM_TABLE( _name, _field, _max, _count ) \
722 const Z1_Field_Rec t1_field_ ## _field = \
723 Z1_FIELD_NUM_ARRAY( T1TYPE, _field, _count, _max );
725 #define Z1_NEW_FIXED_TABLE( _name, _field, _max, _count ) \
727 const Z1_Field_Rec t1_field_ ## _field = \
728 Z1_FIELD_FIXED_ARRAY( T1TYPE, _field, _count, _max );
730 #define Z1_NEW_NUM_TABLE2( _name, _field, _max ) \
732 const Z1_Field_Rec t1_field_ ## _field = \
733 Z1_FIELD_NUM_ARRAY2( T1TYPE, _field, _max );
735 #define Z1_NEW_FIXED_TABLE2( _name, _field, _max ) \
737 const Z1_Field_Rec t1_field_ ## _field = \
738 Z1_FIELD_FIXED_ARRAY2( T1TYPE, _field, _max );
741 #define Z1_FONTINFO_STRING( n, f ) Z1_NEW_STRING( n, f )
742 #define Z1_FONTINFO_NUM( n, f ) Z1_NEW_NUM( n, f )
743 #define Z1_FONTINFO_BOOL( n, f ) Z1_NEW_BOOL( n, f )
744 #define Z1_PRIVATE_NUM( n, f ) Z1_NEW_NUM( n, f )
745 #define Z1_PRIVATE_FIXED( n, f ) Z1_NEW_FIXED( n, f )
746 #define Z1_PRIVATE_NUM_TABLE( n, f, m, c ) Z1_NEW_NUM_TABLE( n, f, m, c )
747 #define Z1_PRIVATE_NUM_TABLE2( n, f, m ) Z1_NEW_NUM_TABLE2( n, f, m )
748 #define Z1_TOPDICT_NUM( n, f ) Z1_NEW_NUM( n, f )
749 #define Z1_TOPDICT_NUM_FIXED2( n, f, m ) Z1_NEW_FIXED_TABLE2( n, f, m )
752 /* including this file defines all field variables */
753 #ifdef FT_FLAT_COMPILE
755 #include "z1tokens.h"
759 #include <type1z/z1tokens.h>
764 /*************************************************************************/
766 /* Second, define the keyword variables. This is a set of Z1_KeyWord */
767 /* structures used to model the way each keyword is `loaded'. */
769 /*************************************************************************/
771 typedef void (*Z1_Parse_Func
)( T1_Face face
,
775 typedef enum Z1_KeyWord_Type_
777 t1_keyword_callback
= 0,
779 t1_keyword_field_table
784 typedef enum Z1_KeyWord_Location_
786 t1_keyword_type1
= 0,
787 t1_keyword_font_info
,
790 } Z1_KeyWord_Location
;
793 typedef struct Z1_KeyWord_
796 Z1_KeyWord_Type type
;
797 Z1_KeyWord_Location location
;
798 Z1_Parse_Func parsing
;
799 const Z1_Field_Rec
* field
;
804 #define Z1_KEYWORD_CALLBACK( name, callback ) \
806 name, t1_keyword_callback, t1_keyword_type1, callback, 0 \
809 #define Z1_KEYWORD_TYPE1( name, f ) \
811 name, t1_keyword_field, t1_keyword_type1, 0, &t1_field_ ## f \
814 #define Z1_KEYWORD_FONTINFO( name, f ) \
816 name, t1_keyword_field, t1_keyword_font_info, 0, &t1_field_ ## f \
819 #define Z1_KEYWORD_PRIVATE( name, f ) \
821 name, t1_keyword_field, t1_keyword_private, 0, &t1_field_ ## f \
824 #define Z1_KEYWORD_FONTINFO_TABLE( name, f ) \
826 name, t1_keyword_field_table, t1_keyword_font_info, 0, \
830 #define Z1_KEYWORD_PRIVATE_TABLE( name, f ) \
832 name, t1_keyword_field_table, t1_keyword_private, 0, \
837 #undef Z1_FONTINFO_STRING
838 #undef Z1_FONTINFO_NUM
839 #undef Z1_FONTINFO_BOOL
840 #undef Z1_PRIVATE_NUM
841 #undef Z1_PRIVATE_FIXED
842 #undef Z1_PRIVATE_NUM_TABLE
843 #undef Z1_PRIVATE_NUM_TABLE2
844 #undef Z1_TOPDICT_NUM
845 #undef Z1_TOPDICT_NUM_FIXED2
847 #define Z1_FONTINFO_STRING( n, f ) Z1_KEYWORD_FONTINFO( n, f ),
848 #define Z1_FONTINFO_NUM( n, f ) Z1_KEYWORD_FONTINFO( n, f ),
849 #define Z1_FONTINFO_BOOL( n, f ) Z1_KEYWORD_FONTINFO( n, f ),
850 #define Z1_PRIVATE_NUM( n, f ) Z1_KEYWORD_PRIVATE( n, f ),
851 #define Z1_PRIVATE_FIXED( n, f ) Z1_KEYWORD_PRIVATE( n, f ),
852 #define Z1_PRIVATE_NUM_TABLE( n, f, m, c ) Z1_KEYWORD_PRIVATE_TABLE( n, f ),
853 #define Z1_PRIVATE_NUM_TABLE2( n, f, m ) Z1_KEYWORD_PRIVATE_TABLE( n, f ),
854 #define Z1_TOPDICT_NUM( n, f ) Z1_KEYWORD_TYPE1( n, f ),
855 #define Z1_TOPDICT_NUM_FIXED2( n, f, m ) Z1_KEYWORD_TYPE1( n, f ),
859 FT_Error
t1_load_keyword( T1_Face face
,
861 Z1_KeyWord
* keyword
)
867 T1_Blend
* blend
= face
->blend
;
870 /* if the keyword has a dedicated callback, call it */
871 if ( keyword
->type
== t1_keyword_callback
)
873 keyword
->parsing( face
, loader
);
874 error
= loader
->parser
.error
;
878 /* now, the keyword is either a simple field, or a table of fields; */
879 /* we are now going to take care of it */
880 switch ( keyword
->location
)
882 case t1_keyword_font_info
:
883 dummy_object
= &face
->type1
.font_info
;
884 objects
= &dummy_object
;
889 objects
= (void**)blend
->font_infos
;
890 max_objects
= blend
->num_designs
;
894 case t1_keyword_private
:
895 dummy_object
= &face
->type1
.private_dict
;
896 objects
= &dummy_object
;
901 objects
= (void**)blend
->privates
;
902 max_objects
= blend
->num_designs
;
907 dummy_object
= &face
->type1
;
908 objects
= &dummy_object
;
912 if ( keyword
->type
== t1_keyword_field_table
)
913 error
= Z1_Load_Field_Table( &loader
->parser
, keyword
->field
,
914 objects
, max_objects
, 0 );
916 error
= Z1_Load_Field( &loader
->parser
, keyword
->field
,
917 objects
, max_objects
, 0 );
925 int is_space( char c
)
927 return ( c
== ' ' || c
== '\t' || c
== '\r' || c
== '\n' );
932 int is_alpha( char c
)
934 return ( isalnum( c
) ||
941 void skip_whitespace( Z1_Parser
* parser
)
943 FT_Byte
* cur
= parser
->cursor
;
946 while ( cur
< parser
->limit
&& is_space( *cur
) )
949 parser
->cursor
= cur
;
954 void skip_blackspace( Z1_Parser
* parser
)
956 FT_Byte
* cur
= parser
->cursor
;
958 while ( cur
< parser
->limit
&& !is_space( *cur
) )
961 parser
->cursor
= cur
;
966 int read_binary_data( Z1_Parser
* parser
,
971 FT_Byte
* limit
= parser
->limit
;
974 /* the binary data has the following format */
976 /* `size' [white*] RD white ....... ND */
979 skip_whitespace( parser
);
980 cur
= parser
->cursor
;
982 if ( cur
< limit
&& (FT_Byte
)( *cur
- '0' ) < 10 )
984 *size
= Z1_ToInt( parser
);
986 skip_whitespace( parser
);
987 skip_blackspace( parser
); /* `RD' or `-|' or something else */
989 /* there is only one whitespace char after the */
990 /* `RD' or `-|' token */
991 *base
= parser
->cursor
+ 1;
993 parser
->cursor
+= *size
+1;
997 FT_ERROR(( "read_binary_data: invalid size field\n" ));
998 parser
->error
= T1_Err_Invalid_File_Format
;
1003 /* we will now define the routines used to handle */
1004 /* the `/Encoding', `/Subrs', and `/CharStrings' */
1008 void parse_font_name( T1_Face face
,
1011 Z1_Parser
* parser
= &loader
->parser
;
1013 FT_Memory memory
= parser
->memory
;
1020 skip_whitespace( parser
);
1022 cur
= parser
->cursor
;
1023 limit
= parser
->limit
;
1025 if ( cur
>= limit
- 1 || *cur
!= '/' )
1030 while ( cur2
< limit
&& is_alpha( *cur2
) )
1036 if ( ALLOC( face
->type1
.font_name
, len
+ 1 ) )
1038 parser
->error
= error
;
1042 MEM_Copy( face
->type1
.font_name
, cur
, len
);
1043 face
->type1
.font_name
[len
] = '\0';
1045 parser
->cursor
= cur2
;
1050 void parse_font_bbox( T1_Face face
,
1053 Z1_Parser
* parser
= &loader
->parser
;
1055 FT_BBox
* bbox
= &face
->type1
.font_bbox
;
1058 (void)Z1_ToCoordArray( parser
, 4, temp
);
1059 bbox
->xMin
= temp
[0];
1060 bbox
->yMin
= temp
[1];
1061 bbox
->xMax
= temp
[2];
1062 bbox
->yMax
= temp
[3];
1067 void parse_font_matrix( T1_Face face
,
1070 Z1_Parser
* parser
= &loader
->parser
;
1071 FT_Matrix
* matrix
= &face
->type1
.font_matrix
;
1075 (void)Z1_ToFixedArray( parser
, 4, temp
, 3 );
1076 matrix
->xx
= temp
[0];
1077 matrix
->yx
= temp
[1];
1078 matrix
->xy
= temp
[2];
1079 matrix
->yy
= temp
[3];
1084 void parse_encoding( T1_Face face
,
1087 Z1_Parser
* parser
= &loader
->parser
;
1088 FT_Byte
* cur
= parser
->cursor
;
1089 FT_Byte
* limit
= parser
->limit
;
1092 /* skip whitespace */
1093 while ( is_space( *cur
) )
1098 FT_ERROR(( "parse_encoding: out of bounds!\n" ));
1099 parser
->error
= T1_Err_Invalid_File_Format
;
1104 /* if we have a number, then the encoding is an array, */
1105 /* and we must load it now */
1106 if ( (FT_Byte
)( *cur
- '0' ) < 10 )
1108 T1_Encoding
* encode
= &face
->type1
.encoding
;
1110 Z1_Table
* char_table
= &loader
->encoding_table
;
1111 FT_Memory memory
= parser
->memory
;
1115 /* read the number of entries in the encoding, should be 256 */
1116 count
= Z1_ToInt( parser
);
1117 if ( parser
->error
)
1120 /* we use a Z1_Table to store our charnames */
1121 encode
->num_chars
= count
;
1122 if ( ALLOC_ARRAY( encode
->char_index
, count
, FT_Short
) ||
1123 ALLOC_ARRAY( encode
->char_name
, count
, FT_String
* ) ||
1124 ( error
= Z1_New_Table( char_table
, count
, memory
) ) != 0 )
1126 parser
->error
= error
;
1130 /* Now, we will need to read a record of the form */
1131 /* ... charcode /charname ... for each entry in our table */
1133 /* We simply look for a number followed by an immediate */
1134 /* name. Note that this ignores correctly the sequence */
1135 /* that is often seen in type1 fonts: */
1137 /* 0 1 255 { 1 index exch /.notdef put } for dup */
1139 /* used to clean the encoding array before anything else. */
1141 /* We stop when we encounter a `def'. */
1143 cur
= parser
->cursor
;
1144 limit
= parser
->limit
;
1147 for ( ; cur
< limit
; )
1154 /* we stop when we encounter a `def' */
1155 if ( c
== 'd' && cur
+ 3 < limit
)
1157 if ( cur
[1] == 'e' &&
1159 is_space(cur
[-1]) &&
1162 FT_TRACE6(( "encoding end\n" ));
1167 /* otherwise, we must find a number before anything else */
1168 if ( (FT_Byte
)( c
- '0' ) < 10 )
1173 parser
->cursor
= cur
;
1174 charcode
= Z1_ToInt( parser
);
1175 cur
= parser
->cursor
;
1177 /* skip whitespace */
1178 while ( cur
< limit
&& is_space( *cur
) )
1181 if ( cur
< limit
&& *cur
== '/' )
1183 /* bingo, we have an immediate name -- it must be a */
1184 /* character name */
1185 FT_Byte
* cur2
= cur
+ 1;
1189 while ( cur2
< limit
&& is_alpha( *cur2
) )
1192 len
= cur2
- cur
- 1;
1194 parser
->error
= Z1_Add_Table( char_table
, charcode
,
1196 char_table
->elements
[charcode
][len
] = '\0';
1197 if ( parser
->error
)
1207 face
->type1
.encoding_type
= t1_encoding_array
;
1208 parser
->cursor
= cur
;
1210 /* Otherwise, we should have either `StandardEncoding' or */
1211 /* `ExpertEncoding' */
1214 if ( cur
+ 17 < limit
&&
1215 strncmp( (const char*)cur
, "StandardEncoding", 16 ) == 0 )
1216 face
->type1
.encoding_type
= t1_encoding_standard
;
1218 else if ( cur
+ 15 < limit
&&
1219 strncmp( (const char*)cur
, "ExpertEncoding", 14 ) == 0 )
1220 face
->type1
.encoding_type
= t1_encoding_expert
;
1224 FT_ERROR(( "parse_encoding: invalid token!\n" ));
1225 parser
->error
= T1_Err_Invalid_File_Format
;
1232 void parse_subrs( T1_Face face
,
1235 Z1_Parser
* parser
= &loader
->parser
;
1236 Z1_Table
* table
= &loader
->subrs
;
1237 FT_Memory memory
= parser
->memory
;
1242 loader
->num_subrs
= Z1_ToInt( parser
);
1243 if ( parser
->error
)
1246 /* position the parser right before the `dup' of the first subr */
1247 skip_whitespace( parser
);
1248 skip_blackspace( parser
); /* `array' */
1249 skip_whitespace( parser
);
1251 /* initialize subrs array */
1252 error
= Z1_New_Table( table
, loader
->num_subrs
, memory
);
1256 /* the format is simple: */
1258 /* `index' + binary data */
1261 for ( n
= 0; n
< loader
->num_subrs
; n
++ )
1267 /* If the next token isn't `dup', we are also done. This */
1268 /* happens when there are `holes' in the Subrs array. */
1269 if ( strncmp( (char*)parser
->cursor
, "dup", 3 ) != 0 )
1272 index
= Z1_ToInt( parser
);
1274 if ( !read_binary_data( parser
, &size
, &base
) )
1277 /* The binary string is followed by one token, e.g. `NP' */
1278 /* (bound to `noaccess put') or by two separate tokens: */
1279 /* `noaccess' & `put'. We position the parser right */
1280 /* before the next `dup', if any. */
1281 skip_whitespace( parser
);
1282 skip_blackspace( parser
); /* `NP' or `I' or `noaccess' */
1283 skip_whitespace( parser
);
1285 if ( strncmp( (char*)parser
->cursor
, "put", 3 ) == 0 )
1287 skip_blackspace( parser
); /* skip `put' */
1288 skip_whitespace( parser
);
1291 /* some fonts use a value of -1 for lenIV to indicate that */
1292 /* the charstrings are unencoded */
1294 /* thanks to Tom Kacvinsky for pointing this out */
1296 if ( face
->type1
.private_dict
.lenIV
>= 0 )
1298 Z1_Decrypt( base
, size
, 4330 );
1299 size
-= face
->type1
.private_dict
.lenIV
;
1300 base
+= face
->type1
.private_dict
.lenIV
;
1303 error
= Z1_Add_Table( table
, index
, base
, size
);
1310 parser
->error
= error
;
1315 void parse_charstrings( T1_Face face
,
1318 Z1_Parser
* parser
= &loader
->parser
;
1319 Z1_Table
* code_table
= &loader
->charstrings
;
1320 Z1_Table
* name_table
= &loader
->glyph_names
;
1321 FT_Memory memory
= parser
->memory
;
1325 FT_Byte
* limit
= parser
->limit
;
1329 loader
->num_glyphs
= Z1_ToInt( parser
);
1330 if ( parser
->error
)
1333 /* initialize tables */
1334 error
= Z1_New_Table( code_table
, loader
->num_glyphs
, memory
) ||
1335 Z1_New_Table( name_table
, loader
->num_glyphs
, memory
);
1346 /* the format is simple: */
1347 /* `/glyphname' + binary data */
1349 /* note that we stop when we find a `def' */
1351 skip_whitespace( parser
);
1353 cur
= parser
->cursor
;
1357 /* we stop when we find a `def' or `end' keyword */
1371 skip_blackspace( parser
);
1374 FT_Byte
* cur2
= cur
+ 1;
1378 while ( cur2
< limit
&& is_alpha( *cur2
) )
1380 len
= cur2
- cur
- 1;
1382 error
= Z1_Add_Table( name_table
, n
, cur
+ 1, len
+ 1 );
1386 /* add a trailing zero to the name table */
1387 name_table
->elements
[n
][len
] = '\0';
1389 parser
->cursor
= cur2
;
1390 if ( !read_binary_data( parser
, &size
, &base
) )
1393 if ( face
->type1
.private_dict
.lenIV
>= 0 )
1395 Z1_Decrypt( base
, size
, 4330 );
1396 size
-= face
->type1
.private_dict
.lenIV
;
1397 base
+= face
->type1
.private_dict
.lenIV
;
1400 error
= Z1_Add_Table( code_table
, n
, base
, size
);
1405 if ( n
>= loader
->num_glyphs
)
1409 loader
->num_glyphs
= n
;
1413 parser
->error
= error
;
1418 const Z1_KeyWord t1_keywords
[] =
1421 #ifdef FT_FLAT_COMPILE
1423 #include "z1tokens.h"
1427 #include <type1z/z1tokens.h>
1431 /* now add the special functions... */
1432 Z1_KEYWORD_CALLBACK( "FontName", parse_font_name
),
1433 Z1_KEYWORD_CALLBACK( "FontBBox", parse_font_bbox
),
1434 Z1_KEYWORD_CALLBACK( "FontMatrix", parse_font_matrix
),
1435 Z1_KEYWORD_CALLBACK( "Encoding", parse_encoding
),
1436 Z1_KEYWORD_CALLBACK( "Subrs", parse_subrs
),
1437 Z1_KEYWORD_CALLBACK( "CharStrings", parse_charstrings
),
1439 #ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
1440 Z1_KEYWORD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions
),
1441 Z1_KEYWORD_CALLBACK( "BlendDesignMap", parse_blend_design_map
),
1442 Z1_KEYWORD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types
),
1443 Z1_KEYWORD_CALLBACK( "WeightVector", parse_weight_vector
),
1444 Z1_KEYWORD_CALLBACK( "shareddict", parse_shared_dict
),
1447 Z1_KEYWORD_CALLBACK( 0, 0 )
1452 FT_Error
parse_dict( T1_Face face
,
1457 Z1_Parser
* parser
= &loader
->parser
;
1460 parser
->cursor
= base
;
1461 parser
->limit
= base
+ size
;
1465 FT_Byte
* cur
= base
;
1466 FT_Byte
* limit
= cur
+ size
;
1469 for ( ; cur
< limit
; cur
++ )
1471 /* look for `FontDirectory', which causes problems on some fonts */
1472 if ( *cur
== 'F' && cur
+ 25 < limit
&&
1473 strncmp( (char*)cur
, "FontDirectory", 13 ) == 0 )
1478 /* skip the `FontDirectory' keyword */
1482 /* lookup the `known' keyword */
1483 while ( cur
< limit
&& *cur
!= 'k' &&
1484 strncmp( (char*)cur
, "known", 5 ) )
1492 /* skip the `known' keyword and the token following it */
1494 loader
->parser
.cursor
= cur
;
1495 Z1_ToToken( &loader
->parser
, &token
);
1497 /* if the last token was an array, skip it! */
1498 if ( token
.type
== t1_token_array
)
1499 cur2
= parser
->cursor
;
1503 /* look for immediates */
1504 else if ( *cur
== '/' && cur
+ 2 < limit
)
1512 while ( cur2
< limit
&& is_alpha( *cur2
) )
1516 if ( len
> 0 && len
< 22 )
1518 if ( !loader
->fontdata
)
1520 if ( strncmp( (char*)cur
, "FontInfo", 8 ) == 0 )
1521 loader
->fontdata
= 1;
1525 /* now, compare the immediate name to the keyword table */
1526 Z1_KeyWord
* keyword
= (Z1_KeyWord
*)t1_keywords
;
1534 name
= (FT_Byte
*)keyword
->name
;
1538 if ( cur
[0] == name
[0] &&
1539 len
== (FT_Int
)strlen( (const char*)name
) )
1544 for ( n
= 1; n
< len
; n
++ )
1545 if ( cur
[n
] != name
[n
] )
1550 /* we found it -- run the parsing callback! */
1551 parser
->cursor
= cur2
;
1552 skip_whitespace( parser
);
1553 parser
->error
= t1_load_keyword( face
, loader
, keyword
);
1554 if ( parser
->error
)
1555 return parser
->error
;
1557 cur
= parser
->cursor
;
1568 return parser
->error
;
1573 void t1_init_loader( Z1_Loader
* loader
,
1578 MEM_Set( loader
, 0, sizeof ( *loader
) );
1579 loader
->num_glyphs
= 0;
1580 loader
->num_chars
= 0;
1582 /* initialize the tables -- simply set their `init' field to 0 */
1583 loader
->encoding_table
.init
= 0;
1584 loader
->charstrings
.init
= 0;
1585 loader
->glyph_names
.init
= 0;
1586 loader
->subrs
.init
= 0;
1587 loader
->fontdata
= 0;
1592 void t1_done_loader( Z1_Loader
* loader
)
1594 Z1_Parser
* parser
= &loader
->parser
;
1597 /* finalize tables */
1598 Z1_Release_Table( &loader
->encoding_table
);
1599 Z1_Release_Table( &loader
->charstrings
);
1600 Z1_Release_Table( &loader
->glyph_names
);
1601 Z1_Release_Table( &loader
->subrs
);
1603 /* finalize parser */
1604 Z1_Done_Parser( parser
);
1609 FT_Error
Z1_Open_Face( T1_Face face
)
1613 T1_Font
* type1
= &face
->type1
;
1617 t1_init_loader( &loader
, face
);
1620 type1
->private_dict
.lenIV
= 4;
1622 parser
= &loader
.parser
;
1623 error
= Z1_New_Parser( parser
, face
->root
.stream
, face
->root
.memory
);
1627 error
= parse_dict( face
, &loader
, parser
->base_dict
, parser
->base_len
);
1631 error
= Z1_Get_Private_Dict( parser
);
1635 error
= parse_dict( face
, &loader
, parser
->private_dict
,
1636 parser
->private_len
);
1640 /* now, propagate the subrs, charstrings, and glyphnames tables */
1641 /* to the Type1 data */
1642 type1
->num_glyphs
= loader
.num_glyphs
;
1644 if ( !loader
.subrs
.init
)
1646 FT_ERROR(( "Z1_Open_Face: no subrs array in face!\n" ));
1647 error
= T1_Err_Invalid_File_Format
;
1650 if ( !loader
.charstrings
.init
)
1652 FT_ERROR(( "Z1_Open_Face: no charstrings array in face!\n" ));
1653 error
= T1_Err_Invalid_File_Format
;
1656 loader
.subrs
.init
= 0;
1657 type1
->num_subrs
= loader
.num_subrs
;
1658 type1
->subrs_block
= loader
.subrs
.block
;
1659 type1
->subrs
= loader
.subrs
.elements
;
1660 type1
->subrs_len
= loader
.subrs
.lengths
;
1662 loader
.charstrings
.init
= 0;
1663 type1
->charstrings_block
= loader
.charstrings
.block
;
1664 type1
->charstrings
= loader
.charstrings
.elements
;
1665 type1
->charstrings_len
= loader
.charstrings
.lengths
;
1667 /* we copy the glyph names `block' and `elements' fields; */
1668 /* the `lengths' field must be released later */
1669 type1
->glyph_names_block
= loader
.glyph_names
.block
;
1670 type1
->glyph_names
= (FT_String
**)loader
.glyph_names
.elements
;
1671 loader
.glyph_names
.block
= 0;
1672 loader
.glyph_names
.elements
= 0;
1674 /* we must now build type1.encoding when we have a custom */
1676 if ( type1
->encoding_type
== t1_encoding_array
)
1678 FT_Int charcode
, index
, min_char
, max_char
;
1680 FT_Byte
* glyph_name
;
1683 /* OK, we do the following: for each element in the encoding */
1684 /* table, look up the index of the glyph having the same name */
1685 /* the index is then stored in type1.encoding.char_index, and */
1686 /* a the name to type1.encoding.char_name */
1692 for ( ; charcode
< loader
.encoding_table
.num_elems
; charcode
++ )
1694 type1
->encoding
.char_index
[charcode
] = 0;
1695 type1
->encoding
.char_name
[charcode
] = ".notdef";
1697 char_name
= loader
.encoding_table
.elements
[charcode
];
1699 for ( index
= 0; index
< type1
->num_glyphs
; index
++ )
1701 glyph_name
= (FT_Byte
*)type1
->glyph_names
[index
];
1702 if ( strcmp( (const char*)char_name
,
1703 (const char*)glyph_name
) == 0 )
1705 type1
->encoding
.char_index
[charcode
] = index
;
1706 type1
->encoding
.char_name
[charcode
] = (char*)glyph_name
;
1708 if (charcode
< min_char
) min_char
= charcode
;
1709 if (charcode
> max_char
) max_char
= charcode
;
1714 type1
->encoding
.code_first
= min_char
;
1715 type1
->encoding
.code_last
= max_char
;
1716 type1
->encoding
.num_chars
= loader
.num_chars
;
1720 t1_done_loader( &loader
);