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 <freetype/src/type1/t1tokens.h>
32 #include <freetype/src/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;