• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************/
2 /*                                                                         */
3 /*  t1decode.c                                                             */
4 /*                                                                         */
5 /*    PostScript Type 1 decoding routines (body).                          */
6 /*                                                                         */
7 /*  Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 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 <ft2build.h>
20 #include FT_INTERNAL_DEBUG_H
21 #include FT_INTERNAL_POSTSCRIPT_HINTS_H
22 #include FT_OUTLINE_H
23 
24 #include "t1decode.h"
25 #include "psobjs.h"
26 
27 #include "psauxerr.h"
28 
29 
30   /*************************************************************************/
31   /*                                                                       */
32   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
33   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
34   /* messages during execution.                                            */
35   /*                                                                       */
36 #undef  FT_COMPONENT
37 #define FT_COMPONENT  trace_t1decode
38 
39 
40   typedef enum  T1_Operator_
41   {
42     op_none = 0,
43     op_endchar,
44     op_hsbw,
45     op_seac,
46     op_sbw,
47     op_closepath,
48     op_hlineto,
49     op_hmoveto,
50     op_hvcurveto,
51     op_rlineto,
52     op_rmoveto,
53     op_rrcurveto,
54     op_vhcurveto,
55     op_vlineto,
56     op_vmoveto,
57     op_dotsection,
58     op_hstem,
59     op_hstem3,
60     op_vstem,
61     op_vstem3,
62     op_div,
63     op_callothersubr,
64     op_callsubr,
65     op_pop,
66     op_return,
67     op_setcurrentpoint,
68     op_unknown15,
69 
70     op_max    /* never remove this one */
71 
72   } T1_Operator;
73 
74 
75   static
76   const FT_Int  t1_args_count[op_max] =
77   {
78     0, /* none */
79     0, /* endchar */
80     2, /* hsbw */
81     5, /* seac */
82     4, /* sbw */
83     0, /* closepath */
84     1, /* hlineto */
85     1, /* hmoveto */
86     4, /* hvcurveto */
87     2, /* rlineto */
88     2, /* rmoveto */
89     6, /* rrcurveto */
90     4, /* vhcurveto */
91     1, /* vlineto */
92     1, /* vmoveto */
93     0, /* dotsection */
94     2, /* hstem */
95     6, /* hstem3 */
96     2, /* vstem */
97     6, /* vstem3 */
98     2, /* div */
99    -1, /* callothersubr */
100     1, /* callsubr */
101     0, /* pop */
102     0, /* return */
103     2, /* setcurrentpoint */
104     2  /* opcode 15 (undocumented and obsolete) */
105   };
106 
107 
108   /*************************************************************************/
109   /*                                                                       */
110   /* <Function>                                                            */
111   /*    t1_lookup_glyph_by_stdcharcode                                     */
112   /*                                                                       */
113   /* <Description>                                                         */
114   /*    Looks up a given glyph by its StandardEncoding charcode.  Used to  */
115   /*    implement the SEAC Type 1 operator.                                */
116   /*                                                                       */
117   /* <Input>                                                               */
118   /*    face     :: The current face object.                               */
119   /*                                                                       */
120   /*    charcode :: The character code to look for.                        */
121   /*                                                                       */
122   /* <Return>                                                              */
123   /*    A glyph index in the font face.  Returns -1 if the corresponding   */
124   /*    glyph wasn't found.                                                */
125   /*                                                                       */
126   static FT_Int
t1_lookup_glyph_by_stdcharcode(T1_Decoder decoder,FT_Int charcode)127   t1_lookup_glyph_by_stdcharcode( T1_Decoder  decoder,
128                                   FT_Int      charcode )
129   {
130     FT_UInt             n;
131     const FT_String*    glyph_name;
132     FT_Service_PsCMaps  psnames = decoder->psnames;
133 
134 
135     /* check range of standard char code */
136     if ( charcode < 0 || charcode > 255 )
137       return -1;
138 
139     glyph_name = psnames->adobe_std_strings(
140                    psnames->adobe_std_encoding[charcode]);
141 
142     for ( n = 0; n < decoder->num_glyphs; n++ )
143     {
144       FT_String*  name = (FT_String*)decoder->glyph_names[n];
145 
146 
147       if ( name && name[0] == glyph_name[0]  &&
148            ft_strcmp( name, glyph_name ) == 0 )
149         return n;
150     }
151 
152     return -1;
153   }
154 
155 
156   /*************************************************************************/
157   /*                                                                       */
158   /* <Function>                                                            */
159   /*    t1operator_seac                                                    */
160   /*                                                                       */
161   /* <Description>                                                         */
162   /*    Implements the `seac' Type 1 operator for a Type 1 decoder.        */
163   /*                                                                       */
164   /* <Input>                                                               */
165   /*    decoder :: The current CID decoder.                                */
166   /*                                                                       */
167   /*    asb     :: The accent's side bearing.                              */
168   /*                                                                       */
169   /*    adx     :: The horizontal offset of the accent.                    */
170   /*                                                                       */
171   /*    ady     :: The vertical offset of the accent.                      */
172   /*                                                                       */
173   /*    bchar   :: The base character's StandardEncoding charcode.         */
174   /*                                                                       */
175   /*    achar   :: The accent character's StandardEncoding charcode.       */
176   /*                                                                       */
177   /* <Return>                                                              */
178   /*    FreeType error code.  0 means success.                             */
179   /*                                                                       */
180   static FT_Error
t1operator_seac(T1_Decoder decoder,FT_Pos asb,FT_Pos adx,FT_Pos ady,FT_Int bchar,FT_Int achar)181   t1operator_seac( T1_Decoder  decoder,
182                    FT_Pos      asb,
183                    FT_Pos      adx,
184                    FT_Pos      ady,
185                    FT_Int      bchar,
186                    FT_Int      achar )
187   {
188     FT_Error     error;
189     FT_Int       bchar_index, achar_index;
190 #if 0
191     FT_Int       n_base_points;
192     FT_Outline*  base = decoder->builder.base;
193 #endif
194     FT_Vector    left_bearing, advance;
195 
196 
197     /* seac weirdness */
198     adx += decoder->builder.left_bearing.x;
199 
200     /* `glyph_names' is set to 0 for CID fonts which do not */
201     /* include an encoding.  How can we deal with these?    */
202     if ( decoder->glyph_names == 0 )
203     {
204       FT_ERROR(( "t1operator_seac:" ));
205       FT_ERROR(( " glyph names table not available in this font!\n" ));
206       return PSaux_Err_Syntax_Error;
207     }
208 
209     bchar_index = t1_lookup_glyph_by_stdcharcode( decoder, bchar );
210     achar_index = t1_lookup_glyph_by_stdcharcode( decoder, achar );
211 
212     if ( bchar_index < 0 || achar_index < 0 )
213     {
214       FT_ERROR(( "t1operator_seac:" ));
215       FT_ERROR(( " invalid seac character code arguments\n" ));
216       return PSaux_Err_Syntax_Error;
217     }
218 
219     /* if we are trying to load a composite glyph, do not load the */
220     /* accent character and return the array of subglyphs.         */
221     if ( decoder->builder.no_recurse )
222     {
223       FT_GlyphSlot    glyph  = (FT_GlyphSlot)decoder->builder.glyph;
224       FT_GlyphLoader  loader = glyph->internal->loader;
225       FT_SubGlyph     subg;
226 
227 
228       /* reallocate subglyph array if necessary */
229       error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
230       if ( error )
231         goto Exit;
232 
233       subg = loader->current.subglyphs;
234 
235       /* subglyph 0 = base character */
236       subg->index = bchar_index;
237       subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
238                     FT_SUBGLYPH_FLAG_USE_MY_METRICS;
239       subg->arg1  = 0;
240       subg->arg2  = 0;
241       subg++;
242 
243       /* subglyph 1 = accent character */
244       subg->index = achar_index;
245       subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
246       subg->arg1  = (FT_Int)( adx - asb );
247       subg->arg2  = (FT_Int)ady;
248 
249       /* set up remaining glyph fields */
250       glyph->num_subglyphs = 2;
251       glyph->subglyphs     = loader->base.subglyphs;
252       glyph->format        = FT_GLYPH_FORMAT_COMPOSITE;
253 
254       loader->current.num_subglyphs = 2;
255       goto Exit;
256     }
257 
258     /* First load `bchar' in builder */
259     /* now load the unscaled outline */
260 
261     FT_GlyphLoader_Prepare( decoder->builder.loader );  /* prepare loader */
262 
263     error = t1_decoder_parse_glyph( decoder, bchar_index );
264     if ( error )
265       goto Exit;
266 
267     /* save the left bearing and width of the base character */
268     /* as they will be erased by the next load.              */
269 
270     left_bearing = decoder->builder.left_bearing;
271     advance      = decoder->builder.advance;
272 
273     decoder->builder.left_bearing.x = 0;
274     decoder->builder.left_bearing.y = 0;
275 
276     decoder->builder.pos_x = adx - asb;
277     decoder->builder.pos_y = ady;
278 
279     /* Now load `achar' on top of */
280     /* the base outline           */
281     error = t1_decoder_parse_glyph( decoder, achar_index );
282     if ( error )
283       goto Exit;
284 
285     /* restore the left side bearing and   */
286     /* advance width of the base character */
287 
288     decoder->builder.left_bearing = left_bearing;
289     decoder->builder.advance      = advance;
290 
291     decoder->builder.pos_x = 0;
292     decoder->builder.pos_y = 0;
293 
294   Exit:
295     return error;
296   }
297 
298 
299   /*************************************************************************/
300   /*                                                                       */
301   /* <Function>                                                            */
302   /*    t1_decoder_parse_charstrings                                       */
303   /*                                                                       */
304   /* <Description>                                                         */
305   /*    Parses a given Type 1 charstrings program.                         */
306   /*                                                                       */
307   /* <Input>                                                               */
308   /*    decoder         :: The current Type 1 decoder.                     */
309   /*                                                                       */
310   /*    charstring_base :: The base address of the charstring stream.      */
311   /*                                                                       */
312   /*    charstring_len  :: The length in bytes of the charstring stream.   */
313   /*                                                                       */
314   /* <Return>                                                              */
315   /*    FreeType error code.  0 means success.                             */
316   /*                                                                       */
317   FT_LOCAL_DEF( FT_Error )
t1_decoder_parse_charstrings(T1_Decoder decoder,FT_Byte * charstring_base,FT_UInt charstring_len)318   t1_decoder_parse_charstrings( T1_Decoder  decoder,
319                                 FT_Byte*    charstring_base,
320                                 FT_UInt     charstring_len )
321   {
322     FT_Error         error;
323     T1_Decoder_Zone  zone;
324     FT_Byte*         ip;
325     FT_Byte*         limit;
326     T1_Builder       builder = &decoder->builder;
327     FT_Pos           x, y, orig_x, orig_y;
328     FT_Int           known_othersubr_result_cnt   = 0;
329     FT_Int           unknown_othersubr_result_cnt = 0;
330 
331     T1_Hints_Funcs   hinter;
332 
333 
334     /* we don't want to touch the source code -- use macro trick */
335 #define start_point    t1_builder_start_point
336 #define check_points   t1_builder_check_points
337 #define add_point      t1_builder_add_point
338 #define add_point1     t1_builder_add_point1
339 #define add_contour    t1_builder_add_contour
340 #define close_contour  t1_builder_close_contour
341 
342     /* First of all, initialize the decoder */
343     decoder->top  = decoder->stack;
344     decoder->zone = decoder->zones;
345     zone          = decoder->zones;
346 
347     builder->parse_state = T1_Parse_Start;
348 
349     hinter = (T1_Hints_Funcs)builder->hints_funcs;
350 
351     /* a font that reads BuildCharArray without setting */
352     /* its values first is buggy, but ...               */
353     FT_ASSERT( ( decoder->len_buildchar == 0 ) ==
354                ( decoder->buildchar == NULL ) );
355 
356     if ( decoder->len_buildchar > 0 )
357       ft_memset( &decoder->buildchar[0],
358                  0,
359                  sizeof( decoder->buildchar[0] ) * decoder->len_buildchar );
360 
361     FT_TRACE4(( "\nStart charstring\n" ));
362 
363     zone->base           = charstring_base;
364     limit = zone->limit  = charstring_base + charstring_len;
365     ip    = zone->cursor = zone->base;
366 
367     error = PSaux_Err_Ok;
368 
369     x = orig_x = builder->pos_x;
370     y = orig_y = builder->pos_y;
371 
372     /* begin hints recording session, if any */
373     if ( hinter )
374       hinter->open( hinter->hints );
375 
376     /* now, execute loop */
377     while ( ip < limit )
378     {
379       FT_Long*     top   = decoder->top;
380       T1_Operator  op    = op_none;
381       FT_Long      value = 0;
382 
383 
384       FT_ASSERT( known_othersubr_result_cnt == 0   ||
385                  unknown_othersubr_result_cnt == 0 );
386 
387       FT_TRACE5(( " (%d)", decoder->top - decoder->stack ));
388 
389       /*********************************************************************/
390       /*                                                                   */
391       /* Decode operator or operand                                        */
392       /*                                                                   */
393       /*                                                                   */
394 
395       /* first of all, decompress operator or value */
396       switch ( *ip++ )
397       {
398       case 1:
399         op = op_hstem;
400         break;
401 
402       case 3:
403         op = op_vstem;
404         break;
405       case 4:
406         op = op_vmoveto;
407         break;
408       case 5:
409         op = op_rlineto;
410         break;
411       case 6:
412         op = op_hlineto;
413         break;
414       case 7:
415         op = op_vlineto;
416         break;
417       case 8:
418         op = op_rrcurveto;
419         break;
420       case 9:
421         op = op_closepath;
422         break;
423       case 10:
424         op = op_callsubr;
425         break;
426       case 11:
427         op = op_return;
428         break;
429 
430       case 13:
431         op = op_hsbw;
432         break;
433       case 14:
434         op = op_endchar;
435         break;
436 
437       case 15:          /* undocumented, obsolete operator */
438         op = op_unknown15;
439         break;
440 
441       case 21:
442         op = op_rmoveto;
443         break;
444       case 22:
445         op = op_hmoveto;
446         break;
447 
448       case 30:
449         op = op_vhcurveto;
450         break;
451       case 31:
452         op = op_hvcurveto;
453         break;
454 
455       case 12:
456         if ( ip > limit )
457         {
458           FT_ERROR(( "t1_decoder_parse_charstrings: "
459                      "invalid escape (12+EOF)\n" ));
460           goto Syntax_Error;
461         }
462 
463         switch ( *ip++ )
464         {
465         case 0:
466           op = op_dotsection;
467           break;
468         case 1:
469           op = op_vstem3;
470           break;
471         case 2:
472           op = op_hstem3;
473           break;
474         case 6:
475           op = op_seac;
476           break;
477         case 7:
478           op = op_sbw;
479           break;
480         case 12:
481           op = op_div;
482           break;
483         case 16:
484           op = op_callothersubr;
485           break;
486         case 17:
487           op = op_pop;
488           break;
489         case 33:
490           op = op_setcurrentpoint;
491           break;
492 
493         default:
494           FT_ERROR(( "t1_decoder_parse_charstrings: "
495                      "invalid escape (12+%d)\n",
496                      ip[-1] ));
497           goto Syntax_Error;
498         }
499         break;
500 
501       case 255:    /* four bytes integer */
502         if ( ip + 4 > limit )
503         {
504           FT_ERROR(( "t1_decoder_parse_charstrings: "
505                      "unexpected EOF in integer\n" ));
506           goto Syntax_Error;
507         }
508 
509         value = (FT_Int32)( ((FT_Long)ip[0] << 24) |
510                             ((FT_Long)ip[1] << 16) |
511                             ((FT_Long)ip[2] << 8 ) |
512                                       ip[3] );
513         ip += 4;
514         break;
515 
516       default:
517         if ( ip[-1] >= 32 )
518         {
519           if ( ip[-1] < 247 )
520             value = (FT_Long)ip[-1] - 139;
521           else
522           {
523             if ( ++ip > limit )
524             {
525               FT_ERROR(( "t1_decoder_parse_charstrings: " ));
526               FT_ERROR(( "unexpected EOF in integer\n" ));
527               goto Syntax_Error;
528             }
529 
530             if ( ip[-2] < 251 )
531               value =  ( ( (FT_Long)ip[-2] - 247 ) << 8 ) + ip[-1] + 108;
532             else
533               value = -( ( ( (FT_Long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );
534           }
535         }
536         else
537         {
538           FT_ERROR(( "t1_decoder_parse_charstrings: "
539                      "invalid byte (%d)\n", ip[-1] ));
540           goto Syntax_Error;
541         }
542       }
543 
544       if ( unknown_othersubr_result_cnt > 0 )
545       {
546         switch ( op )
547         {
548         case op_callsubr:
549         case op_return:
550         case op_none:
551         case op_pop:
552           break;
553 
554         default:
555           /* all operands have been transferred by previous pops */
556           unknown_othersubr_result_cnt = 0;
557           break;
558         }
559       }
560 
561       /*********************************************************************/
562       /*                                                                   */
563       /*  Push value on stack, or process operator                         */
564       /*                                                                   */
565       /*                                                                   */
566       if ( op == op_none )
567       {
568         if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
569         {
570           FT_ERROR(( "t1_decoder_parse_charstrings: stack overflow!\n" ));
571           goto Syntax_Error;
572         }
573 
574         FT_TRACE4(( " %ld", value ));
575 
576         *top++       = value;
577         decoder->top = top;
578       }
579       else if ( op == op_callothersubr )  /* callothersubr */
580       {
581         FT_Int  subr_no;
582         FT_Int  arg_cnt;
583 
584 
585         FT_TRACE4(( " callothersubr" ));
586 
587         if ( top - decoder->stack < 2 )
588           goto Stack_Underflow;
589 
590         top -= 2;
591 
592         subr_no = (FT_Int)top[1];
593         arg_cnt = (FT_Int)top[0];
594 
595         /***********************************************************/
596         /*                                                         */
597         /* remove all operands to callothersubr from the stack     */
598         /*                                                         */
599         /* for handled othersubrs, where we know the number of     */
600         /* arguments, we increase the stack by the value of        */
601         /* known_othersubr_result_cnt                              */
602         /*                                                         */
603         /* for unhandled othersubrs the following pops adjust the  */
604         /* stack pointer as necessary                              */
605 
606         if ( arg_cnt > top - decoder->stack )
607           goto Stack_Underflow;
608 
609         top -= arg_cnt;
610 
611         known_othersubr_result_cnt   = 0;
612         unknown_othersubr_result_cnt = 0;
613 
614         /* XXX TODO: The checks to `arg_count == <whatever>'       */
615         /* might not be correct; an othersubr expects a certain    */
616         /* number of operands on the PostScript stack (as opposed  */
617         /* to the T1 stack) but it doesn't have to put them there  */
618         /* by itself; previous othersubrs might have left the      */
619         /* operands there if they were not followed by an          */
620         /* appropriate number of pops                              */
621         /*                                                         */
622         /* On the other hand, Adobe Reader 7.0.8 for Linux doesn't */
623         /* accept a font that contains charstrings like            */
624         /*                                                         */
625         /*     100 200 2 20 callothersubr                          */
626         /*     300 1 20 callothersubr pop                          */
627         /*                                                         */
628         /* Perhaps this is the reason why BuildCharArray exists.   */
629 
630         switch ( subr_no )
631         {
632         case 1:                     /* start flex feature */
633           if ( arg_cnt != 0 )
634             goto Unexpected_OtherSubr;
635 
636           decoder->flex_state        = 1;
637           decoder->num_flex_vectors  = 0;
638           if ( start_point( builder, x, y ) ||
639                check_points( builder, 6 )   )
640             goto Fail;
641           break;
642 
643         case 2:                     /* add flex vectors */
644           {
645             FT_Int  idx;
646 
647 
648             if ( arg_cnt != 0 )
649               goto Unexpected_OtherSubr;
650 
651             /* note that we should not add a point for index 0; */
652             /* this will move our current position to the flex  */
653             /* point without adding any point to the outline    */
654             idx = decoder->num_flex_vectors++;
655             if ( idx > 0 && idx < 7 )
656               add_point( builder,
657                          x,
658                          y,
659                          (FT_Byte)( idx == 3 || idx == 6 ) );
660           }
661           break;
662 
663         case 0:                     /* end flex feature */
664           if ( arg_cnt != 3 )
665             goto Unexpected_OtherSubr;
666 
667           if ( decoder->flex_state       == 0 ||
668                decoder->num_flex_vectors != 7 )
669           {
670             FT_ERROR(( "t1_decoder_parse_charstrings: "
671                        "unexpected flex end\n" ));
672             goto Syntax_Error;
673           }
674 
675           /* the two `results' are popped by the following setcurrentpoint */
676           known_othersubr_result_cnt = 2;
677           break;
678 
679         case 3:                     /* change hints */
680           if ( arg_cnt != 1 )
681             goto Unexpected_OtherSubr;
682 
683           known_othersubr_result_cnt = 1;
684 
685           if ( hinter )
686             hinter->reset( hinter->hints, builder->current->n_points );
687 
688           break;
689 
690         case 12:
691         case 13:
692           /* counter control hints, clear stack */
693           top = decoder->stack;
694           break;
695 
696         case 14:
697         case 15:
698         case 16:
699         case 17:
700         case 18:                    /* multiple masters */
701           {
702             PS_Blend  blend = decoder->blend;
703             FT_UInt   num_points, nn, mm;
704             FT_Long*  delta;
705             FT_Long*  values;
706 
707 
708             if ( !blend )
709             {
710               FT_ERROR(( "t1_decoder_parse_charstrings: " ));
711               FT_ERROR(( "unexpected multiple masters operator!\n" ));
712               goto Syntax_Error;
713             }
714 
715             num_points = (FT_UInt)subr_no - 13 + ( subr_no == 18 );
716             if ( arg_cnt != (FT_Int)( num_points * blend->num_designs ) )
717             {
718               FT_ERROR(( "t1_decoder_parse_charstrings: " ));
719               FT_ERROR(( "incorrect number of mm arguments\n" ));
720               goto Syntax_Error;
721             }
722 
723             /* we want to compute:                                   */
724             /*                                                       */
725             /*  a0*w0 + a1*w1 + ... + ak*wk                          */
726             /*                                                       */
727             /* but we only have the a0, a1-a0, a2-a0, .. ak-a0       */
728             /* however, given that w0 + w1 + ... + wk == 1, we can   */
729             /* rewrite it easily as:                                 */
730             /*                                                       */
731             /*  a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk       */
732             /*                                                       */
733             /* where k == num_designs-1                              */
734             /*                                                       */
735             /* I guess that's why it's written in this `compact'     */
736             /* form.                                                 */
737             /*                                                       */
738             delta  = top + num_points;
739             values = top;
740             for ( nn = 0; nn < num_points; nn++ )
741             {
742               FT_Long  tmp = values[0];
743 
744 
745               for ( mm = 1; mm < blend->num_designs; mm++ )
746                 tmp += FT_MulFix( *delta++, blend->weight_vector[mm] );
747 
748               *values++ = tmp;
749             }
750 
751             known_othersubr_result_cnt = num_points;
752             break;
753           }
754 
755 #ifdef CAN_HANDLE_NON_INTEGRAL_T1_OPERANDS
756 
757           /* We cannot yet enable these since currently  */
758           /* our T1 stack stores integers which lack the */
759           /* precision to express the values             */
760 
761         case 19:
762           /* <idx> 1 19 callothersubr                             */
763           /* => replace elements starting from index cvi( <idx> ) */
764           /*    of BuildCharArray with WeightVector               */
765           {
766             FT_Int    idx;
767             PS_Blend  blend = decoder->blend;
768 
769 
770             if ( arg_cnt != 1 || blend == NULL )
771               goto Unexpected_OtherSubr;
772 
773             idx = top[0];
774 
775             if ( idx < 0                                                 ||
776                  idx + blend->num_designs > decoder->face->len_buildchar )
777               goto Unexpected_OtherSubr;
778 
779             ft_memcpy( &decoder->buildchar[idx],
780                        blend->weight_vector,
781                        blend->num_designs *
782                          sizeof( blend->weight_vector[0] ) );
783           }
784           break;
785 
786         case 20:
787           /* <arg1> <arg2> 2 20 callothersubr pop   */
788           /* ==> push <arg1> + <arg2> onto T1 stack */
789           if ( arg_cnt != 2 )
790             goto Unexpected_OtherSubr;
791 
792           top[0] += top[1]; /* XXX (over|under)flow */
793 
794           known_othersubr_result_cnt = 1;
795           break;
796 
797         case 21:
798           /* <arg1> <arg2> 2 21 callothersubr pop   */
799           /* ==> push <arg1> - <arg2> onto T1 stack */
800           if ( arg_cnt != 2 )
801             goto Unexpected_OtherSubr;
802 
803           top[0] -= top[1]; /* XXX (over|under)flow */
804 
805           known_othersubr_result_cnt = 1;
806           break;
807 
808         case 22:
809           /* <arg1> <arg2> 2 22 callothersubr pop   */
810           /* ==> push <arg1> * <arg2> onto T1 stack */
811           if ( arg_cnt != 2 )
812             goto Unexpected_OtherSubr;
813 
814           top[0] *= top[1]; /* XXX (over|under)flow */
815 
816           known_othersubr_result_cnt = 1;
817           break;
818 
819         case 23:
820           /* <arg1> <arg2> 2 23 callothersubr pop   */
821           /* ==> push <arg1> / <arg2> onto T1 stack */
822           if ( arg_cnt != 2 || top[1] == 0 )
823             goto Unexpected_OtherSubr;
824 
825           top[0] /= top[1]; /* XXX (over|under)flow */
826 
827           known_othersubr_result_cnt = 1;
828           break;
829 
830 #endif /* CAN_HANDLE_NON_INTEGRAL_T1_OPERANDS */
831 
832         case 24:
833           /* <val> <idx> 2 24 callothersubr              */
834           /* => set BuildCharArray[cvi( <idx> )] = <val> */
835           {
836             FT_Int    idx;
837             PS_Blend  blend = decoder->blend;
838 
839             if ( arg_cnt != 2 || blend == NULL )
840               goto Unexpected_OtherSubr;
841 
842             idx = top[1];
843 
844             if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
845               goto Unexpected_OtherSubr;
846 
847             decoder->buildchar[idx] = top[0];
848           }
849           break;
850 
851         case 25:
852           /* <idx> 1 25 callothersubr pop       */
853           /* => push BuildCharArray[cvi( idx )] */
854           /*    onto T1 stack                   */
855           {
856             FT_Int    idx;
857             PS_Blend  blend = decoder->blend;
858 
859             if ( arg_cnt != 1 || blend == NULL )
860               goto Unexpected_OtherSubr;
861 
862             idx = top[0];
863 
864             if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
865               goto Unexpected_OtherSubr;
866 
867             top[0] = decoder->buildchar[idx];
868           }
869 
870           known_othersubr_result_cnt = 1;
871           break;
872 
873 #if 0
874         case 26:
875           /* <val> mark <idx> ==> set BuildCharArray[cvi( <idx> )] = <val>, */
876           /*                      leave mark on T1 stack                    */
877           /* <val> <idx>      ==> set BuildCharArray[cvi( <idx> )] = <val>  */
878           XXX who has left his mark on the (PostScript) stack ?;
879           break;
880 #endif
881 
882         case 27:
883           /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */
884           /* ==> push <res1> onto T1 stack if <val1> <= <val2>,  */
885           /*     otherwise push <res2>                          */
886           if ( arg_cnt != 4 )
887             goto Unexpected_OtherSubr;
888 
889           if ( top[2] > top[3] )
890             top[0] = top[1];
891 
892           known_othersubr_result_cnt = 1;
893           break;
894 
895 #ifdef CAN_HANDLE_NON_INTEGRAL_T1_OPERANDS
896         case 28:
897           /* 0 28 callothersubr pop                               */
898           /* => push random value from interval [0, 1) onto stack */
899           if ( arg_cnt != 0 )
900             goto Unexpected_OtherSubr;
901 
902           top[0] = FT_rand();
903           known_othersubr_result_cnt = 1;
904           break;
905 #endif
906 
907         default:
908           FT_ERROR(( "t1_decoder_parse_charstrings: "
909                      "unknown othersubr [%d %d], wish me luck!\n",
910                      arg_cnt, subr_no ));
911           unknown_othersubr_result_cnt = arg_cnt;
912           break;
913 
914         Unexpected_OtherSubr:
915           FT_ERROR(( "t1_decoder_parse_charstrings: "
916                      "invalid othersubr [%d %d]!\n", arg_cnt, subr_no ));
917           goto Syntax_Error;
918         }
919 
920         top += known_othersubr_result_cnt;
921 
922         decoder->top = top;
923       }
924       else  /* general operator */
925       {
926         FT_Int  num_args = t1_args_count[op];
927 
928 
929         FT_ASSERT( num_args >= 0 );
930 
931         if ( top - decoder->stack < num_args )
932           goto Stack_Underflow;
933 
934         /* XXX Operators usually take their operands from the        */
935         /*     bottom of the stack, i.e., the operands are           */
936         /*     decoder->stack[0], ..., decoder->stack[num_args - 1]; */
937         /*     only div, callsubr, and callothersubr are different.  */
938         /*     In practice it doesn't matter (?).                    */
939 
940 #ifdef FT_DEBUG_LEVEL_TRACE
941 
942         switch ( op )
943         {
944         case op_callsubr:
945         case op_div:
946         case op_callothersubr:
947         case op_pop:
948         case op_return:
949           break;
950 
951         default:
952           if ( top - decoder->stack != num_args )
953             FT_TRACE0(( "t1_decoder_parse_charstrings: "
954                         "too much operands on the stack "
955                         "(seen %d, expected %d)\n",
956                         top - decoder->stack, num_args ));
957             break;
958         }
959 
960 #endif /* FT_DEBUG_LEVEL_TRACE */
961 
962         top -= num_args;
963 
964         switch ( op )
965         {
966         case op_endchar:
967           FT_TRACE4(( " endchar" ));
968 
969           close_contour( builder );
970 
971           /* close hints recording session */
972           if ( hinter )
973           {
974             if (hinter->close( hinter->hints, builder->current->n_points ))
975               goto Syntax_Error;
976 
977             /* apply hints to the loaded glyph outline now */
978             hinter->apply( hinter->hints,
979                            builder->current,
980                            (PSH_Globals) builder->hints_globals,
981                            decoder->hint_mode );
982           }
983 
984           /* add current outline to the glyph slot */
985           FT_GlyphLoader_Add( builder->loader );
986 
987           FT_TRACE4(( "\n" ));
988 
989           /* the compiler should optimize away this empty loop but ... */
990 
991 #ifdef FT_DEBUG_LEVEL_TRACE
992 
993           if ( decoder->len_buildchar > 0 )
994           {
995             FT_UInt  i;
996 
997 
998             FT_TRACE4(( "BuildCharArray = [ " ));
999 
1000             for ( i = 0; i < decoder->len_buildchar; ++i )
1001               FT_TRACE4(( "%d ", decoder->buildchar[ i ] ));
1002 
1003             FT_TRACE4(( "]\n" ));
1004           }
1005 
1006 #endif /* FT_DEBUG_LEVEL_TRACE */
1007 
1008           FT_TRACE4(( "\n" ));
1009 
1010           /* return now! */
1011           return PSaux_Err_Ok;
1012 
1013         case op_hsbw:
1014           FT_TRACE4(( " hsbw" ));
1015 
1016           builder->parse_state = T1_Parse_Have_Width;
1017 
1018           builder->left_bearing.x += top[0];
1019           builder->advance.x       = top[1];
1020           builder->advance.y       = 0;
1021 
1022           orig_x = builder->last.x = x = builder->pos_x + top[0];
1023           orig_y = builder->last.y = y = builder->pos_y;
1024 
1025           FT_UNUSED( orig_y );
1026 
1027           /* the `metrics_only' indicates that we only want to compute */
1028           /* the glyph's metrics (lsb + advance width), not load the   */
1029           /* rest of it; so exit immediately                           */
1030           if ( builder->metrics_only )
1031             return PSaux_Err_Ok;
1032 
1033           break;
1034 
1035         case op_seac:
1036           /* return immediately after the processing */
1037           return t1operator_seac( decoder, top[0], top[1], top[2],
1038                                            (FT_Int)top[3], (FT_Int)top[4] );
1039 
1040         case op_sbw:
1041           FT_TRACE4(( " sbw" ));
1042 
1043           builder->parse_state = T1_Parse_Have_Width;
1044 
1045           builder->left_bearing.x += top[0];
1046           builder->left_bearing.y += top[1];
1047           builder->advance.x       = top[2];
1048           builder->advance.y       = top[3];
1049 
1050           builder->last.x = x = builder->pos_x + top[0];
1051           builder->last.y = y = builder->pos_y + top[1];
1052 
1053           /* the `metrics_only' indicates that we only want to compute */
1054           /* the glyph's metrics (lsb + advance width), not load the   */
1055           /* rest of it; so exit immediately                           */
1056           if ( builder->metrics_only )
1057             return PSaux_Err_Ok;
1058 
1059           break;
1060 
1061         case op_closepath:
1062           FT_TRACE4(( " closepath" ));
1063 
1064           /* if there is no path, `closepath' is a no-op */
1065           if ( builder->parse_state == T1_Parse_Have_Path   ||
1066                builder->parse_state == T1_Parse_Have_Moveto )
1067             close_contour( builder );
1068 
1069           builder->parse_state = T1_Parse_Have_Width;
1070           break;
1071 
1072         case op_hlineto:
1073           FT_TRACE4(( " hlineto" ));
1074 
1075           if ( start_point( builder, x, y ) )
1076             goto Fail;
1077 
1078           x += top[0];
1079           goto Add_Line;
1080 
1081         case op_hmoveto:
1082           FT_TRACE4(( " hmoveto" ));
1083 
1084           x += top[0];
1085           if ( !decoder->flex_state )
1086           {
1087             if ( builder->parse_state == T1_Parse_Start )
1088               goto Syntax_Error;
1089             builder->parse_state = T1_Parse_Have_Moveto;
1090           }
1091           break;
1092 
1093         case op_hvcurveto:
1094           FT_TRACE4(( " hvcurveto" ));
1095 
1096           if ( start_point( builder, x, y ) ||
1097                check_points( builder, 3 )   )
1098             goto Fail;
1099 
1100           x += top[0];
1101           add_point( builder, x, y, 0 );
1102           x += top[1];
1103           y += top[2];
1104           add_point( builder, x, y, 0 );
1105           y += top[3];
1106           add_point( builder, x, y, 1 );
1107           break;
1108 
1109         case op_rlineto:
1110           FT_TRACE4(( " rlineto" ));
1111 
1112           if ( start_point( builder, x, y ) )
1113             goto Fail;
1114 
1115           x += top[0];
1116           y += top[1];
1117 
1118         Add_Line:
1119           if ( add_point1( builder, x, y ) )
1120             goto Fail;
1121           break;
1122 
1123         case op_rmoveto:
1124           FT_TRACE4(( " rmoveto" ));
1125 
1126           x += top[0];
1127           y += top[1];
1128           if ( !decoder->flex_state )
1129           {
1130             if ( builder->parse_state == T1_Parse_Start )
1131               goto Syntax_Error;
1132             builder->parse_state = T1_Parse_Have_Moveto;
1133           }
1134           break;
1135 
1136         case op_rrcurveto:
1137           FT_TRACE4(( " rcurveto" ));
1138 
1139           if ( start_point( builder, x, y ) ||
1140                check_points( builder, 3 )   )
1141             goto Fail;
1142 
1143           x += top[0];
1144           y += top[1];
1145           add_point( builder, x, y, 0 );
1146 
1147           x += top[2];
1148           y += top[3];
1149           add_point( builder, x, y, 0 );
1150 
1151           x += top[4];
1152           y += top[5];
1153           add_point( builder, x, y, 1 );
1154           break;
1155 
1156         case op_vhcurveto:
1157           FT_TRACE4(( " vhcurveto" ));
1158 
1159           if ( start_point( builder, x, y ) ||
1160                check_points( builder, 3 )   )
1161             goto Fail;
1162 
1163           y += top[0];
1164           add_point( builder, x, y, 0 );
1165           x += top[1];
1166           y += top[2];
1167           add_point( builder, x, y, 0 );
1168           x += top[3];
1169           add_point( builder, x, y, 1 );
1170           break;
1171 
1172         case op_vlineto:
1173           FT_TRACE4(( " vlineto" ));
1174 
1175           if ( start_point( builder, x, y ) )
1176             goto Fail;
1177 
1178           y += top[0];
1179           goto Add_Line;
1180 
1181         case op_vmoveto:
1182           FT_TRACE4(( " vmoveto" ));
1183 
1184           y += top[0];
1185           if ( !decoder->flex_state )
1186           {
1187             if ( builder->parse_state == T1_Parse_Start )
1188               goto Syntax_Error;
1189             builder->parse_state = T1_Parse_Have_Moveto;
1190           }
1191           break;
1192 
1193         case op_div:
1194           FT_TRACE4(( " div" ));
1195 
1196           if ( top[1] )
1197           {
1198             *top = top[0] / top[1];
1199             ++top;
1200           }
1201           else
1202           {
1203             FT_ERROR(( "t1_decoder_parse_charstrings: division by 0\n" ));
1204             goto Syntax_Error;
1205           }
1206           break;
1207 
1208         case op_callsubr:
1209           {
1210             FT_Int  idx;
1211 
1212 
1213             FT_TRACE4(( " callsubr" ));
1214 
1215             idx = (FT_Int)top[0];
1216             if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs )
1217             {
1218               FT_ERROR(( "t1_decoder_parse_charstrings: "
1219                          "invalid subrs index\n" ));
1220               goto Syntax_Error;
1221             }
1222 
1223             if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
1224             {
1225               FT_ERROR(( "t1_decoder_parse_charstrings: "
1226                          "too many nested subrs\n" ));
1227               goto Syntax_Error;
1228             }
1229 
1230             zone->cursor = ip;  /* save current instruction pointer */
1231 
1232             zone++;
1233 
1234             /* The Type 1 driver stores subroutines without the seed bytes. */
1235             /* The CID driver stores subroutines with seed bytes.  This     */
1236             /* case is taken care of when decoder->subrs_len == 0.          */
1237             zone->base = decoder->subrs[idx];
1238 
1239             if ( decoder->subrs_len )
1240               zone->limit = zone->base + decoder->subrs_len[idx];
1241             else
1242             {
1243               /* We are using subroutines from a CID font.  We must adjust */
1244               /* for the seed bytes.                                       */
1245               zone->base  += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
1246               zone->limit  = decoder->subrs[idx + 1];
1247             }
1248 
1249             zone->cursor = zone->base;
1250 
1251             if ( !zone->base )
1252             {
1253               FT_ERROR(( "t1_decoder_parse_charstrings: "
1254                          "invoking empty subrs!\n" ));
1255               goto Syntax_Error;
1256             }
1257 
1258             decoder->zone = zone;
1259             ip            = zone->base;
1260             limit         = zone->limit;
1261             break;
1262           }
1263 
1264         case op_pop:
1265           FT_TRACE4(( " pop" ));
1266 
1267           if ( known_othersubr_result_cnt > 0 )
1268           {
1269             known_othersubr_result_cnt--;
1270             /* ignore, we pushed the operands ourselves */
1271             break;
1272           }
1273 
1274           if ( unknown_othersubr_result_cnt == 0 )
1275           {
1276             FT_ERROR(( "t1_decoder_parse_charstrings: "
1277                        "no more operands for othersubr!\n" ));
1278             goto Syntax_Error;
1279           }
1280 
1281           unknown_othersubr_result_cnt--;
1282           top++;   /* `push' the operand to callothersubr onto the stack */
1283           break;
1284 
1285         case op_return:
1286           FT_TRACE4(( " return" ));
1287 
1288           if ( zone <= decoder->zones )
1289           {
1290             FT_ERROR(( "t1_decoder_parse_charstrings: unexpected return\n" ));
1291             goto Syntax_Error;
1292           }
1293 
1294           zone--;
1295           ip            = zone->cursor;
1296           limit         = zone->limit;
1297           decoder->zone = zone;
1298           break;
1299 
1300         case op_dotsection:
1301           FT_TRACE4(( " dotsection" ));
1302 
1303           break;
1304 
1305         case op_hstem:
1306           FT_TRACE4(( " hstem" ));
1307 
1308           /* record horizontal hint */
1309           if ( hinter )
1310           {
1311             /* top[0] += builder->left_bearing.y; */
1312             hinter->stem( hinter->hints, 1, top );
1313           }
1314 
1315           break;
1316 
1317         case op_hstem3:
1318           FT_TRACE4(( " hstem3" ));
1319 
1320           /* record horizontal counter-controlled hints */
1321           if ( hinter )
1322             hinter->stem3( hinter->hints, 1, top );
1323 
1324           break;
1325 
1326         case op_vstem:
1327           FT_TRACE4(( " vstem" ));
1328 
1329           /* record vertical  hint */
1330           if ( hinter )
1331           {
1332             top[0] += orig_x;
1333             hinter->stem( hinter->hints, 0, top );
1334           }
1335 
1336           break;
1337 
1338         case op_vstem3:
1339           FT_TRACE4(( " vstem3" ));
1340 
1341           /* record vertical counter-controlled hints */
1342           if ( hinter )
1343           {
1344             FT_Pos  dx = orig_x;
1345 
1346 
1347             top[0] += dx;
1348             top[2] += dx;
1349             top[4] += dx;
1350             hinter->stem3( hinter->hints, 0, top );
1351           }
1352           break;
1353 
1354         case op_setcurrentpoint:
1355           FT_TRACE4(( " setcurrentpoint" ));
1356 
1357           /* From the T1 specs, section 6.4:                        */
1358           /*                                                        */
1359           /*   The setcurrentpoint command is used only in          */
1360           /*   conjunction with results from OtherSubrs procedures. */
1361 
1362           /* known_othersubr_result_cnt != 0 is already handled above */
1363           if ( decoder->flex_state != 1 )
1364           {
1365             FT_ERROR(( "t1_decoder_parse_charstrings: " ));
1366             FT_ERROR(( "unexpected `setcurrentpoint'\n" ));
1367 
1368             goto Syntax_Error;
1369           }
1370           else
1371             decoder->flex_state = 0;
1372           break;
1373 
1374         case op_unknown15:
1375           FT_TRACE4(( " opcode_15" ));
1376           /* nothing to do except to pop the two arguments */
1377           break;
1378 
1379         default:
1380           FT_ERROR(( "t1_decoder_parse_charstrings: "
1381                      "unhandled opcode %d\n", op ));
1382           goto Syntax_Error;
1383         }
1384 
1385         /* XXX Operators usually clear the operand stack;  */
1386         /*     only div, callsubr, callothersubr, pop, and */
1387         /*     return are different.                       */
1388         /*     In practice it doesn't matter (?).          */
1389 
1390         decoder->top = top;
1391 
1392       } /* general operator processing */
1393 
1394     } /* while ip < limit */
1395 
1396     FT_TRACE4(( "..end..\n\n" ));
1397 
1398   Fail:
1399     return error;
1400 
1401   Syntax_Error:
1402     return PSaux_Err_Syntax_Error;
1403 
1404   Stack_Underflow:
1405     return PSaux_Err_Stack_Underflow;
1406   }
1407 
1408 
1409   /* parse a single Type 1 glyph */
1410   FT_LOCAL_DEF( FT_Error )
t1_decoder_parse_glyph(T1_Decoder decoder,FT_UInt glyph)1411   t1_decoder_parse_glyph( T1_Decoder  decoder,
1412                           FT_UInt     glyph )
1413   {
1414     return decoder->parse_callback( decoder, glyph );
1415   }
1416 
1417 
1418   /* initialize T1 decoder */
1419   FT_LOCAL_DEF( FT_Error )
t1_decoder_init(T1_Decoder decoder,FT_Face face,FT_Size size,FT_GlyphSlot slot,FT_Byte ** glyph_names,PS_Blend blend,FT_Bool hinting,FT_Render_Mode hint_mode,T1_Decoder_Callback parse_callback)1420   t1_decoder_init( T1_Decoder           decoder,
1421                    FT_Face              face,
1422                    FT_Size              size,
1423                    FT_GlyphSlot         slot,
1424                    FT_Byte**            glyph_names,
1425                    PS_Blend             blend,
1426                    FT_Bool              hinting,
1427                    FT_Render_Mode       hint_mode,
1428                    T1_Decoder_Callback  parse_callback )
1429   {
1430     FT_MEM_ZERO( decoder, sizeof ( *decoder ) );
1431 
1432     /* retrieve PSNames interface from list of current modules */
1433     {
1434       FT_Service_PsCMaps  psnames = 0;
1435 
1436 
1437       FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
1438       if ( !psnames )
1439       {
1440         FT_ERROR(( "t1_decoder_init: " ));
1441         FT_ERROR(( "the `psnames' module is not available\n" ));
1442         return PSaux_Err_Unimplemented_Feature;
1443       }
1444 
1445       decoder->psnames = psnames;
1446     }
1447 
1448     t1_builder_init( &decoder->builder, face, size, slot, hinting );
1449 
1450     /* decoder->buildchar and decoder->len_buildchar have to be  */
1451     /* initialized by the caller since we cannot know the length */
1452     /* of the BuildCharArray                                     */
1453 
1454     decoder->num_glyphs     = (FT_UInt)face->num_glyphs;
1455     decoder->glyph_names    = glyph_names;
1456     decoder->hint_mode      = hint_mode;
1457     decoder->blend          = blend;
1458     decoder->parse_callback = parse_callback;
1459 
1460     decoder->funcs          = t1_decoder_funcs;
1461 
1462     return PSaux_Err_Ok;
1463   }
1464 
1465 
1466   /* finalize T1 decoder */
1467   FT_LOCAL_DEF( void )
t1_decoder_done(T1_Decoder decoder)1468   t1_decoder_done( T1_Decoder  decoder )
1469   {
1470     t1_builder_done( &decoder->builder );
1471   }
1472 
1473 
1474 /* END */
1475