update for HEAD-2003050101
[reactos.git] / lib / freetype / src / psaux / t1decode.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  t1decode.c                                                             */
4 /*                                                                         */
5 /*    PostScript Type 1 decoding routines (body).                          */
6 /*                                                                         */
7 /*  Copyright 2000-2001, 2002 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
69     op_max    /* never remove this one */
70
71   } T1_Operator;
72
73
74   static
75   const FT_Int  t1_args_count[op_max] =
76   {
77     0, /* none */
78     0, /* endchar */
79     2, /* hsbw */
80     5, /* seac */
81     4, /* sbw */
82     0, /* closepath */
83     1, /* hlineto */
84     1, /* hmoveto */
85     4, /* hvcurveto */
86     2, /* rlineto */
87     2, /* rmoveto */
88     6, /* rrcurveto */
89     4, /* vhcurveto */
90     1, /* vlineto */
91     1, /* vmoveto */
92     0, /* dotsection */
93     2, /* hstem */
94     6, /* hstem3 */
95     2, /* vstem */
96     6, /* vstem3 */
97     2, /* div */
98    -1, /* callothersubr */
99     1, /* callsubr */
100     0, /* pop */
101     0, /* return */
102     2  /* setcurrentpoint */
103   };
104
105
106   /*************************************************************************/
107   /*                                                                       */
108   /* <Function>                                                            */
109   /*    t1_lookup_glyph_by_stdcharcode                                     */
110   /*                                                                       */
111   /* <Description>                                                         */
112   /*    Looks up a given glyph by its StandardEncoding charcode.  Used to  */
113   /*    implement the SEAC Type 1 operator.                                */
114   /*                                                                       */
115   /* <Input>                                                               */
116   /*    face     :: The current face object.                               */
117   /*                                                                       */
118   /*    charcode :: The character code to look for.                        */
119   /*                                                                       */
120   /* <Return>                                                              */
121   /*    A glyph index in the font face.  Returns -1 if the corresponding   */
122   /*    glyph wasn't found.                                                */
123   /*                                                                       */
124   static FT_Int
125   t1_lookup_glyph_by_stdcharcode( T1_Decoder  decoder,
126                                   FT_Int      charcode )
127   {
128     FT_UInt           n;
129     const FT_String*  glyph_name;
130     PSNames_Service   psnames = decoder->psnames;
131
132
133     /* check range of standard char code */
134     if ( charcode < 0 || charcode > 255 )
135       return -1;
136
137     glyph_name = psnames->adobe_std_strings(
138                    psnames->adobe_std_encoding[charcode]);
139
140     for ( n = 0; n < decoder->num_glyphs; n++ )
141     {
142       FT_String*  name = (FT_String*)decoder->glyph_names[n];
143
144
145       if ( name && name[0] == glyph_name[0]  &&
146            ft_strcmp( name,glyph_name ) == 0 )
147         return n;
148     }
149
150     return -1;
151   }
152
153
154   /*************************************************************************/
155   /*                                                                       */
156   /* <Function>                                                            */
157   /*    t1operator_seac                                                    */
158   /*                                                                       */
159   /* <Description>                                                         */
160   /*    Implements the `seac' Type 1 operator for a Type 1 decoder.        */
161   /*                                                                       */
162   /* <Input>                                                               */
163   /*    decoder :: The current CID decoder.                                */
164   /*                                                                       */
165   /*    asb     :: The accent's side bearing.                              */
166   /*                                                                       */
167   /*    adx     :: The horizontal offset of the accent.                    */
168   /*                                                                       */
169   /*    ady     :: The vertical offset of the accent.                      */
170   /*                                                                       */
171   /*    bchar   :: The base character's StandardEncoding charcode.         */
172   /*                                                                       */
173   /*    achar   :: The accent character's StandardEncoding charcode.       */
174   /*                                                                       */
175   /* <Return>                                                              */
176   /*    FreeType error code.  0 means success.                             */
177   /*                                                                       */
178   static FT_Error
179   t1operator_seac( T1_Decoder  decoder,
180                    FT_Pos      asb,
181                    FT_Pos      adx,
182                    FT_Pos      ady,
183                    FT_Int      bchar,
184                    FT_Int      achar )
185   {
186     FT_Error     error;
187     FT_Int       bchar_index, achar_index;
188 #if 0
189     FT_Int       n_base_points;
190     FT_Outline*  base = decoder->builder.base;
191 #endif
192     FT_Vector    left_bearing, advance;
193
194
195     /* seac weirdness */
196     adx += decoder->builder.left_bearing.x;
197
198     /* `glyph_names' is set to 0 for CID fonts which do not */
199     /* include an encoding.  How can we deal with these?    */
200     if ( decoder->glyph_names == 0 )
201     {
202       FT_ERROR(( "t1operator_seac:" ));
203       FT_ERROR(( " glyph names table not available in this font!\n" ));
204       return PSaux_Err_Syntax_Error;
205     }
206
207     bchar_index = t1_lookup_glyph_by_stdcharcode( decoder, bchar );
208     achar_index = t1_lookup_glyph_by_stdcharcode( decoder, achar );
209
210     if ( bchar_index < 0 || achar_index < 0 )
211     {
212       FT_ERROR(( "t1operator_seac:" ));
213       FT_ERROR(( " invalid seac character code arguments\n" ));
214       return PSaux_Err_Syntax_Error;
215     }
216
217     /* if we are trying to load a composite glyph, do not load the */
218     /* accent character and return the array of subglyphs.         */
219     if ( decoder->builder.no_recurse )
220     {
221       FT_GlyphSlot    glyph  = (FT_GlyphSlot)decoder->builder.glyph;
222       FT_GlyphLoader  loader = glyph->internal->loader;
223       FT_SubGlyph     subg;
224
225
226       /* reallocate subglyph array if necessary */
227       error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
228       if ( error )
229         goto Exit;
230
231       subg = loader->current.subglyphs;
232
233       /* subglyph 0 = base character */
234       subg->index = bchar_index;
235       subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
236                     FT_SUBGLYPH_FLAG_USE_MY_METRICS;
237       subg->arg1  = 0;
238       subg->arg2  = 0;
239       subg++;
240
241       /* subglyph 1 = accent character */
242       subg->index = achar_index;
243       subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
244       subg->arg1  = adx - asb;
245       subg->arg2  = ady;
246
247       /* set up remaining glyph fields */
248       glyph->num_subglyphs = 2;
249       glyph->subglyphs     = loader->base.subglyphs;
250       glyph->format        = FT_GLYPH_FORMAT_COMPOSITE;
251
252       loader->current.num_subglyphs = 2;
253       goto Exit;
254     }
255
256     /* First load `bchar' in builder */
257     /* now load the unscaled outline */
258
259     FT_GlyphLoader_Prepare( decoder->builder.loader );  /* prepare loader */
260
261     error = t1_decoder_parse_glyph( decoder, bchar_index );
262     if ( error )
263       goto Exit;
264
265 #if 0
266     n_base_points = base->n_points;
267 #endif
268
269     /* save the left bearing and width of the base character */
270     /* as they will be erased by the next load.              */
271
272     left_bearing = decoder->builder.left_bearing;
273     advance      = decoder->builder.advance;
274
275     decoder->builder.left_bearing.x = 0;
276     decoder->builder.left_bearing.y = 0;
277
278     decoder->builder.pos_x = adx - asb;
279     decoder->builder.pos_y = ady;
280
281     /* Now load `achar' on top of */
282     /* the base outline           */
283     error = t1_decoder_parse_glyph( decoder, achar_index );
284     if ( error )
285       goto Exit;
286
287     /* restore the left side bearing and   */
288     /* advance width of the base character */
289
290     decoder->builder.left_bearing = left_bearing;
291     decoder->builder.advance      = advance;
292
293     /* XXX: old code doesn't work with PostScript hinter */
294 #if 0
295     /* Finally, move the accent */
296     if ( decoder->builder.load_points )
297     {
298       FT_Outline  dummy;
299
300
301       dummy.n_points = (short)( base->n_points - n_base_points );
302       dummy.points   = base->points + n_base_points;
303
304       FT_Outline_Translate( &dummy, adx - asb, ady );
305     }
306 #else
307     decoder->builder.pos_x = 0;
308     decoder->builder.pos_y = 0;
309 #endif
310
311   Exit:
312     return error;
313   }
314
315
316   /*************************************************************************/
317   /*                                                                       */
318   /* <Function>                                                            */
319   /*    t1_decoder_parse_charstrings                                       */
320   /*                                                                       */
321   /* <Description>                                                         */
322   /*    Parses a given Type 1 charstrings program.                         */
323   /*                                                                       */
324   /* <Input>                                                               */
325   /*    decoder         :: The current Type 1 decoder.                     */
326   /*                                                                       */
327   /*    charstring_base :: The base address of the charstring stream.      */
328   /*                                                                       */
329   /*    charstring_len  :: The length in bytes of the charstring stream.   */
330   /*                                                                       */
331   /* <Return>                                                              */
332   /*    FreeType error code.  0 means success.                             */
333   /*                                                                       */
334   FT_LOCAL_DEF( FT_Error )
335   t1_decoder_parse_charstrings( T1_Decoder  decoder,
336                                 FT_Byte*    charstring_base,
337                                 FT_UInt     charstring_len )
338   {
339     FT_Error         error;
340     T1_Decoder_Zone  zone;
341     FT_Byte*         ip;
342     FT_Byte*         limit;
343     T1_Builder       builder = &decoder->builder;
344     FT_Pos           x, y, orig_x, orig_y;
345
346     T1_Hints_Funcs   hinter;
347
348
349     /* we don't want to touch the source code -- use macro trick */
350 #define start_point    t1_builder_start_point
351 #define check_points   t1_builder_check_points
352 #define add_point      t1_builder_add_point
353 #define add_point1     t1_builder_add_point1
354 #define add_contour    t1_builder_add_contour
355 #define close_contour  t1_builder_close_contour
356
357     /* First of all, initialize the decoder */
358     decoder->top  = decoder->stack;
359     decoder->zone = decoder->zones;
360     zone          = decoder->zones;
361
362     builder->path_begun  = 0;
363
364     hinter = (T1_Hints_Funcs)builder->hints_funcs;
365
366     zone->base           = charstring_base;
367     limit = zone->limit  = charstring_base + charstring_len;
368     ip    = zone->cursor = zone->base;
369
370     error = PSaux_Err_Ok;
371
372     x = orig_x = builder->pos_x;
373     y = orig_y = builder->pos_y;
374
375     /* begin hints recording session, if any */
376     if ( hinter )
377       hinter->open( hinter->hints );
378
379     /* now, execute loop */
380     while ( ip < limit )
381     {
382       FT_Long*     top   = decoder->top;
383       T1_Operator  op    = op_none;
384       FT_Long      value = 0;
385
386
387       /*********************************************************************/
388       /*                                                                   */
389       /* Decode operator or operand                                        */
390       /*                                                                   */
391       /*                                                                   */
392
393       /* first of all, decompress operator or value */
394       switch ( *ip++ )
395       {
396       case 1:
397         op = op_hstem;
398         break;
399
400       case 3:
401         op = op_vstem;
402         break;
403       case 4:
404         op = op_vmoveto;
405         break;
406       case 5:
407         op = op_rlineto;
408         break;
409       case 6:
410         op = op_hlineto;
411         break;
412       case 7:
413         op = op_vlineto;
414         break;
415       case 8:
416         op = op_rrcurveto;
417         break;
418       case 9:
419         op = op_closepath;
420         break;
421       case 10:
422         op = op_callsubr;
423         break;
424       case 11:
425         op = op_return;
426         break;
427
428       case 13:
429         op = op_hsbw;
430         break;
431       case 14:
432         op = op_endchar;
433         break;
434
435       case 15:          /* undocumented, obsolete operator */
436         op = op_none;
437         break;
438
439       case 21:
440         op = op_rmoveto;
441         break;
442       case 22:
443         op = op_hmoveto;
444         break;
445
446       case 30:
447         op = op_vhcurveto;
448         break;
449       case 31:
450         op = op_hvcurveto;
451         break;
452
453       case 12:
454         if ( ip > limit )
455         {
456           FT_ERROR(( "t1_decoder_parse_charstrings: "
457                      "invalid escape (12+EOF)\n" ));
458           goto Syntax_Error;
459         }
460
461         switch ( *ip++ )
462         {
463         case 0:
464           op = op_dotsection;
465           break;
466         case 1:
467           op = op_vstem3;
468           break;
469         case 2:
470           op = op_hstem3;
471           break;
472         case 6:
473           op = op_seac;
474           break;
475         case 7:
476           op = op_sbw;
477           break;
478         case 12:
479           op = op_div;
480           break;
481         case 16:
482           op = op_callothersubr;
483           break;
484         case 17:
485           op = op_pop;
486           break;
487         case 33:
488           op = op_setcurrentpoint;
489           break;
490
491         default:
492           FT_ERROR(( "t1_decoder_parse_charstrings: "
493                      "invalid escape (12+%d)\n",
494                      ip[-1] ));
495           goto Syntax_Error;
496         }
497         break;
498
499       case 255:    /* four bytes integer */
500         if ( ip + 4 > limit )
501         {
502           FT_ERROR(( "t1_decoder_parse_charstrings: "
503                      "unexpected EOF in integer\n" ));
504           goto Syntax_Error;
505         }
506
507         value = (FT_Int32)( ((FT_Long)ip[0] << 24) |
508                             ((FT_Long)ip[1] << 16) |
509                             ((FT_Long)ip[2] << 8 ) |
510                                       ip[3] );
511         ip += 4;
512         break;
513
514       default:
515         if ( ip[-1] >= 32 )
516         {
517           if ( ip[-1] < 247 )
518             value = (FT_Long)ip[-1] - 139;
519           else
520           {
521             if ( ++ip > limit )
522             {
523               FT_ERROR(( "t1_decoder_parse_charstrings: " ));
524               FT_ERROR(( "unexpected EOF in integer\n" ));
525               goto Syntax_Error;
526             }
527
528             if ( ip[-2] < 251 )
529               value =  ( ( (FT_Long)ip[-2] - 247 ) << 8 ) + ip[-1] + 108;
530             else
531               value = -( ( ( (FT_Long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );
532           }
533         }
534         else
535         {
536           FT_ERROR(( "t1_decoder_parse_charstrings: "
537                      "invalid byte (%d)\n", ip[-1] ));
538           goto Syntax_Error;
539         }
540       }
541
542       /*********************************************************************/
543       /*                                                                   */
544       /*  Push value on stack, or process operator                         */
545       /*                                                                   */
546       /*                                                                   */
547       if ( op == op_none )
548       {
549         if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
550         {
551           FT_ERROR(( "t1_decoder_parse_charstrings: stack overflow!\n" ));
552           goto Syntax_Error;
553         }
554
555         FT_TRACE4(( " %ld", value ));
556
557         *top++       = value;
558         decoder->top = top;
559       }
560       else if ( op == op_callothersubr )  /* callothersubr */
561       {
562         FT_TRACE4(( " callothersubr" ));
563
564         if ( top - decoder->stack < 2 )
565           goto Stack_Underflow;
566
567         top -= 2;
568         switch ( top[1] )
569         {
570         case 1:                     /* start flex feature */
571           if ( top[0] != 0 )
572             goto Unexpected_OtherSubr;
573
574           decoder->flex_state        = 1;
575           decoder->num_flex_vectors  = 0;
576           if ( start_point( builder, x, y ) ||
577                check_points( builder, 6 )   )
578             goto Memory_Error;
579           break;
580
581         case 2:                     /* add flex vectors */
582           {
583             FT_Int  idx;
584
585
586             if ( top[0] != 0 )
587               goto Unexpected_OtherSubr;
588
589             /* note that we should not add a point for index 0; */
590             /* this will move our current position to the flex  */
591             /* point without adding any point to the outline    */
592             idx = decoder->num_flex_vectors++;
593             if ( idx > 0 && idx < 7 )
594               add_point( builder,
595                          x,
596                          y,
597                          (FT_Byte)( idx == 3 || idx == 6 ) );
598           }
599           break;
600
601         case 0:                     /* end flex feature */
602           if ( top[0] != 3 )
603             goto Unexpected_OtherSubr;
604
605           if ( decoder->flex_state       == 0 ||
606                decoder->num_flex_vectors != 7 )
607           {
608             FT_ERROR(( "t1_decoder_parse_charstrings: "
609                        "unexpected flex end\n" ));
610             goto Syntax_Error;
611           }
612
613           /* now consume the remaining `pop pop setcurpoint' */
614           if ( ip + 6 > limit ||
615                ip[0] != 12 || ip[1] != 17 || /* pop */
616                ip[2] != 12 || ip[3] != 17 || /* pop */
617                ip[4] != 12 || ip[5] != 33 )  /* setcurpoint */
618           {
619             FT_ERROR(( "t1_decoder_parse_charstrings: "
620                        "invalid flex charstring\n" ));
621             goto Syntax_Error;
622           }
623
624           ip += 6;
625           decoder->flex_state = 0;
626           break;
627
628         case 3:                     /* change hints */
629           if ( top[0] != 1 )
630             goto Unexpected_OtherSubr;
631
632           /* eat the following `pop' */
633           if ( ip + 2 > limit )
634           {
635             FT_ERROR(( "t1_decoder_parse_charstrings: "
636                        "invalid escape (12+%d)\n", ip[-1] ));
637             goto Syntax_Error;
638           }
639
640           if ( ip[0] != 12 || ip[1] != 17 )
641           {
642             FT_ERROR(( "t1_decoder_parse_charstrings: " ));
643             FT_ERROR(( "`pop' expected, found (%d %d)\n", ip[0], ip[1] ));
644             goto Syntax_Error;
645           }
646           ip += 2;
647
648           if ( hinter )
649             hinter->reset( hinter->hints, builder->current->n_points );
650
651           break;
652
653         case 12:
654         case 13:
655           /* counter control hints, clear stack */
656           top = decoder->stack;
657           break;
658
659         case 14:
660         case 15:
661         case 16:
662         case 17:
663         case 18:                    /* multiple masters */
664           {
665             PS_Blend  blend = decoder->blend;
666             FT_UInt   num_points, nn, mm;
667             FT_Long*  delta;
668             FT_Long*  values;
669
670
671             if ( !blend )
672             {
673               FT_ERROR(( "t1_decoder_parse_charstrings: " ));
674               FT_ERROR(( "unexpected multiple masters operator!\n" ));
675               goto Syntax_Error;
676             }
677
678             num_points = (FT_UInt)top[1] - 13 + ( top[1] == 18 );
679             if ( top[0] != (FT_Int)( num_points * blend->num_designs ) )
680             {
681               FT_ERROR(( "t1_decoder_parse_charstrings: " ));
682               FT_ERROR(( "incorrect number of mm arguments\n" ));
683               goto Syntax_Error;
684             }
685
686             top -= blend->num_designs * num_points;
687             if ( top < decoder->stack )
688               goto Stack_Underflow;
689
690             /* we want to compute:                                   */
691             /*                                                       */
692             /*  a0*w0 + a1*w1 + ... + ak*wk                          */
693             /*                                                       */
694             /* but we only have the a0, a1-a0, a2-a0, .. ak-a0       */
695             /* however, given that w0 + w1 + ... + wk == 1, we can   */
696             /* rewrite it easily as:                                 */
697             /*                                                       */
698             /*  a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk       */
699             /*                                                       */
700             /* where k == num_designs-1                              */
701             /*                                                       */
702             /* I guess that's why it's written in this `compact'     */
703             /* form.                                                 */
704             /*                                                       */
705             delta  = top + num_points;
706             values = top;
707             for ( nn = 0; nn < num_points; nn++ )
708             {
709               FT_Int  tmp = values[0];
710
711
712               for ( mm = 1; mm < blend->num_designs; mm++ )
713                 tmp += FT_MulFix( *delta++, blend->weight_vector[mm] );
714
715               *values++ = tmp;
716             }
717             /* note that `top' will be incremented later by calls to `pop' */
718             break;
719           }
720
721         default:
722         Unexpected_OtherSubr:
723           FT_ERROR(( "t1_decoder_parse_charstrings: "
724                      "invalid othersubr [%d %d]!\n", top[0], top[1] ));
725           goto Syntax_Error;
726         }
727         decoder->top = top;
728       }
729       else  /* general operator */
730       {
731         FT_Int  num_args = t1_args_count[op];
732
733
734         if ( top - decoder->stack < num_args )
735           goto Stack_Underflow;
736
737         top -= num_args;
738
739         switch ( op )
740         {
741         case op_endchar:
742           FT_TRACE4(( " endchar" ));
743
744           close_contour( builder );
745
746           /* close hints recording session */
747           if ( hinter )
748           {
749             if (hinter->close( hinter->hints, builder->current->n_points ))
750               goto Syntax_Error;
751
752             /* apply hints to the loaded glyph outline now */
753             hinter->apply( hinter->hints,
754                            builder->current,
755                            (PSH_Globals) builder->hints_globals,
756                            decoder->hint_mode );
757           }
758
759           /* add current outline to the glyph slot */
760           FT_GlyphLoader_Add( builder->loader );
761
762           /* return now! */
763           FT_TRACE4(( "\n\n" ));
764           return PSaux_Err_Ok;
765
766         case op_hsbw:
767           FT_TRACE4(( " hsbw" ));
768
769           builder->left_bearing.x += top[0];
770           builder->advance.x       = top[1];
771           builder->advance.y       = 0;
772
773           orig_x = builder->last.x = x = builder->pos_x + top[0];
774           orig_y = builder->last.y = y = builder->pos_y;
775
776           FT_UNUSED( orig_y );
777
778           /* the `metrics_only' indicates that we only want to compute */
779           /* the glyph's metrics (lsb + advance width), not load the   */
780           /* rest of it; so exit immediately                           */
781           if ( builder->metrics_only )
782             return PSaux_Err_Ok;
783
784           break;
785
786         case op_seac:
787           /* return immediately after the processing */
788           return t1operator_seac( decoder, top[0], top[1],
789                                            top[2], top[3], top[4] );
790
791         case op_sbw:
792           FT_TRACE4(( " sbw" ));
793
794           builder->left_bearing.x += top[0];
795           builder->left_bearing.y += top[1];
796           builder->advance.x       = top[2];
797           builder->advance.y       = top[3];
798
799           builder->last.x = x = builder->pos_x + top[0];
800           builder->last.y = y = builder->pos_y + top[1];
801
802           /* the `metrics_only' indicates that we only want to compute */
803           /* the glyph's metrics (lsb + advance width), not load the   */
804           /* rest of it; so exit immediately                           */
805           if ( builder->metrics_only )
806             return PSaux_Err_Ok;
807
808           break;
809
810         case op_closepath:
811           FT_TRACE4(( " closepath" ));
812
813           close_contour( builder );
814           builder->path_begun = 0;
815           break;
816
817         case op_hlineto:
818           FT_TRACE4(( " hlineto" ));
819
820           if ( start_point( builder, x, y ) )
821             goto Memory_Error;
822
823           x += top[0];
824           goto Add_Line;
825
826         case op_hmoveto:
827           FT_TRACE4(( " hmoveto" ));
828
829           x += top[0];
830           if ( !decoder->flex_state )
831             builder->path_begun = 0;
832           break;
833
834         case op_hvcurveto:
835           FT_TRACE4(( " hvcurveto" ));
836
837           if ( start_point( builder, x, y ) ||
838                check_points( builder, 3 )   )
839             goto Memory_Error;
840
841           x += top[0];
842           add_point( builder, x, y, 0 );
843           x += top[1];
844           y += top[2];
845           add_point( builder, x, y, 0 );
846           y += top[3];
847           add_point( builder, x, y, 1 );
848           break;
849
850         case op_rlineto:
851           FT_TRACE4(( " rlineto" ));
852
853           if ( start_point( builder, x, y ) )
854             goto Memory_Error;
855
856           x += top[0];
857           y += top[1];
858
859         Add_Line:
860           if ( add_point1( builder, x, y ) )
861             goto Memory_Error;
862           break;
863
864         case op_rmoveto:
865           FT_TRACE4(( " rmoveto" ));
866
867           x += top[0];
868           y += top[1];
869           if ( !decoder->flex_state )
870             builder->path_begun = 0;
871           break;
872
873         case op_rrcurveto:
874           FT_TRACE4(( " rcurveto" ));
875
876           if ( start_point( builder, x, y ) ||
877                check_points( builder, 3 )   )
878             goto Memory_Error;
879
880           x += top[0];
881           y += top[1];
882           add_point( builder, x, y, 0 );
883
884           x += top[2];
885           y += top[3];
886           add_point( builder, x, y, 0 );
887
888           x += top[4];
889           y += top[5];
890           add_point( builder, x, y, 1 );
891           break;
892
893         case op_vhcurveto:
894           FT_TRACE4(( " vhcurveto" ));
895
896           if ( start_point( builder, x, y ) ||
897                check_points( builder, 3 )   )
898             goto Memory_Error;
899
900           y += top[0];
901           add_point( builder, x, y, 0 );
902           x += top[1];
903           y += top[2];
904           add_point( builder, x, y, 0 );
905           x += top[3];
906           add_point( builder, x, y, 1 );
907           break;
908
909         case op_vlineto:
910           FT_TRACE4(( " vlineto" ));
911
912           if ( start_point( builder, x, y ) )
913             goto Memory_Error;
914
915           y += top[0];
916           goto Add_Line;
917
918         case op_vmoveto:
919           FT_TRACE4(( " vmoveto" ));
920
921           y += top[0];
922           if ( !decoder->flex_state )
923             builder->path_begun = 0;
924           break;
925
926         case op_div:
927           FT_TRACE4(( " div" ));
928
929           if ( top[1] )
930           {
931             *top = top[0] / top[1];
932             ++top;
933           }
934           else
935           {
936             FT_ERROR(( "t1_decoder_parse_charstrings: division by 0\n" ));
937             goto Syntax_Error;
938           }
939           break;
940
941         case op_callsubr:
942           {
943             FT_Int  idx;
944
945
946             FT_TRACE4(( " callsubr" ));
947
948             idx = top[0];
949             if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs )
950             {
951               FT_ERROR(( "t1_decoder_parse_charstrings: "
952                          "invalid subrs index\n" ));
953               goto Syntax_Error;
954             }
955
956             if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
957             {
958               FT_ERROR(( "t1_decoder_parse_charstrings: "
959                          "too many nested subrs\n" ));
960               goto Syntax_Error;
961             }
962
963             zone->cursor = ip;  /* save current instruction pointer */
964
965             zone++;
966
967             /* The Type 1 driver stores subroutines without the seed bytes. */
968             /* The CID driver stores subroutines with seed bytes.  This     */
969             /* case is taken care of when decoder->subrs_len == 0.          */
970             zone->base = decoder->subrs[idx];
971
972             if ( decoder->subrs_len )
973               zone->limit = zone->base + decoder->subrs_len[idx];
974             else
975             {
976               /* We are using subroutines from a CID font.  We must adjust */
977               /* for the seed bytes.                                       */
978               zone->base  += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
979               zone->limit  = decoder->subrs[idx + 1];
980             }
981
982             zone->cursor = zone->base;
983
984             if ( !zone->base )
985             {
986               FT_ERROR(( "t1_decoder_parse_charstrings: "
987                          "invoking empty subrs!\n" ));
988               goto Syntax_Error;
989             }
990
991             decoder->zone = zone;
992             ip            = zone->base;
993             limit         = zone->limit;
994             break;
995           }
996
997         case op_pop:
998           FT_TRACE4(( " pop" ));
999
1000           /* theoretically, the arguments are already on the stack */
1001           top++;
1002           break;
1003
1004         case op_return:
1005           FT_TRACE4(( " return" ));
1006
1007           if ( zone <= decoder->zones )
1008           {
1009             FT_ERROR(( "t1_decoder_parse_charstrings: unexpected return\n" ));
1010             goto Syntax_Error;
1011           }
1012
1013           zone--;
1014           ip            = zone->cursor;
1015           limit         = zone->limit;
1016           decoder->zone = zone;
1017           break;
1018
1019         case op_dotsection:
1020           FT_TRACE4(( " dotsection" ));
1021
1022           break;
1023
1024         case op_hstem:
1025           FT_TRACE4(( " hstem" ));
1026
1027           /* record horizontal hint */
1028           if ( hinter )
1029           {
1030             /* top[0] += builder->left_bearing.y; */
1031             hinter->stem( hinter->hints, 1, top );
1032           }
1033
1034           break;
1035
1036         case op_hstem3:
1037           FT_TRACE4(( " hstem3" ));
1038
1039           /* record horizontal counter-controlled hints */
1040           if ( hinter )
1041             hinter->stem3( hinter->hints, 1, top );
1042
1043           break;
1044
1045         case op_vstem:
1046           FT_TRACE4(( " vstem" ));
1047
1048           /* record vertical  hint */
1049           if ( hinter )
1050           {
1051             top[0] += orig_x;
1052             hinter->stem( hinter->hints, 0, top );
1053           }
1054
1055           break;
1056
1057         case op_vstem3:
1058           FT_TRACE4(( " vstem3" ));
1059
1060           /* record vertical counter-controlled hints */
1061           if ( hinter )
1062           {
1063             FT_Pos  dx = orig_x;
1064
1065
1066             top[0] += dx;
1067             top[2] += dx;
1068             top[4] += dx;
1069             hinter->stem3( hinter->hints, 0, top );
1070           }
1071           break;
1072
1073         case op_setcurrentpoint:
1074           FT_TRACE4(( " setcurrentpoint" ));
1075
1076           FT_ERROR(( "t1_decoder_parse_charstrings: " ));
1077           FT_ERROR(( "unexpected `setcurrentpoint'\n" ));
1078           goto Syntax_Error;
1079
1080         default:
1081           FT_ERROR(( "t1_decoder_parse_charstrings: "
1082                      "unhandled opcode %d\n", op ));
1083           goto Syntax_Error;
1084         }
1085
1086         decoder->top = top;
1087
1088       } /* general operator processing */
1089
1090     } /* while ip < limit */
1091
1092     FT_TRACE4(( "..end..\n\n" ));
1093
1094     return error;
1095
1096   Syntax_Error:
1097     return PSaux_Err_Syntax_Error;
1098
1099   Stack_Underflow:
1100     return PSaux_Err_Stack_Underflow;
1101
1102   Memory_Error:
1103     return builder->error;
1104   }
1105
1106
1107   /* parse a single Type 1 glyph */
1108   FT_LOCAL_DEF( FT_Error )
1109   t1_decoder_parse_glyph( T1_Decoder  decoder,
1110                           FT_UInt     glyph )
1111   {
1112     return decoder->parse_callback( decoder, glyph );
1113   }
1114
1115
1116   /* initialize T1 decoder */
1117   FT_LOCAL_DEF( FT_Error )
1118   t1_decoder_init( T1_Decoder           decoder,
1119                    FT_Face              face,
1120                    FT_Size              size,
1121                    FT_GlyphSlot         slot,
1122                    FT_Byte**            glyph_names,
1123                    PS_Blend             blend,
1124                    FT_Bool              hinting,
1125                    FT_Render_Mode       hint_mode,
1126                    T1_Decoder_Callback  parse_callback )
1127   {
1128     FT_MEM_ZERO( decoder, sizeof ( *decoder ) );
1129
1130     /* retrieve PSNames interface from list of current modules */
1131     {
1132       PSNames_Service  psnames = 0;
1133
1134
1135       psnames = (PSNames_Service)FT_Get_Module_Interface(
1136                   FT_FACE_LIBRARY(face), "psnames" );
1137       if ( !psnames )
1138       {
1139         FT_ERROR(( "t1_decoder_init: " ));
1140         FT_ERROR(( "the `psnames' module is not available\n" ));
1141         return PSaux_Err_Unimplemented_Feature;
1142       }
1143
1144       decoder->psnames = psnames;
1145     }
1146
1147     t1_builder_init( &decoder->builder, face, size, slot, hinting );
1148
1149     decoder->num_glyphs     = (FT_UInt)face->num_glyphs;
1150     decoder->glyph_names    = glyph_names;
1151     decoder->hint_flags     = face->internal->hint_flags;
1152     decoder->hint_mode      = hint_mode;
1153     decoder->blend          = blend;
1154     decoder->parse_callback = parse_callback;
1155
1156     decoder->funcs          = t1_decoder_funcs;
1157
1158     return 0;
1159   }
1160
1161
1162   /* finalize T1 decoder */
1163   FT_LOCAL_DEF( void )
1164   t1_decoder_done( T1_Decoder  decoder )
1165   {
1166     t1_builder_done( &decoder->builder );
1167   }
1168
1169
1170 /* END */