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