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