]> git.saurik.com Git - wxWidgets.git/blob - src/freetype/type1/t1load.c
Project file updates; cast in strconv.cpp to compile with VC++ 6
[wxWidgets.git] / src / freetype / type1 / t1load.c
1 /***************************************************************************/
2 /* */
3 /* t1load.c */
4 /* */
5 /* Type 1 font loader (body). */
6 /* */
7 /* Copyright 1996-2000 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
9 /* */
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. */
15 /* */
16 /***************************************************************************/
17
18
19 #include <freetype/config/ftconfig.h>
20 #include <freetype/internal/ftdebug.h>
21 #include <freetype/internal/t1types.h>
22
23
24 #ifdef FT_FLAT_COMPILE
25
26 #include "t1tokens.h"
27 #include "t1parse.h"
28
29 #else
30
31 #include <type1/t1tokens.h>
32 #include <type1/t1parse.h>
33
34 #endif
35
36
37 #include <stdio.h>
38
39 #include <string.h> /* for strncpy(), strncmp(), strlen() */
40
41
42 /*************************************************************************/
43 /* */
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. */
47 /* */
48 #undef FT_COMPONENT
49 #define FT_COMPONENT trace_t1load
50
51
52 typedef FT_Error (*T1_Parse_Func)( T1_Parser* parser );
53
54
55 /*************************************************************************/
56 /* */
57 /* <Function> */
58 /* Init_T1_Parser */
59 /* */
60 /* <Description> */
61 /* Initializes a given parser object to build a given T1_Face. */
62 /* */
63 /* <InOut> */
64 /* parser :: A handle to the newly built parser object. */
65 /* */
66 /* <Input> */
67 /* face :: A handle to the target Type 1 face object. */
68 /* */
69 /* tokenizer :: A handle to the target Type 1 token manager. */
70 /* */
71 LOCAL_FUNC
72 void Init_T1_Parser( T1_Parser* parser,
73 T1_Face face,
74 T1_Tokenizer tokenizer )
75 {
76 parser->error = 0;
77 parser->face = face;
78 parser->tokenizer = tokenizer;
79 parser->top = parser->stack;
80 parser->limit = parser->stack + T1_MAX_STACK_DEPTH;
81
82 parser->state_index = 0;
83 parser->state_stack[0] = dict_none;
84
85 parser->encoding_type = t1_encoding_none;
86 parser->encoding_names = 0;
87 parser->encoding_offsets = 0;
88 parser->encoding_lengths = 0;
89
90 parser->dump_tokens = 0;
91 face->type1.private_dict.lenIV = 4; /* XXX : is it sure? */
92 }
93
94
95 /*************************************************************************/
96 /* */
97 /* <Function> */
98 /* Next_T1_Token */
99 /* */
100 /* <Description> */
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. */
104 /* */
105 /* <Input> */
106 /* parser :: A handle to the source parser. */
107 /* */
108 /* <Output> */
109 /* token :: The extracted token descriptor. */
110 /* */
111 /* <Return> */
112 /* FreeTyoe error code. 0 means success. */
113 /* */
114 LOCAL_FUNC
115 FT_Error Next_T1_Token( T1_Parser* parser,
116 T1_Token* token )
117 {
118 FT_Error error;
119 T1_Tokenizer tokzer = parser->tokenizer;
120
121
122 L1:
123 error = Read_Token( tokzer );
124 if ( error )
125 return error;
126
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 )
132 {
133 case key_dup:
134 case key_execonly:
135 case key_readonly:
136 case key_noaccess:
137 case key_userdict:
138 /* do nothing - loop */
139 goto L1;
140
141 /* we also translate some other keywords from their alternative */
142 /* to their `normal' form */
143
144 case key_NP_alternate:
145 token->kind2 = key_NP;
146 break;
147
148 case key_RD_alternate:
149 token->kind2 = key_RD;
150 break;
151
152 case key_ND_alternate:
153 token->kind2 = key_ND;
154 break;
155
156 default:
157 ;
158 }
159
160 #if defined( FT_DEBUG_LEVEL_ERROR ) || defined( FT_DEBUG_LEVEL_TRACE )
161
162 /* Dump the token when requested. This feature is only available */
163 /* in the `error' and `trace' debug levels. */
164 if ( parser->dump_tokens )
165 {
166 FT_String temp_string[128];
167 FT_Int len;
168
169
170 len = token->len;
171 if ( len > 127 )
172 len = 127;
173 strncpy( temp_string,
174 (FT_String*)tokzer->base + token->start,
175 len );
176 temp_string[len] = '\0';
177 FT_ERROR(( "%s\n", temp_string ));
178 }
179
180 #endif /* FT_DEBUG_LEVEL_ERROR or FT_DEBUG_LEVEL_TRACE */
181
182 return T1_Err_Ok;
183 }
184
185
186 static
187 FT_Error Expect_Keyword( T1_Parser* parser,
188 T1_TokenType keyword )
189 {
190 T1_Token token;
191 FT_Error error;
192
193
194 error = Next_T1_Token( parser, &token );
195 if ( error )
196 goto Exit;
197
198 if ( token.kind != tok_keyword ||
199 token.kind2 != keyword )
200 {
201 error = T1_Err_Syntax_Error;
202 FT_ERROR(( "Expect_Keyword: keyword `%s' expected.\n",
203 t1_keywords[keyword - key_first_] ));
204 }
205
206 Exit:
207 return error;
208 }
209
210
211 static
212 FT_Error Expect_Keyword2( T1_Parser* parser,
213 T1_TokenType keyword1,
214 T1_TokenType keyword2 )
215 {
216 T1_Token token;
217 FT_Error error;
218
219
220 error = Next_T1_Token( parser, &token );
221 if ( error )
222 goto Exit;
223
224 if ( token.kind != tok_keyword ||
225 ( token.kind2 != keyword1 &&
226 token.kind2 != keyword2 ) )
227 {
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_] ));
232 }
233
234 Exit:
235 return error;
236 }
237
238
239 static
240 void Parse_Encoding( T1_Parser* parser )
241 {
242 T1_Token* token = parser->top+1;
243 FT_Memory memory = parser->face->root.memory;
244 T1_Encoding* encode = &parser->face->type1.encoding;
245 FT_Error error = 0;
246
247
248 if ( token->kind == tok_keyword &&
249 ( token->kind2 == key_StandardEncoding ||
250 token->kind2 == key_ExpertEncoding ) )
251 {
252 encode->num_chars = 256;
253 encode->code_first = 32;
254 encode->code_last = 255;
255
256 if ( ALLOC_ARRAY( encode->char_index, 256, FT_Short ) )
257 goto Exit;
258
259 encode->char_name = 0; /* no need to store glyph names */
260
261 /* Now copy the encoding */
262 switch ( token->kind2 )
263 {
264 case key_ExpertEncoding:
265 parser->encoding_type = t1_encoding_expert;
266 break;
267
268 default:
269 parser->encoding_type = t1_encoding_standard;
270 break;
271 }
272 }
273 else
274 {
275 FT_ERROR(( "Parse_Encoding: invalid encoding type\n" ));
276 error = T1_Err_Syntax_Error;
277 }
278
279 Exit:
280 parser->error = error;
281 }
282
283
284 /*************************************************************************/
285 /* */
286 /* */
287 /* IMPLEMENTATION OF THE `DEF' KEYWORD DEPENDING ON */
288 /* CURRENT DICTIONARY STATE */
289 /* */
290 /* */
291 /*************************************************************************/
292
293
294 /*************************************************************************/
295 /* */
296 /* <Function> */
297 /* Do_Def_Font */
298 /* */
299 /* <Description> */
300 /* This function performs a `def' if in the Font dictionary. Its */
301 /* purpose is to build the T1_Face attributes directly from the */
302 /* stream. */
303 /* */
304 /* <InOut> */
305 /* parser :: A handle to the current parser. */
306 /* */
307 /* <Return> */
308 /* FreeType error code. 0 means success. */
309 /* */
310 static
311 FT_Error Do_Def_Font( T1_Parser* parser )
312 {
313 T1_Token* top = parser->top;
314 T1_Face face = parser->face;
315 T1_Font* type1 = &face->type1;
316
317
318 switch ( top[0].kind2 )
319 {
320 case imm_FontName:
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 )
325 {
326 FT_Memory memory = parser->tokenizer->memory;
327 FT_Error error;
328 FT_Int len = top[1].len;
329
330
331 if ( ALLOC( type1->font_name, len + 1 ) )
332 {
333 parser->error = error;
334 return error;
335 }
336
337 MEM_Copy( type1->font_name,
338 parser->tokenizer->base + top[1].start,
339 len );
340 type1->font_name[len] = '\0';
341 }
342 else
343 type1->font_name = CopyString( parser );
344 break;
345
346 case imm_Encoding:
347 Parse_Encoding( parser );
348 break;
349
350 case imm_PaintType:
351 type1->paint_type = (FT_Byte)CopyInteger( parser );
352 break;
353
354 case imm_FontType:
355 type1->font_type = (FT_Byte)CopyInteger( parser );
356 break;
357
358 case imm_FontMatrix:
359 CopyMatrix( parser, &type1->font_matrix );
360 break;
361
362 case imm_FontBBox:
363 CopyBBox( parser, &type1->font_bbox );
364 break;
365
366 case imm_UniqueID:
367 type1->private_dict.unique_id = CopyInteger( parser );
368 break;
369
370 case imm_StrokeWidth:
371 type1->stroke_width = CopyInteger( parser );
372 break;
373
374 case imm_FontID:
375 type1->font_id = CopyInteger( parser );
376 break;
377
378 default:
379 /* ignore all other things */
380 parser->error = T1_Err_Ok;
381 }
382
383 return parser->error;
384 }
385
386
387 /*************************************************************************/
388 /* */
389 /* <Function> */
390 /* Do_Def_FontInfo */
391 /* */
392 /* <Description> */
393 /* This function performs a `def' if in the FontInfo dictionary. Its */
394 /* purpose is to build the T1_FontInfo structure directly from the */
395 /* stream. */
396 /* */
397 /* <InOut> */
398 /* parser :: A handle to the current parser. */
399 /* */
400 /* <Return> */
401 /* FreeTyoe error code. 0 means success. */
402 /* */
403 static
404 FT_Error Do_Def_FontInfo( T1_Parser* parser )
405 {
406 T1_Token* top = parser->top;
407 T1_FontInfo* info = &parser->face->type1.font_info;
408
409
410 switch ( top[0].kind2 )
411 {
412 case imm_version:
413 info->version = CopyString( parser );
414 break;
415
416 case imm_Notice:
417 info->notice = CopyString( parser );
418 break;
419
420 case imm_FullName:
421 info->full_name = CopyString( parser );
422 break;
423
424 case imm_FamilyName:
425 info->family_name = CopyString( parser );
426 break;
427
428 case imm_Weight:
429 info->weight = CopyString( parser );
430 break;
431
432 case imm_ItalicAngle:
433 info->italic_angle = CopyInteger( parser );
434 break;
435
436 case imm_isFixedPitch:
437 info->is_fixed_pitch = CopyBoolean( parser );
438 break;
439
440 case imm_UnderlinePosition:
441 info->underline_position = (FT_Short)CopyInteger( parser );
442 break;
443
444 case imm_UnderlineThickness:
445 info->underline_thickness = (FT_Short)CopyInteger( parser );
446 break;
447
448 default:
449 /* ignore all other things */
450 parser->error = T1_Err_Ok;
451 }
452
453 return parser->error;
454 }
455
456
457 /*************************************************************************/
458 /* */
459 /* <Function> */
460 /* Do_Def_Private */
461 /* */
462 /* <Description> */
463 /* This function performs a `def' if in the Private dictionary. Its */
464 /* purpose is to build the T1_Private structure directly from the */
465 /* stream. */
466 /* */
467 /* <InOut> */
468 /* parser :: A handle to the current parser. */
469 /* */
470 /* <Return> */
471 /* FreeTyoe error code. 0 means success. */
472 /* */
473 static
474 FT_Error Do_Def_Private( T1_Parser* parser )
475 {
476 T1_Token* top = parser->top;
477 T1_Private* priv = &parser->face->type1.private_dict;
478
479
480 switch ( top[0].kind2 )
481 {
482 /* Ignore the definitions of RD, NP, ND, and their alternate forms */
483 case imm_RD:
484 case imm_RD_alternate:
485 case imm_ND:
486 case imm_ND_alternate:
487 case imm_NP:
488 case imm_NP_alternate:
489 parser->error = T1_Err_Ok;
490 break;
491
492 case imm_BlueValues:
493 CopyArray( parser, &priv->num_blue_values,
494 priv->blue_values, 14 );
495 break;
496
497 case imm_OtherBlues:
498 CopyArray( parser, &priv->num_other_blues,
499 priv->other_blues, 10 );
500 break;
501
502 case imm_FamilyBlues:
503 CopyArray( parser, &priv->num_family_blues,
504 priv->family_blues, 14 );
505 break;
506
507 case imm_FamilyOtherBlues:
508 CopyArray( parser, &priv->num_family_other_blues,
509 priv->family_other_blues, 10 );
510 break;
511
512 case imm_BlueScale:
513 priv->blue_scale = CopyFloat( parser, 0x10000L );
514 break;
515
516 case imm_BlueShift:
517 priv->blue_shift = CopyInteger( parser );
518 break;
519
520 case imm_BlueFuzz:
521 priv->blue_fuzz = CopyInteger( parser );
522 break;
523
524 case imm_StdHW:
525 CopyArray( parser, 0, (FT_Short*)&priv->standard_width, 1 );
526 break;
527
528 case imm_StdVW:
529 CopyArray( parser, 0, (FT_Short*)&priv->standard_height, 1 );
530 break;
531
532 case imm_StemSnapH:
533 CopyArray( parser, &priv->num_snap_widths,
534 priv->snap_widths, 12 );
535 break;
536
537 case imm_StemSnapV:
538 CopyArray( parser, &priv->num_snap_heights,
539 priv->snap_heights, 12 );
540 break;
541
542 case imm_ForceBold:
543 priv->force_bold = CopyBoolean( parser );
544 break;
545
546 case imm_LanguageGroup:
547 priv->language_group = CopyInteger( parser );
548 break;
549
550 case imm_password:
551 priv->password = CopyInteger( parser );
552 break;
553
554 case imm_UniqueID:
555 priv->unique_id = CopyInteger( parser );
556 break;
557
558 case imm_lenIV:
559 priv->lenIV = CopyInteger( parser );
560 break;
561
562 case imm_MinFeature:
563 CopyArray( parser, 0, priv->min_feature, 2 );
564 break;
565
566 default:
567 /* ignore all other things */
568 parser->error = T1_Err_Ok;
569 }
570
571 return parser->error;
572 }
573
574
575 /*************************************************************************/
576 /* */
577 /* <Function> */
578 /* Do_Def_Error */
579 /* */
580 /* <Description> */
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. */
584 /* */
585 /* <InOut> */
586 /* parser :: A handle to the current parser. */
587 /* */
588 /* <Return> */
589 /* FreeType error code. 0 means success. */
590 /* */
591 static
592 FT_Error Do_Def_Error( T1_Parser* parser )
593 {
594 FT_ERROR(( "Do_Def_Error:" ));
595 FT_ERROR(( " `def' keyword encountered in bad dictionary/array\n" ));
596
597 parser->error = T1_Err_Syntax_Error;
598
599 return parser->error;
600 }
601
602
603 static
604 FT_Error Do_Def_Ignore( T1_Parser* parser )
605 {
606 FT_UNUSED( parser );
607 return T1_Err_Ok;
608 }
609
610
611 static
612 T1_Parse_Func def_funcs[dict_max] =
613 {
614 Do_Def_Error,
615 Do_Def_Font,
616 Do_Def_FontInfo,
617 Do_Def_Ignore,
618 Do_Def_Private,
619 Do_Def_Ignore,
620 Do_Def_Ignore,
621 Do_Def_Ignore,
622 Do_Def_Ignore,
623 Do_Def_Ignore,
624 Do_Def_Ignore,
625 };
626
627
628 /*************************************************************************/
629 /* */
630 /* */
631 /* IMPLEMENTATION OF THE `PUT' KEYWORD DEPENDING ON */
632 /* CURRENT DICTIONARY STATE */
633 /* */
634 /* */
635 /*************************************************************************/
636
637
638 /*************************************************************************/
639 /* */
640 /* <Function> */
641 /* Do_Put_Encoding */
642 /* */
643 /* <Description> */
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. */
647 /* */
648 /* <InOut> */
649 /* parser :: A handle to the current parser. */
650 /* */
651 /* <Return> */
652 /* FreeType error code. 0 means success. */
653 /* */
654 static
655 FT_Error Do_Put_Encoding( T1_Parser* parser )
656 {
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;
661 FT_Int index;
662
663
664 /* record and check the character code */
665 if ( top[0].kind != tok_number )
666 {
667 FT_TRACE4(( "Do_Put_Encoding: number expected\n" ));
668 goto Syntax_Error;
669 }
670 index = (FT_Int)CopyInteger( parser );
671 if ( parser->error )
672 return parser->error;
673
674 if ( index < 0 || index >= encode->num_chars )
675 {
676 FT_TRACE4(( "Do_Put_Encoding: invalid character code\n" ));
677 goto Syntax_Error;
678 }
679
680 /* record the immediate name */
681 if ( top[1].kind != tok_immediate )
682 {
683 FT_TRACE4(( "Do_Put_Encoding: immediate name expected\n" ));
684 goto Syntax_Error;
685 }
686
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 )
690 {
691 parser->table.elements[index] = 0;
692 parser->table.lengths [index] = 0;
693 }
694 else
695 {
696 FT_String temp_name[128];
697 T1_Token* token = top + 1;
698 FT_Int len = token->len - 1;
699
700
701 /* copy immediate name */
702 if ( len > 127 )
703 len = 127;
704 MEM_Copy( temp_name, parser->tokenizer->base + token->start + 1, len );
705 temp_name[len] = '\0';
706
707 error = T1_Add_Table( &parser->table, index,
708 (FT_Byte*)temp_name, len + 1 );
709
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;
713 }
714 return error;
715
716 Syntax_Error:
717 /* ignore the error, and simply clear the stack */
718 FT_TRACE4(( "Do_Put_Encoding: invalid syntax encountered\n" ));
719 parser->top = parser->stack;
720
721 return T1_Err_Ok;
722 }
723
724
725 /*************************************************************************/
726 /* */
727 /* */
728 /* IMPLEMENTATION OF THE "RD" KEYWORD DEPENDING ON */
729 /* CURRENT DICTIONARY STATE */
730 /* */
731 /* */
732 /*************************************************************************/
733
734
735 /*************************************************************************/
736 /* */
737 /* <Function> */
738 /* Do_RD_Subrs */
739 /* */
740 /* <Description> */
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. */
744 /* */
745 /* <InOut> */
746 /* parser :: A handle to the current parser. */
747 /* */
748 /* <Return> */
749 /* FreeType error code. 0 means success. */
750 /* */
751 static
752 FT_Error Do_RD_Subrs( T1_Parser* parser )
753 {
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;
758 FT_Int index, count;
759
760
761 /* record and check the character code */
762 if ( top[0].kind != tok_number ||
763 top[1].kind != tok_number )
764 {
765 FT_ERROR(( "Do_RD_Subrs: number expected\n" ));
766 goto Syntax_Error;
767 }
768 index = (FT_Int)CopyInteger( parser );
769 error = parser->error;
770 if ( error )
771 goto Exit;
772
773 count = (FT_Int)CopyInteger( parser );
774 error = parser->error;
775 if ( error )
776 goto Exit;
777
778 if ( index < 0 || index >= face->type1.num_subrs )
779 {
780 FT_ERROR(( "Do_RD_Subrs: invalid character code\n" ));
781 goto Syntax_Error;
782 }
783
784 /* decrypt charstring and skip it */
785 {
786 FT_Byte* base = tokzer->base + tokzer->cursor;
787
788
789 tokzer->cursor += count;
790
791 /* some fonts use a value of -1 for lenIV to indicate that */
792 /* the charstrings are unencoded. */
793 /* */
794 /* Thanks to Tom Kacvinsky for pointing this out. */
795 /* */
796 if ( face->type1.private_dict.lenIV >= 0 )
797 {
798 t1_decrypt( base, count, 4330 );
799
800 base += face->type1.private_dict.lenIV;
801 count -= face->type1.private_dict.lenIV;
802 }
803
804 error = T1_Add_Table( &parser->table, index, base, count );
805 }
806
807 /* consume the closing NP or `put' */
808 error = Expect_Keyword2( parser, key_NP, key_put );
809
810 Exit:
811 return error;
812
813 Syntax_Error:
814 return T1_Err_Syntax_Error;
815 }
816
817
818 /*************************************************************************/
819 /* */
820 /* <Function> */
821 /* Do_RD_CharStrings */
822 /* */
823 /* <Description> */
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. */
827 /* */
828 /* <InOut> */
829 /* parser :: A handle to the current parser. */
830 /* */
831 /* <Return> */
832 /* FreeType error code. 0 means success. */
833 /* */
834 static
835 FT_Error Do_RD_Charstrings( T1_Parser* parser )
836 {
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;
841 FT_Int index, count;
842
843
844 /* check the character name argument */
845 if ( top[0].kind != tok_immediate )
846 {
847 FT_ERROR(( "Do_RD_Charstrings: immediate character name expected\n" ));
848 goto Syntax_Error;
849 }
850
851 /* check the count argument */
852 if ( top[1].kind != tok_number )
853 {
854 FT_ERROR(( "Do_RD_Charstrings: number expected\n" ));
855 goto Syntax_Error;
856 }
857
858 parser->args++;
859 count = (FT_Int)CopyInteger( parser );
860 error = parser->error;
861 if ( error )
862 goto Exit;
863
864 /* record the glyph name and get the corresponding glyph index */
865 if ( top[0].kind2 == imm_notdef )
866 index = 0;
867 else
868 {
869 FT_String temp_name[128];
870 T1_Token* token = top;
871 FT_Int len = token->len - 1;
872
873
874 /* copy immediate name */
875 if ( len > 127 )
876 len = 127;
877 MEM_Copy( temp_name, parser->tokenizer->base + token->start + 1, len );
878 temp_name[len] = '\0';
879
880 index = parser->cur_name++;
881 error = T1_Add_Table( &parser->table, index * 2,
882 (FT_Byte*)temp_name, len + 1 );
883 if ( error )
884 goto Exit;
885 }
886
887 /* decrypt and record charstring, then skip them */
888 {
889 FT_Byte* base = tokzer->base + tokzer->cursor;
890
891
892 tokzer->cursor += count; /* skip */
893
894 if ( face->type1.private_dict.lenIV >= 0 )
895 {
896 t1_decrypt( base, count, 4330 );
897
898 base += face->type1.private_dict.lenIV;
899 count -= face->type1.private_dict.lenIV;
900 }
901
902 error = T1_Add_Table( &parser->table, index * 2 + 1, base, count );
903 }
904
905 /* consume the closing `ND' */
906 if ( !error )
907 error = Expect_Keyword( parser, key_ND );
908
909 Exit:
910 return error;
911
912 Syntax_Error:
913 return T1_Err_Syntax_Error;
914 }
915
916
917 static
918 FT_Error Expect_Dict_Arguments( T1_Parser* parser,
919 FT_Int num_args,
920 T1_TokenType immediate,
921 T1_DictState new_state,
922 FT_Int* count )
923 {
924 /* check that we have enough arguments in the stack, including */
925 /* the `dict' keyword */
926 if ( parser->top - parser->stack < num_args )
927 {
928 FT_ERROR(( "Expect_Dict_Arguments: expecting at least %d arguments",
929 num_args ));
930 goto Syntax_Error;
931 }
932
933 /* check that we have the correct immediate, if needed */
934 if ( num_args == 2 )
935 {
936 if ( parser->top[-2].kind != tok_immediate ||
937 parser->top[-2].kind2 != immediate )
938 {
939 FT_ERROR(( "Expect_Dict_Arguments: expecting `/%s' dictionary\n",
940 t1_immediates[immediate - imm_first_] ));
941 goto Syntax_Error;
942 }
943 }
944
945 parser->args = parser->top-1;
946
947 /* check that the count argument is a number */
948 if ( parser->args->kind != tok_number )
949 {
950 FT_ERROR(( "Expect_Dict_Arguments:" ));
951 FT_ERROR(( " expecting numerical count argument for `dict'\n" ));
952 goto Syntax_Error;
953 }
954
955 if ( count )
956 {
957 *count = CopyInteger( parser );
958 if ( parser->error )
959 return parser->error;
960 }
961
962 /* save the dictionary state */
963 parser->state_stack[++parser->state_index] = new_state;
964
965 /* consume the `begin' keyword and clear the stack */
966 parser->top -= num_args;
967 return Expect_Keyword( parser, key_begin );
968
969 Syntax_Error:
970 return T1_Err_Syntax_Error;
971 }
972
973
974 static
975 FT_Error Expect_Array_Arguments( T1_Parser* parser )
976 {
977 T1_Token* top = parser->top;
978 FT_Error error = T1_Err_Ok;
979 T1_DictState new_state;
980 FT_Int count;
981 T1_Face face = parser->face;
982 FT_Memory memory = face->root.memory;
983
984
985 /* Check arguments format */
986 if ( top - parser->stack < 2 )
987 {
988 FT_ERROR(( "Expect_Array_Arguments: two arguments expected\n" ));
989 error = T1_Err_Stack_Underflow;
990 goto Exit;
991 }
992
993 parser->top -= 2;
994 top -= 2;
995 parser->args = top + 1;
996
997 if ( top[0].kind != tok_immediate )
998 {
999 FT_ERROR(( "Expect_Array_Arguments:" ));
1000 FT_ERROR(( " first argument must be an immediate name\n" ));
1001 goto Syntax_Error;
1002 }
1003
1004 if ( top[1].kind != tok_number )
1005 {
1006 FT_ERROR(( "Expect_Array_Arguments:" ));
1007 FT_ERROR(( " second argument must be a number\n" ));
1008 goto Syntax_Error;
1009 }
1010
1011 count = (FT_Int)CopyInteger( parser );
1012
1013 /* Is this an array we know about? */
1014 switch ( top[0].kind2 )
1015 {
1016 case imm_Encoding:
1017 {
1018 T1_Encoding* encode = &face->type1.encoding;
1019
1020
1021 new_state = dict_encoding;
1022
1023 encode->code_first = count;
1024 encode->code_last = 0;
1025 encode->num_chars = count;
1026
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 ) )
1030 return error;
1031
1032 error = T1_New_Table( &parser->table, count, memory );
1033 if ( error )
1034 goto Exit;
1035
1036 parser->encoding_type = t1_encoding_array;
1037 }
1038 break;
1039
1040 case imm_Subrs:
1041 new_state = dict_subrs;
1042 face->type1.num_subrs = count;
1043
1044 error = T1_New_Table( &parser->table, count, memory );
1045 if ( error )
1046 goto Exit;
1047 break;
1048
1049 case imm_CharStrings:
1050 new_state = dict_charstrings;
1051 break;
1052
1053 default:
1054 new_state = dict_unknown_array;
1055 }
1056
1057 parser->state_stack[++parser->state_index] = new_state;
1058
1059 Exit:
1060 return error;
1061
1062 Syntax_Error:
1063 return T1_Err_Syntax_Error;
1064 }
1065
1066
1067 static
1068 FT_Error Finalize_Parsing( T1_Parser* parser )
1069 {
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;
1075
1076 FT_Int num_glyphs;
1077 FT_Int n;
1078 FT_Error error;
1079
1080
1081 num_glyphs = type1->num_glyphs = parser->cur_name;
1082
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* ) )
1087 return error;
1088
1089 /* copy glyph names and charstrings offsets and lengths */
1090 type1->charstrings_block = strings->block;
1091 for ( n = 0; n < num_glyphs; n++ )
1092 {
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];
1096 }
1097
1098 /* now free the old tables */
1099 FREE( strings->elements );
1100 FREE( strings->lengths );
1101
1102 if ( !psnames )
1103 {
1104 FT_ERROR(( "Finalize_Parsing: `PSNames' module missing!\n" ));
1105 return T1_Err_Unimplemented_Feature;
1106 }
1107
1108 /* compute encoding if required */
1109 if ( parser->encoding_type == t1_encoding_none )
1110 {
1111 FT_ERROR(( "Finalize_Parsing: no encoding specified in font file\n" ));
1112 return T1_Err_Syntax_Error;
1113 }
1114
1115 {
1116 FT_Int n;
1117 T1_Encoding* encode = &type1->encoding;
1118
1119
1120 encode->code_first = encode->num_chars - 1;
1121 encode->code_last = 0;
1122
1123 for ( n = 0; n < encode->num_chars; n++ )
1124 {
1125 FT_String** names;
1126 FT_Int index;
1127 FT_Int m;
1128
1129
1130 switch ( parser->encoding_type )
1131 {
1132 case t1_encoding_standard:
1133 index = psnames->adobe_std_encoding[n];
1134 names = 0;
1135 break;
1136
1137 case t1_encoding_expert:
1138 index = psnames->adobe_expert_encoding[n];
1139 names = 0;
1140 break;
1141
1142 default:
1143 index = n;
1144 names = (FT_String**)parser->encoding_offsets;
1145 }
1146
1147 encode->char_index[n] = 0;
1148
1149 if ( index )
1150 {
1151 FT_String* name;
1152
1153
1154 if ( names )
1155 name = names[index];
1156 else
1157 name = (FT_String*)psnames->adobe_std_strings(index);
1158
1159 if ( name )
1160 {
1161 FT_Int len = strlen( name );
1162
1163
1164 /* lookup glyph index from name */
1165 for ( m = 0; m < num_glyphs; m++ )
1166 {
1167 if ( strncmp( type1->glyph_names[m], name, len ) == 0 )
1168 {
1169 encode->char_index[n] = m;
1170 break;
1171 }
1172 }
1173
1174 if ( n < encode->code_first ) encode->code_first = n;
1175 if ( n > encode->code_last ) encode->code_last = n;
1176 }
1177 }
1178 }
1179
1180 parser->encoding_type = t1_encoding_none;
1181
1182 FREE( parser->encoding_names );
1183 FREE( parser->encoding_lengths );
1184 FREE( parser->encoding_offsets );
1185 }
1186
1187 return T1_Err_Ok;
1188 }
1189
1190
1191 /*************************************************************************/
1192 /* */
1193 /* <Function> */
1194 /* Parse_T1_FontProgram */
1195 /* */
1196 /* <Description> */
1197 /* Parses a given Type 1 font file and builds its face object. */
1198 /* */
1199 /* <InOut> */
1200 /* parser :: A handle to the target parser object. */
1201 /* */
1202 /* <Return> */
1203 /* FreeType error code. 0 means success. */
1204 /* */
1205 /* <Note> */
1206 /* The parser contains a handle to the target face object. */
1207 /* */
1208 LOCAL_FUNC
1209 FT_Error Parse_T1_FontProgram( T1_Parser* parser )
1210 {
1211 FT_Error error;
1212 T1_Font* type1 = &parser->face->type1;
1213
1214
1215 for (;;)
1216 {
1217 T1_Token token;
1218 T1_Token* top;
1219 T1_DictState dict_state;
1220 FT_Int dict_index;
1221
1222
1223 error = Next_T1_Token( parser, &token );
1224 top = parser->top;
1225 dict_index = parser->state_index;
1226 dict_state = parser->state_stack[dict_index];
1227
1228 switch ( token.kind )
1229 {
1230 /* a keyword has been detected */
1231 case tok_keyword:
1232 switch ( token.kind2 )
1233 {
1234 case key_dict:
1235 switch ( dict_state )
1236 {
1237 case dict_none:
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' */
1241 /* state. */
1242 error = Expect_Dict_Arguments( parser, 1, tok_error,
1243 dict_font, 0 );
1244 if ( error )
1245 goto Exit;
1246
1247 /* clear stack from all the previous content. This */
1248 /* could be some stupid Postscript code. */
1249 parser->top = parser->stack;
1250 break;
1251
1252 case dict_font:
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,
1258 dict_fontinfo, 0 );
1259 if ( error )
1260 goto Exit;
1261 break;
1262
1263 case dict_none2:
1264 error = Expect_Dict_Arguments( parser, 2, imm_Private,
1265 dict_private, 0 );
1266 if ( error )
1267 goto Exit;
1268 break;
1269
1270 case dict_private:
1271 {
1272 T1_Face face = parser->face;
1273 FT_Int count;
1274
1275
1276 error = Expect_Dict_Arguments( parser, 2, imm_CharStrings,
1277 dict_charstrings, &count );
1278 if ( error )
1279 goto Exit;
1280
1281 type1->num_glyphs = count;
1282 error = T1_New_Table( &parser->table, count * 2,
1283 face->root.memory );
1284 if ( error )
1285 goto Exit;
1286
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 */
1292 }
1293 break;
1294
1295 default:
1296 /* All other uses are invalid */
1297 FT_ERROR(( "Parse_T1_FontProgram:" ));
1298 FT_ERROR(( " invalid use of `dict' keyword\n" ));
1299 goto Syntax_Error;
1300 }
1301 break;
1302
1303 case key_array:
1304 /* Are we in an array yet? If so, raise an error */
1305 switch ( dict_state )
1306 {
1307 case dict_encoding:
1308 case dict_subrs:
1309 case dict_othersubrs:
1310 case dict_charstrings:
1311 case dict_unknown_array:
1312 FT_ERROR(( "Parse_T1_FontProgram: nested array definitions\n" ));
1313 goto Syntax_Error;
1314
1315 default:
1316 ;
1317 }
1318 error = Expect_Array_Arguments( parser );
1319 if ( error )
1320 goto Exit;
1321 break;
1322
1323 case key_ND:
1324 case key_NP:
1325 case key_def:
1326 /* Are we in an array? If so, finalize it. */
1327 switch ( dict_state )
1328 {
1329 case dict_encoding: /* finish encoding array */
1330 /* copy table names to the face object */
1331 T1_Done_Table( &parser->table );
1332
1333 parser->encoding_names = parser->table.block;
1334 parser->encoding_lengths = parser->table.lengths;
1335 parser->encoding_offsets = parser->table.elements;
1336
1337 parser->state_index--;
1338 break;
1339
1340 case dict_subrs:
1341 /* copy recorder sub-routines */
1342 T1_Done_Table( &parser->table );
1343
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;
1348
1349 parser->state_index--;
1350 break;
1351
1352 case dict_charstrings:
1353 case dict_othersubrs:
1354 case dict_unknown_array:
1355 FT_ERROR(( "Parse_T1_FontProgram: unsupported array\n" ));
1356 goto Syntax_Error;
1357 break;
1358
1359 default: /* normal `def' processing */
1360 /* Check that we have sufficient operands in the stack */
1361 if ( top >= parser->stack + 2 )
1362 {
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 )
1367 {
1368 parser->top -= 2;
1369 parser->args = parser->top + 1;
1370 error = def_funcs[dict_state](parser);
1371 }
1372 else
1373 {
1374 /* This is an error, but some fonts contain */
1375 /* stupid Postscript code. We simply ignore */
1376 /* an invalid `def' by clearing the stack. */
1377 #if 0
1378 FT_ERROR(( "Parse_T1_FontProgram: immediate expected\n" ));
1379 goto Syntax_Error;
1380 #else
1381 parser->top = parser->stack;
1382 #endif
1383 }
1384 }
1385 else
1386 {
1387 FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" ));
1388 goto Stack_Underflow;
1389 }
1390 }
1391 break;
1392
1393 case key_index:
1394 if ( top <= parser->stack )
1395 {
1396 FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" ));
1397 goto Stack_Underflow;
1398 }
1399
1400 /* simply ignore? */
1401 parser->top --;
1402 break;
1403
1404 case key_put:
1405 /* Check that we have sufficient operands in stack */
1406 if ( top < parser->stack + 2 )
1407 {
1408 FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" ));
1409 goto Stack_Underflow;
1410 }
1411
1412 parser->top -= 2;
1413 parser->args = parser->top;
1414
1415 switch ( dict_state )
1416 {
1417 case dict_encoding:
1418 error = Do_Put_Encoding( parser );
1419 if ( error )
1420 goto Exit;
1421 break;
1422
1423 case dict_unknown_array: /* ignore the `put' */
1424 break;
1425
1426 default:
1427 #if 0
1428 FT_ERROR(( "Parse_T1_FontProgram: invalid context\n" ));
1429 goto Syntax_Error;
1430 #else
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;
1435 #endif
1436 }
1437 break;
1438
1439 case key_RD:
1440 /* Check that we have sufficient operands in stack */
1441 if ( top < parser->stack + 2 )
1442 {
1443 FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" ));
1444 goto Stack_Underflow;
1445 }
1446
1447 parser->top -= 2;
1448 parser->args = parser->top;
1449 switch ( dict_state )
1450 {
1451 case dict_subrs:
1452 error = Do_RD_Subrs( parser );
1453 if ( error )
1454 goto Exit;
1455 break;
1456
1457 case dict_charstrings:
1458 error = Do_RD_Charstrings( parser );
1459 if ( error )
1460 goto Exit;
1461 break;
1462
1463 default:
1464 FT_ERROR(( "Parse_T1_FontProgram: invalid context\n" ));
1465 goto Syntax_Error;
1466 }
1467 break;
1468
1469 case key_end:
1470 /* Were we in a dictionary or in an array? */
1471 if ( dict_index <= 0 )
1472 {
1473 FT_ERROR(( "Parse_T1_FontProgram: no dictionary defined\n" ));
1474 goto Syntax_Error;
1475 }
1476
1477 switch ( dict_state )
1478 {
1479 /* jump to the private dictionary if we are closing the */
1480 /* `/Font' dictionary */
1481 case dict_font:
1482 goto Open_Private;
1483
1484 /* exit the parser when closing the CharStrings dictionary */
1485 case dict_charstrings:
1486 return Finalize_Parsing( parser );
1487
1488 default:
1489 /* Pop the current dictionary state and return to previous */
1490 /* one. Consume the `def'. */
1491
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--;
1496
1497 /* many fonts use `NP' instead of `def' or `put', so */
1498 /* we simply ignore the next token */
1499 #if 0
1500 error = Expect_Keyword2( parser, key_def, key_put );
1501 if ( error )
1502 goto Exit;
1503 #else
1504 (void)Expect_Keyword2( parser, key_def, key_put );
1505 #endif
1506 }
1507 break;
1508
1509 case key_for:
1510 /* check that we have four arguments and simply */
1511 /* ignore them */
1512 if ( top - parser->stack < 4 )
1513 {
1514 FT_ERROR(( "Parse_T1_FontProgram: not enough arguments\n" ));
1515 goto Stack_Underflow;
1516 }
1517
1518 parser->top -= 4;
1519 break;
1520
1521 case key_currentdict:
1522 Open_Private:
1523 parser->state_index = 0;
1524 parser->state_stack[0] = dict_none2;
1525 error = Open_PrivateDict( parser->tokenizer );
1526 if ( error )
1527 goto Exit;
1528 break;
1529
1530 case key_true:
1531 case key_false:
1532 case key_StandardEncoding:
1533 case key_ExpertEncoding:
1534 goto Push_Element;
1535
1536 default:
1537 FT_ERROR(( "Parse_T1_FontProgram:" ));
1538 FT_ERROR(( " invalid keyword in context\n" ));
1539 error = T1_Err_Syntax_Error;
1540 }
1541 break;
1542
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 */
1546 case tok_immediate:
1547 if ( token.kind2 == imm_BlendAxisTypes )
1548 {
1549 error = FT_Err_Unknown_File_Format;
1550 goto Exit;
1551 }
1552 /* fallthrough */
1553
1554 /* A number was detected */
1555 case tok_string:
1556 case tok_program:
1557 case tok_array:
1558 case tok_hexarray:
1559 case tok_any:
1560 case tok_number: /* push number on stack */
1561
1562 Push_Element:
1563 if ( top >= parser->limit )
1564 {
1565 error = T1_Err_Stack_Overflow;
1566 goto Exit;
1567 }
1568 else
1569 *parser->top++ = token;
1570 break;
1571
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 */
1575 default:
1576 error = T1_Err_Ok; /* ignore token */
1577 }
1578
1579 if ( error )
1580 return error;
1581 }
1582
1583 Exit:
1584 return error;
1585
1586 Syntax_Error:
1587 return T1_Err_Syntax_Error;
1588
1589 Stack_Underflow:
1590 return T1_Err_Stack_Underflow;
1591 }
1592
1593
1594 /* END */