1 /***************************************************************************/
5 /* 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 #include <freetype/config/ftconfig.h>
20 #include <freetype/internal/ftdebug.h>
21 #include <freetype/internal/t1types.h>
24 #ifdef FT_FLAT_COMPILE
31 #include <type1/t1tokens.h>
32 #include <type1/t1parse.h>
39 #include <string.h> /* for strncpy(), strncmp(), strlen() */
42 /*************************************************************************/
44 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
45 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
46 /* messages during execution. */
49 #define FT_COMPONENT trace_t1load
52 typedef FT_Error (*T1_Parse_Func
)( T1_Parser
* parser
);
55 /*************************************************************************/
61 /* Initializes a given parser object to build a given T1_Face. */
64 /* parser :: A handle to the newly built parser object. */
67 /* face :: A handle to the target Type 1 face object. */
69 /* tokenizer :: A handle to the target Type 1 token manager. */
72 void Init_T1_Parser( T1_Parser
* parser
,
74 T1_Tokenizer tokenizer
)
78 parser
->tokenizer
= tokenizer
;
79 parser
->top
= parser
->stack
;
80 parser
->limit
= parser
->stack
+ T1_MAX_STACK_DEPTH
;
82 parser
->state_index
= 0;
83 parser
->state_stack
[0] = dict_none
;
85 parser
->encoding_type
= t1_encoding_none
;
86 parser
->encoding_names
= 0;
87 parser
->encoding_offsets
= 0;
88 parser
->encoding_lengths
= 0;
90 parser
->dump_tokens
= 0;
91 face
->type1
.private_dict
.lenIV
= 4; /* XXX : is it sure? */
95 /*************************************************************************/
101 /* Grabs the next significant token from a parser's input stream. */
102 /* This function ignores a number of tokens, and translates */
103 /* alternate forms into their common ones. */
106 /* parser :: A handle to the source parser. */
109 /* token :: The extracted token descriptor. */
112 /* FreeTyoe error code. 0 means success. */
115 FT_Error
Next_T1_Token( T1_Parser
* parser
,
119 T1_Tokenizer tokzer
= parser
->tokenizer
;
123 error
= Read_Token( tokzer
);
127 /* we now must ignore a number of tokens like `dup', `executeonly', */
128 /* `readonly', etc. */
129 *token
= tokzer
->token
;
130 if ( token
->kind
== tok_keyword
)
131 switch( token
->kind2
)
138 /* do nothing - loop */
141 /* we also translate some other keywords from their alternative */
142 /* to their `normal' form */
144 case key_NP_alternate
:
145 token
->kind2
= key_NP
;
148 case key_RD_alternate
:
149 token
->kind2
= key_RD
;
152 case key_ND_alternate
:
153 token
->kind2
= key_ND
;
160 #if defined( FT_DEBUG_LEVEL_ERROR ) || defined( FT_DEBUG_LEVEL_TRACE )
162 /* Dump the token when requested. This feature is only available */
163 /* in the `error' and `trace' debug levels. */
164 if ( parser
->dump_tokens
)
166 FT_String temp_string
[128];
173 strncpy( temp_string
,
174 (FT_String
*)tokzer
->base
+ token
->start
,
176 temp_string
[len
] = '\0';
177 FT_ERROR(( "%s\n", temp_string
));
180 #endif /* FT_DEBUG_LEVEL_ERROR or FT_DEBUG_LEVEL_TRACE */
187 FT_Error
Expect_Keyword( T1_Parser
* parser
,
188 T1_TokenType keyword
)
194 error
= Next_T1_Token( parser
, &token
);
198 if ( token
.kind
!= tok_keyword
||
199 token
.kind2
!= keyword
)
201 error
= T1_Err_Syntax_Error
;
202 FT_ERROR(( "Expect_Keyword: keyword `%s' expected.\n",
203 t1_keywords
[keyword
- key_first_
] ));
212 FT_Error
Expect_Keyword2( T1_Parser
* parser
,
213 T1_TokenType keyword1
,
214 T1_TokenType keyword2
)
220 error
= Next_T1_Token( parser
, &token
);
224 if ( token
.kind
!= tok_keyword
||
225 ( token
.kind2
!= keyword1
&&
226 token
.kind2
!= keyword2
) )
228 error
= T1_Err_Syntax_Error
;
229 FT_ERROR(( "Expect_Keyword2: keyword `%s' or `%s' expected.\n",
230 t1_keywords
[keyword1
- key_first_
],
231 t1_keywords
[keyword2
- key_first_
] ));
240 void Parse_Encoding( T1_Parser
* parser
)
242 T1_Token
* token
= parser
->top
+1;
243 FT_Memory memory
= parser
->face
->root
.memory
;
244 T1_Encoding
* encode
= &parser
->face
->type1
.encoding
;
248 if ( token
->kind
== tok_keyword
&&
249 ( token
->kind2
== key_StandardEncoding
||
250 token
->kind2
== key_ExpertEncoding
) )
252 encode
->num_chars
= 256;
253 encode
->code_first
= 32;
254 encode
->code_last
= 255;
256 if ( ALLOC_ARRAY( encode
->char_index
, 256, FT_Short
) )
259 encode
->char_name
= 0; /* no need to store glyph names */
261 /* Now copy the encoding */
262 switch ( token
->kind2
)
264 case key_ExpertEncoding
:
265 parser
->encoding_type
= t1_encoding_expert
;
269 parser
->encoding_type
= t1_encoding_standard
;
275 FT_ERROR(( "Parse_Encoding: invalid encoding type\n" ));
276 error
= T1_Err_Syntax_Error
;
280 parser
->error
= error
;
284 /*************************************************************************/
287 /* IMPLEMENTATION OF THE `DEF' KEYWORD DEPENDING ON */
288 /* CURRENT DICTIONARY STATE */
291 /*************************************************************************/
294 /*************************************************************************/
300 /* This function performs a `def' if in the Font dictionary. Its */
301 /* purpose is to build the T1_Face attributes directly from the */
305 /* parser :: A handle to the current parser. */
308 /* FreeType error code. 0 means success. */
311 FT_Error
Do_Def_Font( T1_Parser
* parser
)
313 T1_Token
* top
= parser
->top
;
314 T1_Face face
= parser
->face
;
315 T1_Font
* type1
= &face
->type1
;
318 switch ( top
[0].kind2
)
321 /* in some cases, the /FontName is an immediate like */
322 /* /TimesNewRoman. In this case, we simply copy the */
323 /* token string (without the /). */
324 if ( top
[1].kind
== tok_immediate
)
326 FT_Memory memory
= parser
->tokenizer
->memory
;
328 FT_Int len
= top
[1].len
;
331 if ( ALLOC( type1
->font_name
, len
+ 1 ) )
333 parser
->error
= error
;
337 MEM_Copy( type1
->font_name
,
338 parser
->tokenizer
->base
+ top
[1].start
,
340 type1
->font_name
[len
] = '\0';
343 type1
->font_name
= CopyString( parser
);
347 Parse_Encoding( parser
);
351 type1
->paint_type
= (FT_Byte
)CopyInteger( parser
);
355 type1
->font_type
= (FT_Byte
)CopyInteger( parser
);
359 CopyMatrix( parser
, &type1
->font_matrix
);
363 CopyBBox( parser
, &type1
->font_bbox
);
367 type1
->private_dict
.unique_id
= CopyInteger( parser
);
370 case imm_StrokeWidth
:
371 type1
->stroke_width
= CopyInteger( parser
);
375 type1
->font_id
= CopyInteger( parser
);
379 /* ignore all other things */
380 parser
->error
= T1_Err_Ok
;
383 return parser
->error
;
387 /*************************************************************************/
390 /* Do_Def_FontInfo */
393 /* This function performs a `def' if in the FontInfo dictionary. Its */
394 /* purpose is to build the T1_FontInfo structure directly from the */
398 /* parser :: A handle to the current parser. */
401 /* FreeTyoe error code. 0 means success. */
404 FT_Error
Do_Def_FontInfo( T1_Parser
* parser
)
406 T1_Token
* top
= parser
->top
;
407 T1_FontInfo
* info
= &parser
->face
->type1
.font_info
;
410 switch ( top
[0].kind2
)
413 info
->version
= CopyString( parser
);
417 info
->notice
= CopyString( parser
);
421 info
->full_name
= CopyString( parser
);
425 info
->family_name
= CopyString( parser
);
429 info
->weight
= CopyString( parser
);
432 case imm_ItalicAngle
:
433 info
->italic_angle
= CopyInteger( parser
);
436 case imm_isFixedPitch
:
437 info
->is_fixed_pitch
= CopyBoolean( parser
);
440 case imm_UnderlinePosition
:
441 info
->underline_position
= (FT_Short
)CopyInteger( parser
);
444 case imm_UnderlineThickness
:
445 info
->underline_thickness
= (FT_Short
)CopyInteger( parser
);
449 /* ignore all other things */
450 parser
->error
= T1_Err_Ok
;
453 return parser
->error
;
457 /*************************************************************************/
463 /* This function performs a `def' if in the Private dictionary. Its */
464 /* purpose is to build the T1_Private structure directly from the */
468 /* parser :: A handle to the current parser. */
471 /* FreeTyoe error code. 0 means success. */
474 FT_Error
Do_Def_Private( T1_Parser
* parser
)
476 T1_Token
* top
= parser
->top
;
477 T1_Private
* priv
= &parser
->face
->type1
.private_dict
;
480 switch ( top
[0].kind2
)
482 /* Ignore the definitions of RD, NP, ND, and their alternate forms */
484 case imm_RD_alternate
:
486 case imm_ND_alternate
:
488 case imm_NP_alternate
:
489 parser
->error
= T1_Err_Ok
;
493 CopyArray( parser
, &priv
->num_blue_values
,
494 priv
->blue_values
, 14 );
498 CopyArray( parser
, &priv
->num_other_blues
,
499 priv
->other_blues
, 10 );
502 case imm_FamilyBlues
:
503 CopyArray( parser
, &priv
->num_family_blues
,
504 priv
->family_blues
, 14 );
507 case imm_FamilyOtherBlues
:
508 CopyArray( parser
, &priv
->num_family_other_blues
,
509 priv
->family_other_blues
, 10 );
513 priv
->blue_scale
= CopyFloat( parser
, 0x10000L
);
517 priv
->blue_shift
= CopyInteger( parser
);
521 priv
->blue_fuzz
= CopyInteger( parser
);
525 CopyArray( parser
, 0, (FT_Short
*)&priv
->standard_width
, 1 );
529 CopyArray( parser
, 0, (FT_Short
*)&priv
->standard_height
, 1 );
533 CopyArray( parser
, &priv
->num_snap_widths
,
534 priv
->snap_widths
, 12 );
538 CopyArray( parser
, &priv
->num_snap_heights
,
539 priv
->snap_heights
, 12 );
543 priv
->force_bold
= CopyBoolean( parser
);
546 case imm_LanguageGroup
:
547 priv
->language_group
= CopyInteger( parser
);
551 priv
->password
= CopyInteger( parser
);
555 priv
->unique_id
= CopyInteger( parser
);
559 priv
->lenIV
= CopyInteger( parser
);
563 CopyArray( parser
, 0, priv
->min_feature
, 2 );
567 /* ignore all other things */
568 parser
->error
= T1_Err_Ok
;
571 return parser
->error
;
575 /*************************************************************************/
581 /* This function returns a simple syntax error when invoked. It is */
582 /* used for the `def' keyword if in the `encoding', `subrs', */
583 /* `othersubrs', and `charstrings' dictionary states. */
586 /* parser :: A handle to the current parser. */
589 /* FreeType error code. 0 means success. */
592 FT_Error
Do_Def_Error( T1_Parser
* parser
)
594 FT_ERROR(( "Do_Def_Error:" ));
595 FT_ERROR(( " `def' keyword encountered in bad dictionary/array\n" ));
597 parser
->error
= T1_Err_Syntax_Error
;
599 return parser
->error
;
604 FT_Error
Do_Def_Ignore( T1_Parser
* parser
)
612 T1_Parse_Func def_funcs
[dict_max
] =
628 /*************************************************************************/
631 /* IMPLEMENTATION OF THE `PUT' KEYWORD DEPENDING ON */
632 /* CURRENT DICTIONARY STATE */
635 /*************************************************************************/
638 /*************************************************************************/
641 /* Do_Put_Encoding */
644 /* This function performs a `put' if in the Encoding array. The */
645 /* glyph name is copied into the T1 recorder, and the charcode and */
646 /* glyph name pointer are written into the face object encoding. */
649 /* parser :: A handle to the current parser. */
652 /* FreeType error code. 0 means success. */
655 FT_Error
Do_Put_Encoding( T1_Parser
* parser
)
657 FT_Error error
= T1_Err_Ok
;
658 T1_Face face
= parser
->face
;
659 T1_Token
* top
= parser
->top
;
660 T1_Encoding
* encode
= &face
->type1
.encoding
;
664 /* record and check the character code */
665 if ( top
[0].kind
!= tok_number
)
667 FT_TRACE4(( "Do_Put_Encoding: number expected\n" ));
670 index
= (FT_Int
)CopyInteger( parser
);
672 return parser
->error
;
674 if ( index
< 0 || index
>= encode
->num_chars
)
676 FT_TRACE4(( "Do_Put_Encoding: invalid character code\n" ));
680 /* record the immediate name */
681 if ( top
[1].kind
!= tok_immediate
)
683 FT_TRACE4(( "Do_Put_Encoding: immediate name expected\n" ));
687 /* if the glyph name is `.notdef', store a NULL char name; */
688 /* otherwise, record the glyph name */
689 if ( top
[1].kind
== imm_notdef
)
691 parser
->table
.elements
[index
] = 0;
692 parser
->table
.lengths
[index
] = 0;
696 FT_String temp_name
[128];
697 T1_Token
* token
= top
+ 1;
698 FT_Int len
= token
->len
- 1;
701 /* copy immediate name */
704 MEM_Copy( temp_name
, parser
->tokenizer
->base
+ token
->start
+ 1, len
);
705 temp_name
[len
] = '\0';
707 error
= T1_Add_Table( &parser
->table
, index
,
708 (FT_Byte
*)temp_name
, len
+ 1 );
710 /* adjust code_first and code_last */
711 if ( index
< encode
->code_first
) encode
->code_first
= index
;
712 if ( index
> encode
->code_last
) encode
->code_last
= index
;
717 /* ignore the error, and simply clear the stack */
718 FT_TRACE4(( "Do_Put_Encoding: invalid syntax encountered\n" ));
719 parser
->top
= parser
->stack
;
725 /*************************************************************************/
728 /* IMPLEMENTATION OF THE "RD" KEYWORD DEPENDING ON */
729 /* CURRENT DICTIONARY STATE */
732 /*************************************************************************/
735 /*************************************************************************/
741 /* This function performs an `RD' if in the Subrs dictionary. It */
742 /* simply records the array of bytecodes/charstrings corresponding to */
743 /* the sub-routine. */
746 /* parser :: A handle to the current parser. */
749 /* FreeType error code. 0 means success. */
752 FT_Error
Do_RD_Subrs( T1_Parser
* parser
)
754 FT_Error error
= T1_Err_Ok
;
755 T1_Face face
= parser
->face
;
756 T1_Token
* top
= parser
->top
;
757 T1_Tokenizer tokzer
= parser
->tokenizer
;
761 /* record and check the character code */
762 if ( top
[0].kind
!= tok_number
||
763 top
[1].kind
!= tok_number
)
765 FT_ERROR(( "Do_RD_Subrs: number expected\n" ));
768 index
= (FT_Int
)CopyInteger( parser
);
769 error
= parser
->error
;
773 count
= (FT_Int
)CopyInteger( parser
);
774 error
= parser
->error
;
778 if ( index
< 0 || index
>= face
->type1
.num_subrs
)
780 FT_ERROR(( "Do_RD_Subrs: invalid character code\n" ));
784 /* decrypt charstring and skip it */
786 FT_Byte
* base
= tokzer
->base
+ tokzer
->cursor
;
789 tokzer
->cursor
+= count
;
791 /* some fonts use a value of -1 for lenIV to indicate that */
792 /* the charstrings are unencoded. */
794 /* Thanks to Tom Kacvinsky for pointing this out. */
796 if ( face
->type1
.private_dict
.lenIV
>= 0 )
798 t1_decrypt( base
, count
, 4330 );
800 base
+= face
->type1
.private_dict
.lenIV
;
801 count
-= face
->type1
.private_dict
.lenIV
;
804 error
= T1_Add_Table( &parser
->table
, index
, base
, count
);
807 /* consume the closing NP or `put' */
808 error
= Expect_Keyword2( parser
, key_NP
, key_put
);
814 return T1_Err_Syntax_Error
;
818 /*************************************************************************/
821 /* Do_RD_CharStrings */
824 /* This function performs an `RD' if in the CharStrings dictionary. */
825 /* It simply records the array of bytecodes/charstrings corresponding */
826 /* to the glyph program string. */
829 /* parser :: A handle to the current parser. */
832 /* FreeType error code. 0 means success. */
835 FT_Error
Do_RD_Charstrings( T1_Parser
* parser
)
837 FT_Error error
= T1_Err_Ok
;
838 T1_Face face
= parser
->face
;
839 T1_Token
* top
= parser
->top
;
840 T1_Tokenizer tokzer
= parser
->tokenizer
;
844 /* check the character name argument */
845 if ( top
[0].kind
!= tok_immediate
)
847 FT_ERROR(( "Do_RD_Charstrings: immediate character name expected\n" ));
851 /* check the count argument */
852 if ( top
[1].kind
!= tok_number
)
854 FT_ERROR(( "Do_RD_Charstrings: number expected\n" ));
859 count
= (FT_Int
)CopyInteger( parser
);
860 error
= parser
->error
;
864 /* record the glyph name and get the corresponding glyph index */
865 if ( top
[0].kind2
== imm_notdef
)
869 FT_String temp_name
[128];
870 T1_Token
* token
= top
;
871 FT_Int len
= token
->len
- 1;
874 /* copy immediate name */
877 MEM_Copy( temp_name
, parser
->tokenizer
->base
+ token
->start
+ 1, len
);
878 temp_name
[len
] = '\0';
880 index
= parser
->cur_name
++;
881 error
= T1_Add_Table( &parser
->table
, index
* 2,
882 (FT_Byte
*)temp_name
, len
+ 1 );
887 /* decrypt and record charstring, then skip them */
889 FT_Byte
* base
= tokzer
->base
+ tokzer
->cursor
;
892 tokzer
->cursor
+= count
; /* skip */
894 if ( face
->type1
.private_dict
.lenIV
>= 0 )
896 t1_decrypt( base
, count
, 4330 );
898 base
+= face
->type1
.private_dict
.lenIV
;
899 count
-= face
->type1
.private_dict
.lenIV
;
902 error
= T1_Add_Table( &parser
->table
, index
* 2 + 1, base
, count
);
905 /* consume the closing `ND' */
907 error
= Expect_Keyword( parser
, key_ND
);
913 return T1_Err_Syntax_Error
;
918 FT_Error
Expect_Dict_Arguments( T1_Parser
* parser
,
920 T1_TokenType immediate
,
921 T1_DictState new_state
,
924 /* check that we have enough arguments in the stack, including */
925 /* the `dict' keyword */
926 if ( parser
->top
- parser
->stack
< num_args
)
928 FT_ERROR(( "Expect_Dict_Arguments: expecting at least %d arguments",
933 /* check that we have the correct immediate, if needed */
936 if ( parser
->top
[-2].kind
!= tok_immediate
||
937 parser
->top
[-2].kind2
!= immediate
)
939 FT_ERROR(( "Expect_Dict_Arguments: expecting `/%s' dictionary\n",
940 t1_immediates
[immediate
- imm_first_
] ));
945 parser
->args
= parser
->top
-1;
947 /* check that the count argument is a number */
948 if ( parser
->args
->kind
!= tok_number
)
950 FT_ERROR(( "Expect_Dict_Arguments:" ));
951 FT_ERROR(( " expecting numerical count argument for `dict'\n" ));
957 *count
= CopyInteger( parser
);
959 return parser
->error
;
962 /* save the dictionary state */
963 parser
->state_stack
[++parser
->state_index
] = new_state
;
965 /* consume the `begin' keyword and clear the stack */
966 parser
->top
-= num_args
;
967 return Expect_Keyword( parser
, key_begin
);
970 return T1_Err_Syntax_Error
;
975 FT_Error
Expect_Array_Arguments( T1_Parser
* parser
)
977 T1_Token
* top
= parser
->top
;
978 FT_Error error
= T1_Err_Ok
;
979 T1_DictState new_state
;
981 T1_Face face
= parser
->face
;
982 FT_Memory memory
= face
->root
.memory
;
985 /* Check arguments format */
986 if ( top
- parser
->stack
< 2 )
988 FT_ERROR(( "Expect_Array_Arguments: two arguments expected\n" ));
989 error
= T1_Err_Stack_Underflow
;
995 parser
->args
= top
+ 1;
997 if ( top
[0].kind
!= tok_immediate
)
999 FT_ERROR(( "Expect_Array_Arguments:" ));
1000 FT_ERROR(( " first argument must be an immediate name\n" ));
1004 if ( top
[1].kind
!= tok_number
)
1006 FT_ERROR(( "Expect_Array_Arguments:" ));
1007 FT_ERROR(( " second argument must be a number\n" ));
1011 count
= (FT_Int
)CopyInteger( parser
);
1013 /* Is this an array we know about? */
1014 switch ( top
[0].kind2
)
1018 T1_Encoding
* encode
= &face
->type1
.encoding
;
1021 new_state
= dict_encoding
;
1023 encode
->code_first
= count
;
1024 encode
->code_last
= 0;
1025 encode
->num_chars
= count
;
1027 /* Allocate the table of character indices. The table of */
1028 /* character names is allocated through init_t1_recorder(). */
1029 if ( ALLOC_ARRAY( encode
->char_index
, count
, FT_Short
) )
1032 error
= T1_New_Table( &parser
->table
, count
, memory
);
1036 parser
->encoding_type
= t1_encoding_array
;
1041 new_state
= dict_subrs
;
1042 face
->type1
.num_subrs
= count
;
1044 error
= T1_New_Table( &parser
->table
, count
, memory
);
1049 case imm_CharStrings
:
1050 new_state
= dict_charstrings
;
1054 new_state
= dict_unknown_array
;
1057 parser
->state_stack
[++parser
->state_index
] = new_state
;
1063 return T1_Err_Syntax_Error
;
1068 FT_Error
Finalize_Parsing( T1_Parser
* parser
)
1070 T1_Face face
= parser
->face
;
1071 T1_Font
* type1
= &face
->type1
;
1072 FT_Memory memory
= face
->root
.memory
;
1073 T1_Table
* strings
= &parser
->table
;
1074 PSNames_Interface
* psnames
= (PSNames_Interface
*)face
->psnames
;
1081 num_glyphs
= type1
->num_glyphs
= parser
->cur_name
;
1083 /* allocate glyph names and charstrings arrays */
1084 if ( ALLOC_ARRAY( type1
->glyph_names
, num_glyphs
, FT_String
* ) ||
1085 ALLOC_ARRAY( type1
->charstrings
, num_glyphs
, FT_Byte
* ) ||
1086 ALLOC_ARRAY( type1
->charstrings_len
, num_glyphs
, FT_Int
* ) )
1089 /* copy glyph names and charstrings offsets and lengths */
1090 type1
->charstrings_block
= strings
->block
;
1091 for ( n
= 0; n
< num_glyphs
; n
++ )
1093 type1
->glyph_names
[n
] = (FT_String
*)strings
->elements
[2 * n
];
1094 type1
->charstrings
[n
] = strings
->elements
[2 * n
+ 1];
1095 type1
->charstrings_len
[n
] = strings
->lengths
[2 * n
+ 1];
1098 /* now free the old tables */
1099 FREE( strings
->elements
);
1100 FREE( strings
->lengths
);
1104 FT_ERROR(( "Finalize_Parsing: `PSNames' module missing!\n" ));
1105 return T1_Err_Unimplemented_Feature
;
1108 /* compute encoding if required */
1109 if ( parser
->encoding_type
== t1_encoding_none
)
1111 FT_ERROR(( "Finalize_Parsing: no encoding specified in font file\n" ));
1112 return T1_Err_Syntax_Error
;
1117 T1_Encoding
* encode
= &type1
->encoding
;
1120 encode
->code_first
= encode
->num_chars
- 1;
1121 encode
->code_last
= 0;
1123 for ( n
= 0; n
< encode
->num_chars
; n
++ )
1130 switch ( parser
->encoding_type
)
1132 case t1_encoding_standard
:
1133 index
= psnames
->adobe_std_encoding
[n
];
1137 case t1_encoding_expert
:
1138 index
= psnames
->adobe_expert_encoding
[n
];
1144 names
= (FT_String
**)parser
->encoding_offsets
;
1147 encode
->char_index
[n
] = 0;
1155 name
= names
[index
];
1157 name
= (FT_String
*)psnames
->adobe_std_strings(index
);
1161 FT_Int len
= strlen( name
);
1164 /* lookup glyph index from name */
1165 for ( m
= 0; m
< num_glyphs
; m
++ )
1167 if ( strncmp( type1
->glyph_names
[m
], name
, len
) == 0 )
1169 encode
->char_index
[n
] = m
;
1174 if ( n
< encode
->code_first
) encode
->code_first
= n
;
1175 if ( n
> encode
->code_last
) encode
->code_last
= n
;
1180 parser
->encoding_type
= t1_encoding_none
;
1182 FREE( parser
->encoding_names
);
1183 FREE( parser
->encoding_lengths
);
1184 FREE( parser
->encoding_offsets
);
1191 /*************************************************************************/
1194 /* Parse_T1_FontProgram */
1197 /* Parses a given Type 1 font file and builds its face object. */
1200 /* parser :: A handle to the target parser object. */
1203 /* FreeType error code. 0 means success. */
1206 /* The parser contains a handle to the target face object. */
1209 FT_Error
Parse_T1_FontProgram( T1_Parser
* parser
)
1212 T1_Font
* type1
= &parser
->face
->type1
;
1219 T1_DictState dict_state
;
1223 error
= Next_T1_Token( parser
, &token
);
1225 dict_index
= parser
->state_index
;
1226 dict_state
= parser
->state_stack
[dict_index
];
1228 switch ( token
.kind
)
1230 /* a keyword has been detected */
1232 switch ( token
.kind2
)
1235 switch ( dict_state
)
1238 /* All right, we are beginning the font dictionary. */
1239 /* Check that we only have one number argument, then */
1240 /* consume the `begin' and change to `dict_font' */
1242 error
= Expect_Dict_Arguments( parser
, 1, tok_error
,
1247 /* clear stack from all the previous content. This */
1248 /* could be some stupid Postscript code. */
1249 parser
->top
= parser
->stack
;
1253 /* This must be the /FontInfo dictionary, so check */
1254 /* that we have at least two arguments, that they */
1255 /* are `/FontInfo' and a number, then change the */
1256 /* dictionary state. */
1257 error
= Expect_Dict_Arguments( parser
, 2, imm_FontInfo
,
1264 error
= Expect_Dict_Arguments( parser
, 2, imm_Private
,
1272 T1_Face face
= parser
->face
;
1276 error
= Expect_Dict_Arguments( parser
, 2, imm_CharStrings
,
1277 dict_charstrings
, &count
);
1281 type1
->num_glyphs
= count
;
1282 error
= T1_New_Table( &parser
->table
, count
* 2,
1283 face
->root
.memory
);
1287 /* record `.notdef' as the first glyph in the font */
1288 error
= T1_Add_Table( &parser
->table
, 0,
1289 (FT_Byte
*)".notdef", 8 );
1290 parser
->cur_name
= 1;
1291 /* XXX: DO SOMETHING HERE */
1296 /* All other uses are invalid */
1297 FT_ERROR(( "Parse_T1_FontProgram:" ));
1298 FT_ERROR(( " invalid use of `dict' keyword\n" ));
1304 /* Are we in an array yet? If so, raise an error */
1305 switch ( dict_state
)
1309 case dict_othersubrs
:
1310 case dict_charstrings
:
1311 case dict_unknown_array
:
1312 FT_ERROR(( "Parse_T1_FontProgram: nested array definitions\n" ));
1318 error
= Expect_Array_Arguments( parser
);
1326 /* Are we in an array? If so, finalize it. */
1327 switch ( dict_state
)
1329 case dict_encoding
: /* finish encoding array */
1330 /* copy table names to the face object */
1331 T1_Done_Table( &parser
->table
);
1333 parser
->encoding_names
= parser
->table
.block
;
1334 parser
->encoding_lengths
= parser
->table
.lengths
;
1335 parser
->encoding_offsets
= parser
->table
.elements
;
1337 parser
->state_index
--;
1341 /* copy recorder sub-routines */
1342 T1_Done_Table( &parser
->table
);
1344 parser
->subrs
= parser
->table
.block
;
1345 type1
->subrs
= parser
->table
.elements
;
1346 type1
->subrs_len
= parser
->table
.lengths
;
1347 type1
->subrs_block
= parser
->table
.block
;
1349 parser
->state_index
--;
1352 case dict_charstrings
:
1353 case dict_othersubrs
:
1354 case dict_unknown_array
:
1355 FT_ERROR(( "Parse_T1_FontProgram: unsupported array\n" ));
1359 default: /* normal `def' processing */
1360 /* Check that we have sufficient operands in the stack */
1361 if ( top
>= parser
->stack
+ 2 )
1363 /* Now check that the first operand is an immediate. */
1364 /* If so, call the appropriate `def' routine based */
1365 /* on the current parser state. */
1366 if ( top
[-2].kind
== tok_immediate
)
1369 parser
->args
= parser
->top
+ 1;
1370 error
= def_funcs
[dict_state
](parser
);
1374 /* This is an error, but some fonts contain */
1375 /* stupid Postscript code. We simply ignore */
1376 /* an invalid `def' by clearing the stack. */
1378 FT_ERROR(( "Parse_T1_FontProgram: immediate expected\n" ));
1381 parser
->top
= parser
->stack
;
1387 FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" ));
1388 goto Stack_Underflow
;
1394 if ( top
<= parser
->stack
)
1396 FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" ));
1397 goto Stack_Underflow
;
1400 /* simply ignore? */
1405 /* Check that we have sufficient operands in stack */
1406 if ( top
< parser
->stack
+ 2 )
1408 FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" ));
1409 goto Stack_Underflow
;
1413 parser
->args
= parser
->top
;
1415 switch ( dict_state
)
1418 error
= Do_Put_Encoding( parser
);
1423 case dict_unknown_array
: /* ignore the `put' */
1428 FT_ERROR(( "Parse_T1_FontProgram: invalid context\n" ));
1431 /* invalid context; simply ignore the `put' and */
1432 /* clear the stack (stupid Postscript code) */
1433 FT_TRACE4(( "Parse_T1_FontProgram: invalid context ignored.\n" ));
1434 parser
->top
= parser
->stack
;
1440 /* Check that we have sufficient operands in stack */
1441 if ( top
< parser
->stack
+ 2 )
1443 FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" ));
1444 goto Stack_Underflow
;
1448 parser
->args
= parser
->top
;
1449 switch ( dict_state
)
1452 error
= Do_RD_Subrs( parser
);
1457 case dict_charstrings
:
1458 error
= Do_RD_Charstrings( parser
);
1464 FT_ERROR(( "Parse_T1_FontProgram: invalid context\n" ));
1470 /* Were we in a dictionary or in an array? */
1471 if ( dict_index
<= 0 )
1473 FT_ERROR(( "Parse_T1_FontProgram: no dictionary defined\n" ));
1477 switch ( dict_state
)
1479 /* jump to the private dictionary if we are closing the */
1480 /* `/Font' dictionary */
1484 /* exit the parser when closing the CharStrings dictionary */
1485 case dict_charstrings
:
1486 return Finalize_Parsing( parser
);
1489 /* Pop the current dictionary state and return to previous */
1490 /* one. Consume the `def'. */
1492 /* Because some buggy fonts (BitStream) have incorrect */
1493 /* syntax, we never escape from the private dictionary */
1494 if ( dict_state
!= dict_private
)
1495 parser
->state_index
--;
1497 /* many fonts use `NP' instead of `def' or `put', so */
1498 /* we simply ignore the next token */
1500 error
= Expect_Keyword2( parser
, key_def
, key_put
);
1504 (void)Expect_Keyword2( parser
, key_def
, key_put
);
1510 /* check that we have four arguments and simply */
1512 if ( top
- parser
->stack
< 4 )
1514 FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" ));
1515 goto Stack_Underflow
;
1521 case key_currentdict
:
1523 parser
->state_index
= 0;
1524 parser
->state_stack
[0] = dict_none2
;
1525 error
= Open_PrivateDict( parser
->tokenizer
);
1532 case key_StandardEncoding
:
1533 case key_ExpertEncoding
:
1537 FT_ERROR(( "Parse_T1_FontProgram:" ));
1538 FT_ERROR(( " invalid keyword in context\n" ));
1539 error
= T1_Err_Syntax_Error
;
1543 /* check for the presence of `/BlendAxisTypes' -- we cannot deal */
1544 /* with multiple master fonts, so we must return a correct error */
1545 /* code to allow another driver to load them */
1547 if ( token
.kind2
== imm_BlendAxisTypes
)
1549 error
= FT_Err_Unknown_File_Format
;
1554 /* A number was detected */
1560 case tok_number
: /* push number on stack */
1563 if ( top
>= parser
->limit
)
1565 error
= T1_Err_Stack_Overflow
;
1569 *parser
->top
++ = token
;
1572 /* anything else is an error per se the spec, but we */
1573 /* frequently encounter stupid postscript code in fonts, */
1574 /* so just ignore them */
1576 error
= T1_Err_Ok
; /* ignore token */
1587 return T1_Err_Syntax_Error
;
1590 return T1_Err_Stack_Underflow
;