source: trunk/poppler/freetype2/src/psaux/t1decode.c @ 262

Last change on this file since 262 was 262, checked in by Eugene Romanenko, 12 years ago

PDF plugin: freetype library updated to version 2.3.8

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