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