This commit was manufactured by cvs2svn to create branch 'captive'.
[reactos.git] / subsys / win32k / freetype / src / 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 <freetype/src/type1/t1tokens.h>
32 #include <freetype/src/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 */