update for HEAD-2003021201
[reactos.git] / subsys / win32k / freetype / src / type1 / t1gload.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  t1gload.c                                                              */
4 /*                                                                         */
5 /*    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 "t1gload.h"
22
23 #ifndef T1_CONFIG_OPTION_DISABLE_HINTER
24 #include "t1hinter.h"
25 #endif
26
27 #else /* FT_FLAT_COMPILE */
28
29 #include <freetype/src/type1/t1gload.h>
30
31 #ifndef T1_CONFIG_OPTION_DISABLE_HINTER
32 #include <freetype/src/type1/t1hinter.h>
33 #endif
34
35 #endif /* FT_FLAT_COMPILE */
36
37
38 #include <freetype/internal/ftdebug.h>
39 #include <freetype/internal/ftstream.h>
40 #include <freetype/ftoutln.h>
41
42 #include <string.h>     /* for strcmp() */
43
44
45   /*************************************************************************/
46   /*                                                                       */
47   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
48   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
49   /* messages during execution.                                            */
50   /*                                                                       */
51 #undef  FT_COMPONENT
52 #define FT_COMPONENT  trace_t1gload
53
54
55   /*************************************************************************/
56   /*************************************************************************/
57   /*************************************************************************/
58   /**********                                                      *********/
59   /**********                                                      *********/
60   /**********             GENERIC CHARSTRING PARSING               *********/
61   /**********                                                      *********/
62   /**********                                                      *********/
63   /*************************************************************************/
64   /*************************************************************************/
65   /*************************************************************************/
66
67
68   static
69   void  T1_Reset_Builder( T1_Builder*  builder,
70                           FT_Bool      reset_base )
71   {
72     builder->pos_x = 0;
73     builder->pos_y = 0;
74
75     builder->left_bearing.x = 0;
76     builder->left_bearing.y = 0;
77     builder->advance.x      = 0;
78     builder->advance.y      = 0;
79
80     builder->pass       = 0;
81     builder->hint_point = 0;
82
83     if ( builder->loader )
84     {
85       if ( reset_base )
86         FT_GlyphLoader_Rewind( builder->loader );
87
88       FT_GlyphLoader_Prepare( builder->loader );
89     }
90   }
91
92
93   /*************************************************************************/
94   /*                                                                       */
95   /* <Function>                                                            */
96   /*    T1_Init_Builder                                                    */
97   /*                                                                       */
98   /* <Description>                                                         */
99   /*    Initializes a given glyph builder.                                 */
100   /*                                                                       */
101   /* <InOut>                                                               */
102   /*    builder :: A pointer to the glyph builder to initialize.           */
103   /*                                                                       */
104   /* <Input>                                                               */
105   /*    face    :: The current face object.                                */
106   /*                                                                       */
107   /*    size    :: The current size object.                                */
108   /*                                                                       */
109   /*    glyph   :: The current glyph object.                               */
110   /*                                                                       */
111   /*    funcs   :: Glyph builder functions (or `methods').                 */
112   /*                                                                       */
113   LOCAL_FUNC
114   void  T1_Init_Builder( T1_Builder*              builder,
115                          T1_Face                  face,
116                          T1_Size                  size,
117                          T1_GlyphSlot             glyph,
118                          const T1_Builder_Funcs*  funcs )
119   {
120     builder->funcs       = *funcs;
121     builder->path_begun  = 0;
122     builder->load_points = 1;
123
124     builder->face   = face;
125     builder->size   = size;
126     builder->glyph  = glyph;
127     builder->memory = face->root.memory;
128
129     if ( glyph )
130     {
131       FT_GlyphLoader*  loader = FT_SLOT( glyph )->loader;
132
133
134       builder->loader  = loader;
135       builder->base    = &loader->base.outline;
136       builder->current = &loader->current.outline;
137     }
138
139     if ( size )
140     {
141       builder->scale_x = size->root.metrics.x_scale;
142       builder->scale_y = size->root.metrics.y_scale;
143     }
144
145     T1_Reset_Builder( builder, 1 );
146   }
147
148
149   /*************************************************************************/
150   /*                                                                       */
151   /* <Function>                                                            */
152   /*    T1_Done_Builder                                                    */
153   /*                                                                       */
154   /* <Description>                                                         */
155   /*    Finalizes a given glyph builder.  Its contents can still be used   */
156   /*    after the call, but the function saves important information       */
157   /*    within the corresponding glyph slot.                               */
158   /*                                                                       */
159   /* <Input>                                                               */
160   /*    builder :: A pointer to the glyph builder to finalize.             */
161   /*                                                                       */
162   LOCAL_FUNC
163   void  T1_Done_Builder( T1_Builder*  builder )
164   {
165     T1_GlyphSlot  glyph = builder->glyph;
166
167
168     if ( glyph )
169       glyph->root.outline = *builder->base;
170   }
171
172
173   /*************************************************************************/
174   /*                                                                       */
175   /* <Function>                                                            */
176   /*    T1_Init_Decoder                                                    */
177   /*                                                                       */
178   /* <Description>                                                         */
179   /*    Initializes a given glyph decoder.                                 */
180   /*                                                                       */
181   /* <InOut>                                                               */
182   /*    decoder :: A pointer to the glyph builder to initialize.           */
183   /*                                                                       */
184   /* <Input>                                                               */
185   /*    funcs   :: The hinting functions interface.                        */
186   /*                                                                       */
187   LOCAL_FUNC
188   void  T1_Init_Decoder( T1_Decoder*             decoder,
189                          const T1_Hinter_Funcs*  funcs )
190   {
191     decoder->hinter = *funcs;    /* copy hinter interface */
192     decoder->top    = 0;
193     decoder->zone   = 0;
194
195     decoder->flex_state       = 0;
196     decoder->num_flex_vectors = 0;
197
198     /* Clear loader */
199     MEM_Set( &decoder->builder, 0, sizeof ( decoder->builder ) );
200   }
201
202
203   /*************************************************************************/
204   /*                                                                       */
205   /* <Function>                                                            */
206   /*    lookup_glyph_by_stdcharcode                                        */
207   /*                                                                       */
208   /* <Description>                                                         */
209   /*    Looks up a given glyph by its StandardEncoding charcode.  Used     */
210   /*    to implement the SEAC Type 1 operator.                             */
211   /*                                                                       */
212   /* <Input>                                                               */
213   /*    face     :: The current face object.                               */
214   /*                                                                       */
215   /*    charcode :: The character code to look for.                        */
216   /*                                                                       */
217   /* <Return>                                                              */
218   /*    A glyph index in the font face.  Returns -1 if the corresponding   */
219   /*    glyph wasn't found.                                                */
220   /*                                                                       */
221   static
222   FT_Int  lookup_glyph_by_stdcharcode( T1_Face  face,
223                                        FT_Int   charcode )
224   {
225     FT_Int              n;
226     const FT_String*    glyph_name;
227     PSNames_Interface*  psnames = (PSNames_Interface*)face->psnames;
228
229
230     /* check range of standard char code */
231     if ( charcode < 0 || charcode > 255 )
232       return -1;
233
234     glyph_name = psnames->adobe_std_strings(
235                    psnames->adobe_std_encoding[charcode] );
236
237     for ( n = 0; n < face->type1.num_glyphs; n++ )
238     {
239       FT_String*  name = (FT_String*)face->type1.glyph_names[n];
240
241
242       if ( name && strcmp( name, glyph_name ) == 0 )
243         return n;
244     }
245
246     return -1;
247   }
248
249
250   /*************************************************************************/
251   /*                                                                       */
252   /* <Function>                                                            */
253   /*    t1operator_seac                                                    */
254   /*                                                                       */
255   /* <Description>                                                         */
256   /*    Implements the `seac' Type 1 operator for a Type 1 decoder.        */
257   /*                                                                       */
258   /* <Input>                                                               */
259   /*    decoder :: The current CID decoder.                                */
260   /*                                                                       */
261   /*    asb     :: The accent's side bearing.                              */
262   /*                                                                       */
263   /*    adx     :: The horizontal offset of the accent.                    */
264   /*                                                                       */
265   /*    ady     :: The vertical offset of the accent.                      */
266   /*                                                                       */
267   /*    bchar   :: The base character's StandardEncoding charcode.         */
268   /*                                                                       */
269   /*    achar   :: The accent character's StandardEncoding charcode.       */
270   /*                                                                       */
271   /* <Return>                                                              */
272   /*    FreeType error code.  0 means success.                             */
273   /*                                                                       */
274   static
275   FT_Error  t1operator_seac( T1_Decoder*  decoder,
276                              FT_Pos       asb,
277                              FT_Pos       adx,
278                              FT_Pos       ady,
279                              FT_Int       bchar,
280                              FT_Int       achar )
281   {
282     FT_Error     error;
283     FT_Int       bchar_index, achar_index, n_base_points;
284     FT_Outline*  base = decoder->builder.base;
285     FT_Vector    left_bearing, advance;
286     T1_Face      face  = decoder->builder.face;
287     T1_Font*     type1 = &face->type1;
288
289
290     bchar_index = lookup_glyph_by_stdcharcode( face, bchar );
291     achar_index = lookup_glyph_by_stdcharcode( face, achar );
292
293     if ( bchar_index < 0 || achar_index < 0 )
294     {
295       FT_ERROR(( "t1operator_seac:" ));
296       FT_ERROR(( " invalid seac character code arguments\n" ));
297       return T1_Err_Syntax_Error;
298     }
299
300     /* if we are trying to load a composite glyph, do not load the */
301     /* accent character and return the array of subglyphs.         */
302     if ( decoder->builder.no_recurse )
303     {
304       FT_GlyphSlot     glyph = (FT_GlyphSlot)decoder->builder.glyph;
305       FT_GlyphLoader*  loader = glyph->loader;
306       FT_SubGlyph*     subg;
307
308
309       /* reallocate subglyph array if necessary */
310       error = FT_GlyphLoader_Check_Subglyphs( loader, 2 );
311       if ( error )
312         goto Exit;
313
314       subg = loader->current.subglyphs;
315
316       /* subglyph 0 = base character */
317       subg->index = bchar_index;
318       subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
319                     FT_SUBGLYPH_FLAG_USE_MY_METRICS;
320       subg->arg1  = 0;
321       subg->arg2  = 0;
322       subg++;
323
324       /* subglyph 1 = accent character */
325       subg->index = achar_index;
326       subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
327       subg->arg1  = adx - asb;
328       subg->arg2  = ady;
329
330       /* set up remaining glyph fields */
331       glyph->num_subglyphs = 2;
332       glyph->subglyphs     = loader->current.subglyphs;
333       glyph->format        = ft_glyph_format_composite;
334
335       loader->current.num_subglyphs = 2;
336       goto Exit;
337     }
338
339     /* First load `bchar' in builder */
340     /* now load the unscaled outline */
341
342     if ( decoder->builder.loader )
343       FT_GlyphLoader_Prepare( decoder->builder.loader );  /* prepare loader */
344
345     error = T1_Parse_CharStrings( decoder,
346                                   type1->charstrings    [bchar_index],
347                                   type1->charstrings_len[bchar_index],
348                                   type1->num_subrs,
349                                   type1->subrs,
350                                   type1->subrs_len );
351     if ( error )
352       goto Exit;
353
354     n_base_points = base->n_points;
355
356     /* save the left bearing and width of the base character */
357     /* as they will be erased by the next load.              */
358
359     left_bearing = decoder->builder.left_bearing;
360     advance      = decoder->builder.advance;
361
362     decoder->builder.left_bearing.x = 0;
363     decoder->builder.left_bearing.y = 0;
364
365     /* Now load `achar' on top of the base outline */
366     error = T1_Parse_CharStrings( decoder,
367                                   type1->charstrings    [achar_index],
368                                   type1->charstrings_len[achar_index],
369                                   type1->num_subrs,
370                                   type1->subrs,
371                                   type1->subrs_len );
372     if ( error )
373       return error;
374
375     /* restore the left side bearing and */
376     /* advance width of the base character */
377
378     decoder->builder.left_bearing = left_bearing;
379     decoder->builder.advance      = advance;
380
381     /* Finally, move the accent */
382     if ( decoder->builder.load_points )
383     {
384       FT_Outline  dummy;
385
386
387       dummy.n_points = base->n_points - n_base_points;
388       dummy.points   = base->points   + n_base_points;
389
390       FT_Outline_Translate( &dummy, adx - asb, ady );
391     }
392
393   Exit:
394     return error;
395   }
396
397
398   /*************************************************************************/
399   /*                                                                       */
400   /* <Function>                                                            */
401   /*    t1operator_flex                                                    */
402   /*                                                                       */
403   /* <Description>                                                         */
404   /*    Implements the `flex' Type 1 operator for a Type 1 decoder.        */
405   /*                                                                       */
406   /* <Input>                                                               */
407   /*    decoder   :: The current Type 1 decoder.                           */
408   /*    threshold :: The threshold.                                        */
409   /*    end_x     :: The horizontal position of the final flex point.      */
410   /*    end_y     :: The vertical position of the final flex point.        */
411   /*                                                                       */
412   /* <Return>                                                              */
413   /*    FreeType error code.  0 means success.                             */
414   /*                                                                       */
415   static
416   FT_Error  t1operator_flex( T1_Decoder*  decoder,
417                              FT_Pos       threshold,
418                              FT_Pos       end_x,
419                              FT_Pos       end_y )
420   {
421     FT_Vector    vec;
422     FT_Vector*   flex  = decoder->flex_vectors;
423     FT_Int       n;
424
425     FT_UNUSED( threshold );
426     FT_UNUSED( end_x );
427     FT_UNUSED( end_y );
428
429
430     /* we don't even try to test the threshold in the non-hinting   */
431     /* builder, even if the flex operator is said to be a path      */
432     /* construction statement in the specification.  This is better */
433     /* left to the hinter.                                          */
434
435     flex = decoder->flex_vectors;
436     vec  = *flex++;
437
438     for ( n = 0; n < 6; n++ )
439     {
440       flex->x += vec.x;
441       flex->y += vec.y;
442
443       vec = *flex++;
444     }
445
446     flex  = decoder->flex_vectors;
447
448     return  decoder->builder.funcs.rcurve_to( &decoder->builder,
449                                               flex[0].x, flex[0].y,
450                                               flex[1].x, flex[1].y,
451                                               flex[2].x, flex[2].y ) ||
452
453             decoder->builder.funcs.rcurve_to( &decoder->builder,
454                                               flex[3].x, flex[3].y,
455                                               flex[4].x, flex[4].y,
456                                               flex[5].x, flex[5].y );
457   }
458
459
460   /*************************************************************************/
461   /*                                                                       */
462   /* <Function>                                                            */
463   /*    T1_Parse_CharStrings                                               */
464   /*                                                                       */
465   /* <Description>                                                         */
466   /*    Parses a given Type 1 charstrings program.                         */
467   /*                                                                       */
468   /* <Input>                                                               */
469   /*    decoder         :: The current Type 1 decoder.                     */
470   /*                                                                       */
471   /*    charstring_base :: The base address of the charstring stream.      */
472   /*                                                                       */
473   /*    charstring_len  :: The length in bytes of the charstring stream.   */
474   /*                                                                       */
475   /*    num_subrs       :: The number of sub-routines.                     */
476   /*                                                                       */
477   /*    subrs_base      :: An array of sub-routines addresses.             */
478   /*                                                                       */
479   /*    subrs_len       :: An array of sub-routines lengths.               */
480   /*                                                                       */
481   /* <Return>                                                              */
482   /*    Free error code.  0 means success.                                 */
483   /*                                                                       */
484   LOCAL_FUNC
485   FT_Error  T1_Parse_CharStrings( T1_Decoder*  decoder,
486                                   FT_Byte*     charstring_base,
487                                   FT_Int       charstring_len,
488                                   FT_Int       num_subrs,
489                                   FT_Byte**    subrs_base,
490                                   FT_Int*      subrs_len )
491   {
492     FT_Error           error;
493     T1_Decoder_Zone*   zone;
494     FT_Byte*           ip;
495     FT_Byte*           limit;
496     T1_Builder*        builder = &decoder->builder;
497     T1_Builder_Funcs*  builds  = &builder->funcs;
498     T1_Hinter_Funcs*   hints   = &decoder->hinter;
499
500     static
501     const FT_Int  args_count[op_max] =
502     {
503       0, /* none */
504       0, /* endchar */
505       2, /* hsbw */
506       5, /* seac */
507       4, /* sbw */
508       0, /* closepath */
509       1, /* hlineto */
510       1, /* hmoveto */
511       4, /* hvcurveto */
512       2, /* rlineto */
513       2, /* rmoveto */
514       6, /* rrcurveto */
515       4, /* vhcurveto */
516       1, /* vlineto */
517       1, /* vmoveto */
518       0, /* dotsection */
519       2, /* hstem */
520       6, /* hstem3 */
521       2, /* vstem */
522       6, /* vstem3 */
523       2, /* div */
524      -1, /* callothersubr */
525       1, /* callsubr */
526       0, /* pop */
527       0, /* return */
528       2  /* setcurrentpoint */
529     };
530
531
532     /* First of all, initialize the decoder */
533     decoder->top  = decoder->stack;
534     decoder->zone = decoder->zones;
535     zone          = decoder->zones;
536
537     builder->path_begun  = 0;
538
539     zone->base           = charstring_base;
540     limit = zone->limit  = charstring_base + charstring_len;
541     ip    = zone->cursor = zone->base;
542
543     error = T1_Err_Ok;
544
545     /* now, execute loop */
546     while ( ip < limit )
547     {
548       FT_Int*      top   = decoder->top;
549       T1_Operator  op    = op_none;
550       FT_Long      value = 0;
551
552
553       /* Start with the decompression of operator or value */
554       switch ( *ip++ )
555       {
556       case 1:
557         op = op_hstem;
558         break;
559
560       case 3:
561         op = op_vstem;
562         break;
563       case 4:
564         op = op_vmoveto;
565         break;
566       case 5:
567         op = op_rlineto;
568         break;
569       case 6:
570         op = op_hlineto;
571         break;
572       case 7:
573         op = op_vlineto;
574         break;
575       case 8:
576         op = op_rrcurveto;
577         break;
578       case 9:
579         op = op_closepath;
580         break;
581       case 10:
582         op = op_callsubr;
583         break;
584       case 11:
585         op = op_return;
586         break;
587
588       case 13:
589         op = op_hsbw;
590         break;
591       case 14:
592         op = op_endchar;
593         break;
594
595       case 21:
596         op = op_rmoveto;
597         break;
598       case 22:
599         op = op_hmoveto;
600         break;
601
602       case 30:
603         op = op_vhcurveto;
604         break;
605       case 31:
606         op = op_hvcurveto;
607         break;
608
609       case 12:
610         if ( ip > limit )
611         {
612           FT_ERROR(( "T1_Parse_CharStrings: invalid escape (12+EOF)\n" ));
613           goto Syntax_Error;
614         }
615
616         switch ( *ip++ )
617         {
618         case 0:
619           op = op_dotsection;
620           break;
621         case 1:
622           op = op_vstem3;
623           break;
624         case 2:
625           op = op_hstem3;
626           break;
627         case 6:
628           op = op_seac;
629           break;
630         case 7:
631           op = op_sbw;
632           break;
633         case 12:
634           op = op_div;
635           break;
636         case 16:
637           op = op_callothersubr;
638           break;
639         case 17:
640           op = op_pop;
641           break;
642         case 33:
643           op = op_setcurrentpoint;
644           break;
645
646         default:
647           FT_ERROR(( "T1_Parse_CharStrings: invalid escape (12+%d)\n",
648                      ip[-1] ));
649           goto Syntax_Error;
650         }
651         break;
652
653       case 255:    /* four bytes integer */
654         if ( ip + 4 > limit )
655         {
656           FT_ERROR(( "T1_Parse_CharStrings: unexpected EOF in integer\n" ));
657           goto Syntax_Error;
658         }
659
660         value = ( (FT_Long)ip[0] << 24 ) |
661                 ( (FT_Long)ip[1] << 16 ) |
662                 ( (FT_Long)ip[2] << 8  ) |
663                            ip[3];
664         ip += 4;
665         break;
666
667       default:
668         if ( ip[-1] >= 32 )
669         {
670           if ( ip[-1] < 247 )
671             value = (FT_Long)ip[-1] - 139;
672           else
673           {
674             if ( ++ip > limit )
675             {
676               FT_ERROR(( "T1_Parse_CharStrings:" ));
677               FT_ERROR(( " unexpected EOF in integer\n" ));
678               goto Syntax_Error;
679             }
680
681             if ( ip[-2] < 251 )
682               value = ((FT_Long)( ip[-2] - 247 ) << 8 ) + ip[-1] + 108;
683             else
684               value = -( ( ( (FT_Long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );
685           }
686         }
687         else
688         {
689           FT_ERROR(( "T1_Parse_CharStrings: invalid byte (%d)\n",
690                      ip[-1] ));
691           goto Syntax_Error;
692         }
693       }
694
695       /* push value if necessary */
696       if ( op == op_none )
697       {
698         if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
699         {
700           FT_ERROR(( "T1_Parse_CharStrings: stack overflow!\n" ));
701           goto Syntax_Error;
702         }
703
704         *top++       = value;
705         decoder->top = top;
706       }
707
708       else if ( op == op_callothersubr ) /* check arguments differently */
709       {
710         if ( top - decoder->stack < 2 )
711           goto Stack_Underflow;
712
713         top -= 2;
714
715         switch ( top[1] )
716         {
717         case 1:   /* start flex feature */
718           if ( top[0] != 0 )
719             goto Unexpected_OtherSubr;
720
721           decoder->flex_state        = 1;
722           decoder->num_flex_vectors  = 0;
723           decoder->flex_vectors[0].x = 0;
724           decoder->flex_vectors[0].y = 0;
725           break;
726
727         case 2:   /* add flex vector */
728           {
729             FT_Int      index;
730             FT_Vector*  flex;
731
732
733             if ( top[0] != 0 )
734               goto Unexpected_OtherSubr;
735
736             top -= 2;
737             if ( top < decoder->stack )
738               goto Stack_Underflow;
739
740             index = decoder->num_flex_vectors++;
741             if ( index >= 7 )
742             {
743               FT_ERROR(( "T1_Parse_CharStrings: too many flex vectors!\n" ));
744               goto Syntax_Error;
745             }
746
747             flex = decoder->flex_vectors + index;
748             flex->x += top[0];
749             flex->y += top[1];
750           }
751           break;
752
753         case 0:   /* end flex feature */
754           if ( decoder->flex_state       == 0 ||
755                decoder->num_flex_vectors != 7 )
756           {
757             FT_ERROR(( "T1_Parse_CharStrings: unexpected flex end\n" ));
758             goto Syntax_Error;
759           }
760
761           if ( top[0] != 3 )
762             goto Unexpected_OtherSubr;
763
764           top -= 3;
765           if ( top < decoder->stack )
766             goto Stack_Underflow;
767
768           /* now consume the remaining `pop pop setcurrentpoint' */
769           if ( ip + 6 > limit              ||
770                ip[0] != 12  || ip[1] != 17 ||   /* pop */
771                ip[2] != 12  || ip[3] != 17 ||   /* pop */
772                ip[4] != 12  || ip[5] != 33 )    /* setcurrentpoint */
773           {
774             FT_ERROR(( "T1_Parse_CharStrings: invalid flex charstring\n" ));
775             goto Syntax_Error;
776           }
777
778           decoder->flex_state = 0;
779           decoder->top        = top;
780
781           error = t1operator_flex( decoder, top[0], top[1], top[2] );
782           break;
783
784         case 3:  /* change hints */
785           if ( top[0] != 1 )
786             goto Unexpected_OtherSubr;
787
788           /* eat the following `pop' */
789           if ( ip + 2 > limit )
790           {
791             FT_ERROR(( "T1_Parse_CharStrings: invalid escape (12+%d)\n",
792                        ip[-1] ));
793             goto Syntax_Error;
794           }
795
796           if ( ip[0] != 12 || ip[1] != 17 )
797           {
798             FT_ERROR(( "T1_Parse_CharStrings:" ));
799             FT_ERROR(( " `pop' expected, found (%d %d)\n", ip[0], ip[1] ));
800             goto Syntax_Error;
801           }
802
803           ip += 2;
804
805           error  = hints->change_hints( builder );
806           break;
807
808         default:
809           /* invalid OtherSubrs call */
810         Unexpected_OtherSubr:
811           FT_ERROR(( "T1_Parse_CharStrings: unexpected OtherSubrs [%d %d]\n",
812                      top[0], top[1] ));
813           goto Syntax_Error;
814         }
815         decoder->top = top;
816       }
817       else
818       {
819         FT_Int  num_args = args_count[op];
820
821
822         if ( top - decoder->stack < num_args )
823           goto Stack_Underflow;
824
825         top -= num_args;
826
827         switch ( op )
828         {
829         case op_endchar:
830           error = builds->end_char( builder );
831           break;
832
833         case op_hsbw:
834           error = builds->set_bearing_point( builder, top[0], 0,
835                                                       top[1], 0 );
836           break;
837
838         case op_seac:
839           /* return immediately after the processing */
840           return t1operator_seac( decoder, top[0], top[1],
841                                            top[2], top[3], top[4] );
842
843         case op_sbw:
844           error = builds->set_bearing_point( builder, top[0], top[1],
845                                                       top[2], top[3] );
846           break;
847
848         case op_closepath:
849           error = builds->close_path( builder );
850           break;
851
852         case op_hlineto:
853           error = builds->rline_to( builder, top[0], 0 );
854           break;
855
856         case op_hmoveto:
857           error = builds->rmove_to( builder, top[0], 0 );
858           break;
859
860         case op_hvcurveto:
861           error = builds->rcurve_to( builder, top[0], 0,
862                                               top[1], top[2],
863                                               0,      top[3] );
864           break;
865
866         case op_rlineto:
867           error = builds->rline_to( builder, top[0], top[1] );
868           break;
869
870         case op_rmoveto:
871           /* ignore operator when in flex mode */
872           if ( decoder->flex_state == 0 )
873             error = builds->rmove_to( builder, top[0], top[1] );
874           else
875             top += 2;
876           break;
877
878         case op_rrcurveto:
879           error = builds->rcurve_to( builder, top[0], top[1],
880                                               top[2], top[3],
881                                               top[4], top[5] );
882           break;
883
884         case op_vhcurveto:
885           error = builds->rcurve_to( builder,      0, top[0],
886                                               top[1], top[2],
887                                               top[3],      0 );
888           break;
889
890         case op_vlineto:
891           error = builds->rline_to( builder, 0, top[0] );
892           break;
893
894         case op_vmoveto:
895           error = builds->rmove_to( builder, 0, top[0] );
896           break;
897
898         case op_dotsection:
899           error = hints->dot_section( builder );
900           break;
901
902         case op_hstem:
903           error = hints->stem( builder, top[0], top[1], 0 );
904           break;
905
906         case op_hstem3:
907           error = hints->stem3( builder, top[0], top[1], top[2],
908                                          top[3], top[4], top[5], 0 );
909           break;
910
911         case op_vstem:
912           error = hints->stem( builder, top[0], top[1], 1 );
913           break;
914
915         case op_vstem3:
916           error = hints->stem3( builder, top[0], top[1], top[2],
917                                          top[3], top[4], top[5], 1 );
918           break;
919
920         case op_div:
921           if ( top[1] )
922           {
923             *top = top[0] / top[1];
924             ++top;
925           }
926           else
927           {
928             FT_ERROR(( "T1_Parse_CHarStrings: division by 0\n" ));
929             goto Syntax_Error;
930           }
931           break;
932
933         case op_callsubr:
934           {
935             FT_Int  index = top[0];
936
937
938             if ( index < 0 || index >= num_subrs )
939             {
940               FT_ERROR(( "T1_Parse_CharStrings: invalid subrs index\n" ));
941               goto Syntax_Error;
942             }
943
944             if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
945             {
946               FT_ERROR(( "T1_Parse_CharStrings: too many nested subrs\n" ));
947               goto Syntax_Error;
948             }
949
950             zone->cursor = ip;  /* save current instruction pointer */
951
952             zone++;
953             zone->base   = subrs_base[index];
954             zone->limit  = zone->base + subrs_len[index];
955             zone->cursor = zone->base;
956
957             if ( !zone->base )
958             {
959               FT_ERROR(( "T1_Parse_CharStrings: invoking empty subrs!\n" ));
960               goto Syntax_Error;
961             }
962
963             decoder->zone = zone;
964             ip            = zone->base;
965             limit         = zone->limit;
966           }
967           break;
968
969         case op_pop:
970           FT_ERROR(( "T1_Parse_CharStrings: unexpected POP\n" ));
971           goto Syntax_Error;
972
973         case op_return:
974           if ( zone <= decoder->zones )
975           {
976             FT_ERROR(( "T1_Parse_CharStrings: unexpected return\n" ));
977             goto Syntax_Error;
978           }
979
980           zone--;
981           ip            = zone->cursor;
982           limit         = zone->limit;
983           decoder->zone = zone;
984           break;
985
986         case op_setcurrentpoint:
987           FT_ERROR(( "T1_Parse_CharStrings:" ));
988           FT_ERROR(( " unexpected `setcurrentpoint'\n" ));
989           goto Syntax_Error;
990           break;
991
992         default:
993           FT_ERROR(( "T1_Parse_CharStrings: unhandled opcode %d\n", op ));
994           goto Syntax_Error;
995         }
996
997         decoder->top = top;
998       }
999     }
1000
1001     return error;
1002
1003   Syntax_Error:
1004     return T1_Err_Syntax_Error;
1005
1006   Stack_Underflow:
1007     return T1_Err_Stack_Underflow;
1008   }
1009
1010
1011   /*************************************************************************/
1012   /*                                                                       */
1013   /* <Function>                                                            */
1014   /*    T1_Add_Points                                                      */
1015   /*                                                                       */
1016   /* <Description>                                                         */
1017   /*    Checks that there is enough room in the current load glyph outline */
1018   /*    to accept `num_points' additional outline points.  If not, this    */
1019   /*    function grows the load outline's arrays accordingly.              */
1020   /*                                                                       */
1021   /* <Input>                                                               */
1022   /*    builder    :: A pointer to the glyph builder object.               */
1023   /*                                                                       */
1024   /*    num_points :: The number of points that will be added later.       */
1025   /*                                                                       */
1026   /* <Return>                                                              */
1027   /*    FreeType error code.  0 means success.                             */
1028   /*                                                                       */
1029   /* <Note>                                                                */
1030   /*    This function does NOT update the points count in the glyph        */
1031   /*    builder.  This must be done by the caller itself, after this       */
1032   /*    function has been invoked.                                         */
1033   /*                                                                       */
1034   LOCAL_FUNC
1035   FT_Error  T1_Add_Points( T1_Builder*  builder,
1036                            FT_Int       num_points )
1037   {
1038     return FT_GlyphLoader_Check_Points( builder->loader, num_points, 0 );
1039   }
1040
1041
1042   /*************************************************************************/
1043   /*                                                                       */
1044   /* <Function>                                                            */
1045   /*    T1_Add_Contours                                                    */
1046   /*                                                                       */
1047   /* <Description>                                                         */
1048   /*    Checks that there is enough room in the current load glyph outline */
1049   /*    to accept `num_contours' additional contours.  If not, this        */
1050   /*    function grows the load outline's arrays accordingly.              */
1051   /*                                                                       */
1052   /* <Input>                                                               */
1053   /*    builder      :: A pointer to the glyph builder object.             */
1054   /*                                                                       */
1055   /*    num_contours :: The number of contours that will be added later.   */
1056   /*                                                                       */
1057   /* <Return>                                                              */
1058   /*    FreeType error code.  0 means success.                             */
1059   /*                                                                       */
1060   /* <Note>                                                                */
1061   /*    This function does NOT update the contours count in the load glyph */
1062   /*    This must be done by the caller itself, after this function is     */
1063   /*    invoked.                                                           */
1064   /*                                                                       */
1065   LOCAL_FUNC
1066   FT_Error  T1_Add_Contours( T1_Builder*  builder,
1067                              FT_Int       num_contours )
1068   {
1069     return FT_GlyphLoader_Check_Points( builder->loader, 0, num_contours );
1070   }
1071
1072
1073   /*************************************************************************/
1074   /*************************************************************************/
1075   /*************************************************************************/
1076   /**********                                                      *********/
1077   /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/
1078   /**********                                                      *********/
1079   /**********    The following code is in charge of computing      *********/
1080   /**********    the maximum advance width of the font.  It        *********/
1081   /**********    quickly processes each glyph charstring to        *********/
1082   /**********    extract the value from either a `sbw' or `seac'   *********/
1083   /**********    operator.                                         *********/
1084   /**********                                                      *********/
1085   /*************************************************************************/
1086   /*************************************************************************/
1087   /*************************************************************************/
1088
1089
1090   static
1091   FT_Error  maxadv_sbw( T1_Decoder*  decoder,
1092                         FT_Pos       sbx,
1093                         FT_Pos       sby,
1094                         FT_Pos       wx,
1095                         FT_Pos       wy )
1096   {
1097     FT_UNUSED( sbx );
1098     FT_UNUSED( sby );
1099     FT_UNUSED( wy );
1100
1101     if ( wx > decoder->builder.advance.x )
1102       decoder->builder.advance.x = wx;
1103
1104     return -1;    /* return an error code to exit the Type 1 parser */
1105                   /* immediately.                                   */
1106   }
1107
1108
1109   static
1110   FT_Int  maxadv_error( void )
1111   {
1112     /* we should never reach this code, unless with a buggy font */
1113     return -2;
1114   }
1115
1116
1117   /* the maxadv_gbuilder_interface is used when computing the maximum  */
1118   /* advance width of all glyphs in a given font.  We only process the */
1119   /* `sbw' operator here, and return an error for all others.          */
1120
1121   /* Note that `seac' is processed by the T1_Decoder.                  */
1122   static
1123   const T1_Builder_Funcs  maxadv_builder_interface =
1124   {
1125     (T1_Builder_EndChar)  maxadv_error,
1126     (T1_Builder_Sbw)      maxadv_sbw,
1127     (T1_Builder_ClosePath)maxadv_error,
1128     (T1_Builder_RLineTo)  maxadv_error,
1129     (T1_Builder_RMoveTo)  maxadv_error,
1130     (T1_Builder_RCurveTo) maxadv_error
1131   };
1132
1133
1134   /* the maxadv_hinter_interface always return an error. */
1135   static
1136   const T1_Hinter_Funcs  maxadv_hinter_interface =
1137   {
1138     (T1_Hinter_DotSection) maxadv_error,
1139     (T1_Hinter_ChangeHints)maxadv_error,
1140     (T1_Hinter_Stem)       maxadv_error,
1141     (T1_Hinter_Stem3)      maxadv_error,
1142   };
1143
1144
1145   LOCAL_FUNC
1146   FT_Error  T1_Compute_Max_Advance( T1_Face  face,
1147                                     FT_Int*  max_advance )
1148   {
1149     FT_Error    error;
1150     T1_Decoder  decoder;
1151     FT_Int      glyph_index;
1152     T1_Font*    type1 = &face->type1;
1153
1154
1155     *max_advance = 0;
1156
1157     /* Initialize load decoder */
1158     T1_Init_Decoder( &decoder, &maxadv_hinter_interface );
1159
1160     T1_Init_Builder( &decoder.builder, face, 0, 0,
1161                      &maxadv_builder_interface );
1162
1163     /* For each glyph, parse the glyph charstring and extract */
1164     /* the advance width.                                     */
1165     for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
1166     {
1167       /* now get load the unscaled outline */
1168       error = T1_Parse_CharStrings( &decoder,
1169                                     type1->charstrings    [glyph_index],
1170                                     type1->charstrings_len[glyph_index],
1171                                     type1->num_subrs,
1172                                     type1->subrs,
1173                                     type1->subrs_len );
1174       /* ignore the error if one occured - skip to next glyph */
1175     }
1176
1177     *max_advance = decoder.builder.advance.x;
1178     return T1_Err_Ok;
1179   }
1180
1181
1182   /*************************************************************************/
1183   /*************************************************************************/
1184   /*************************************************************************/
1185   /**********                                                      *********/
1186   /**********               UNHINTED GLYPH LOADER                  *********/
1187   /**********                                                      *********/
1188   /**********    The following code is in charge of loading a      *********/
1189   /**********    single outline.  It completely ignores hinting    *********/
1190   /**********    and is used when FT_LOAD_NO_HINTING is set.       *********/
1191   /**********                                                      *********/
1192   /**********      The Type 1 hinter is located in `t1hint.c'      *********/
1193   /**********                                                      *********/
1194   /*************************************************************************/
1195   /*************************************************************************/
1196   /*************************************************************************/
1197
1198
1199   static
1200   FT_Error  close_open_path( T1_Builder*  builder )
1201   {
1202     FT_Error     error;
1203     FT_Outline*  cur = builder->current;
1204     FT_Int       num_points;
1205     FT_Int       first_point;
1206
1207
1208     /* Some fonts, like Hershey, are made of `open paths' which are     */
1209     /* now managed directly by FreeType.  In this case, it is necessary */
1210     /* to close the path by duplicating its points in reverse order,    */
1211     /* which is precisely the purpose of this function.                 */
1212
1213     /* first compute the number of points to duplicate */
1214     if ( cur->n_contours > 1 )
1215       first_point = cur->contours[cur->n_contours - 2] + 1;
1216     else
1217       first_point = 0;
1218
1219     num_points = cur->n_points - first_point - 2;
1220     if ( num_points > 0 )
1221     {
1222       FT_Vector*  source_point;
1223       char*       source_tags;
1224       FT_Vector*  point;
1225       char*       tags;
1226
1227
1228       error = T1_Add_Points( builder, num_points );
1229       if ( error )
1230         return error;
1231
1232       point = cur->points + cur->n_points;
1233       tags  = cur->tags   + cur->n_points;
1234
1235       source_point = point - 2;
1236       source_tags  = tags - 2;
1237
1238       cur->n_points += num_points;
1239
1240       if ( builder->load_points )
1241         do
1242         {
1243           *point++ = *source_point--;
1244           *tags++  = *source_tags--;
1245           num_points--;
1246
1247         } while ( num_points > 0 );
1248     }
1249
1250     builder->path_begun = 0;
1251     return T1_Err_Ok;
1252   }
1253
1254
1255   static
1256   FT_Error  gload_closepath( T1_Builder*  builder )
1257   {
1258     FT_Outline*  cur = builder->current;
1259
1260
1261     /* XXXX: We must not include the last point in the path if it */
1262     /*       is located on the first point.                       */
1263     if ( cur->n_points > 1 )
1264     {
1265       FT_Int      first = 0;
1266       FT_Vector*  p1    = cur->points + first;
1267       FT_Vector*  p2    = cur->points + cur->n_points - 1;
1268
1269
1270       if ( cur->n_contours > 1 )
1271       {
1272         first = cur->contours[cur->n_contours - 2] + 1;
1273         p1    = cur->points + first;
1274       }
1275
1276       if ( p1->x == p2->x && p1->y == p2->y )
1277         cur->n_points--;
1278     }
1279
1280     /* save current contour, if any */
1281     if ( cur->n_contours > 0 )
1282       cur->contours[cur->n_contours - 1] = cur->n_points - 1;
1283
1284 #ifndef T1_CONFIG_OPTION_DISABLE_HINTER
1285     /* hint last points if necessary -- this is not strictly required    */
1286     /* there, but it helps for debugging, and doesn't affect performance */
1287     if ( builder->pass == 1 )
1288       T1_Hint_Points( builder );
1289 #endif
1290
1291     builder->path_begun = 0;
1292     return T1_Err_Ok;
1293   }
1294
1295
1296   static
1297   FT_Error  gload_endchar( T1_Builder*  builder )
1298   {
1299     FT_Error  error;
1300
1301
1302     /* close path if needed */
1303     if ( builder->path_begun )
1304     {
1305       error = close_open_path( builder );
1306       if ( error )
1307         return error;
1308     }
1309
1310     error = gload_closepath( builder );
1311
1312     FT_GlyphLoader_Add( builder->loader );
1313
1314     return error;
1315   }
1316
1317
1318   static
1319   FT_Error  gload_sbw( T1_Builder*  builder,
1320                        FT_Pos       sbx,
1321                        FT_Pos       sby,
1322                        FT_Pos       wx,
1323                        FT_Pos       wy )
1324   {
1325     builder->left_bearing.x += sbx;
1326     builder->left_bearing.y += sby;
1327     builder->advance.x       = wx;
1328     builder->advance.y       = wy;
1329
1330     builder->last.x = sbx;
1331     builder->last.y = sby;
1332
1333     return 0;
1334   }
1335
1336
1337   static
1338   FT_Error  gload_rlineto( T1_Builder*  builder,
1339                            FT_Pos       dx,
1340                            FT_Pos       dy )
1341   {
1342     FT_Error     error;
1343     FT_Outline*  cur = builder->current;
1344     FT_Vector    vec;
1345
1346
1347     /* grow buffer if necessary */
1348     error = T1_Add_Points( builder, 1 );
1349     if ( error )
1350       return error;
1351
1352     if ( builder->load_points )
1353     {
1354       /* save point */
1355       vec.x = builder->last.x + dx;
1356       vec.y = builder->last.y + dy;
1357
1358       cur->points[cur->n_points] = vec;
1359       cur->tags  [cur->n_points] = FT_Curve_Tag_On;
1360
1361       builder->last = vec;
1362     }
1363     cur->n_points++;
1364
1365     builder->path_begun = 1;
1366
1367     return T1_Err_Ok;
1368   }
1369
1370
1371   static
1372   FT_Error  gload_rmoveto( T1_Builder*  builder,
1373                            FT_Pos       dx,
1374                            FT_Pos       dy )
1375   {
1376     FT_Error     error;
1377     FT_Outline*  cur = builder->current;
1378     FT_Vector    vec;
1379
1380
1381     /* in the case where `path_begun' is set, we have an `rmoveto' */
1382     /* after some normal path definition. If the face's paint type */
1383     /* is set to 1, this means that we have an `open path', also   */
1384     /* called a `stroke'.  The FreeType raster doesn't support     */
1385     /* opened paths, so we'll close it explicitely there.          */
1386
1387     if ( builder->path_begun && builder->face->type1.paint_type == 1 )
1388     {
1389       if ( builder->face->type1.paint_type == 1 )
1390       {
1391         error = close_open_path( builder );
1392         if ( error )
1393           return error;
1394       }
1395     }
1396
1397     /* grow buffer if necessary */
1398     error = T1_Add_Contours( builder, 1 ) ||
1399             T1_Add_Points  ( builder, 1 );
1400     if ( error )
1401       return error;
1402
1403     /* save current contour, if any */
1404     if ( cur->n_contours > 0 )
1405       cur->contours[cur->n_contours - 1] = cur->n_points - 1;
1406
1407     if ( builder->load_points )
1408     {
1409       /* save point */
1410       vec.x = builder->last.x + dx;
1411       vec.y = builder->last.y + dy;
1412       cur->points[cur->n_points] = vec;
1413       cur->tags  [cur->n_points] = FT_Curve_Tag_On;
1414
1415       builder->last = vec;
1416     }
1417
1418     cur->n_contours++;
1419     cur->n_points++;
1420
1421     return T1_Err_Ok;
1422   }
1423
1424
1425   static
1426   FT_Error  gload_rrcurveto( T1_Builder*  builder,
1427                              FT_Pos       dx1,
1428                              FT_Pos       dy1,
1429                              FT_Pos       dx2,
1430                              FT_Pos       dy2,
1431                              FT_Pos       dx3,
1432                              FT_Pos       dy3 )
1433   {
1434     FT_Error     error;
1435     FT_Outline*  cur = builder->current;
1436     FT_Vector    vec;
1437     FT_Vector*   points;
1438     char*        tags;
1439
1440
1441     /* grow buffer if necessary */
1442     error = T1_Add_Points( builder, 3 );
1443     if ( error )
1444       return error;
1445
1446     if ( builder->load_points )
1447     {
1448       /* save point */
1449       points = cur->points + cur->n_points;
1450       tags   = cur->tags  + cur->n_points;
1451
1452       vec.x = builder->last.x + dx1;
1453       vec.y = builder->last.y + dy1;
1454       points[0] = vec;
1455       tags[0]   = FT_Curve_Tag_Cubic;
1456
1457       vec.x += dx2;
1458       vec.y += dy2;
1459       points[1] = vec;
1460       tags[1]   = FT_Curve_Tag_Cubic;
1461
1462       vec.x += dx3;
1463       vec.y += dy3;
1464       points[2] = vec;
1465       tags[2]   = FT_Curve_Tag_On;
1466
1467       builder->last = vec;
1468     }
1469
1470     cur->n_points      += 3;
1471     builder->path_begun = 1;
1472
1473     return T1_Err_Ok;
1474   }
1475
1476
1477   static
1478   FT_Error  gload_ignore( void )
1479   {
1480     return 0;
1481   }
1482
1483
1484   static
1485   const T1_Builder_Funcs  gload_builder_interface =
1486   {
1487     gload_endchar,
1488     gload_sbw,
1489     gload_closepath,
1490     gload_rlineto,
1491     gload_rmoveto,
1492     gload_rrcurveto
1493   };
1494
1495
1496   static
1497   const T1_Builder_Funcs  gload_builder_interface_null =
1498   {
1499     (T1_Builder_EndChar)  gload_ignore,
1500     (T1_Builder_Sbw)      gload_sbw,      /* record left bearing */
1501     (T1_Builder_ClosePath)gload_ignore,
1502     (T1_Builder_RLineTo)  gload_ignore,
1503     (T1_Builder_RMoveTo)  gload_ignore,
1504     (T1_Builder_RCurveTo) gload_ignore
1505   };
1506
1507
1508   static
1509   const T1_Hinter_Funcs   gload_hinter_interface =
1510   {
1511     (T1_Hinter_DotSection) gload_ignore,   /* dotsection         */
1512     (T1_Hinter_ChangeHints)gload_ignore,   /* changehints        */
1513     (T1_Hinter_Stem)       gload_ignore,   /* hstem & vstem      */
1514     (T1_Hinter_Stem3)      gload_ignore,   /* hstem3 & vestem3   */
1515   };
1516
1517
1518 #ifndef T1_CONFIG_OPTION_DISABLE_HINTER
1519
1520
1521   /*************************************************************************/
1522   /*                                                                       */
1523   /*  Hinter overview:                                                     */
1524   /*                                                                       */
1525   /*    This is a two-pass hinter.  On the first pass, the hints are all   */
1526   /*    recorded by the hinter, and no point is loaded in the outline.     */
1527   /*                                                                       */
1528   /*    When the first pass is finished, all stems hints are grid-fitted   */
1529   /*    at once.                                                           */
1530   /*                                                                       */
1531   /*    Then, a second pass is performed to load the outline points as     */
1532   /*    well as hint/scale them correctly.                                 */
1533   /*                                                                       */
1534   /*************************************************************************/
1535
1536
1537   static
1538   FT_Error  t1_load_hinted_glyph( T1_Decoder*  decoder,
1539                                   FT_UInt      glyph_index,
1540                                   FT_Bool      recurse )
1541   {
1542     T1_Builder*      builder = &decoder->builder;
1543     T1_GlyphSlot     glyph   = builder->glyph;
1544     T1_Font*         type1   = &builder->face->type1;
1545     FT_UInt          old_points, old_contours;
1546     FT_GlyphLoader*  loader = decoder->builder.loader;
1547     FT_Error         error;
1548
1549
1550     /* Pass 1 -- try to load first glyph, simply recording points */
1551     old_points   = loader->base.outline.n_points;
1552     old_contours = loader->base.outline.n_contours;
1553
1554     FT_GlyphLoader_Prepare( decoder->builder.loader );
1555
1556     T1_Reset_Builder( builder, 0 );
1557
1558     builder->no_recurse                = recurse;
1559     builder->pass                      = 0;
1560     glyph->hints->hori_stems.num_stems = 0;
1561     glyph->hints->vert_stems.num_stems = 0;
1562
1563     error = T1_Parse_CharStrings( decoder,
1564                                   type1->charstrings    [glyph_index],
1565                                   type1->charstrings_len[glyph_index],
1566                                   type1->num_subrs,
1567                                   type1->subrs,
1568                                   type1->subrs_len );
1569     if ( error )
1570       goto Exit;
1571
1572     /* check for composite (i.e. `seac' operator) */
1573     if ( glyph->root.format == ft_glyph_format_composite )
1574     {
1575       /* this is a composite glyph, we must then load the first one, */
1576       /* then load the second one on top of it and translate it by a */
1577       /* fixed amount.                                               */
1578       FT_UInt       n_base_points;
1579       FT_SubGlyph*  subglyph = loader->base.subglyphs;
1580       T1_Size       size = builder->size;
1581       FT_Pos        dx, dy;
1582       FT_Vector     left_bearing, advance;
1583
1584
1585       /* clean glyph format */
1586       glyph->root.format = ft_glyph_format_none;
1587
1588       /* First load `bchar' in builder */
1589       builder->no_recurse = 0;
1590       error = t1_load_hinted_glyph( decoder, subglyph->index, 0 );
1591       if ( error )
1592         goto Exit;
1593
1594       /* save the left bearing and width of the base character */
1595       /* as they will be erased by the next load               */
1596       left_bearing = builder->left_bearing;
1597       advance      = builder->advance;
1598
1599       /* Then load `achar' in builder */
1600       n_base_points = builder->base->n_points;
1601       subglyph++;
1602       error = t1_load_hinted_glyph( decoder, subglyph->index, 0 );
1603       if ( error )
1604         goto Exit;
1605
1606       /* Finally, move the accent */
1607       dx = FT_MulFix( subglyph->arg1, size->root.metrics.x_scale );
1608       dy = FT_MulFix( subglyph->arg2, size->root.metrics.y_scale );
1609       dx = ( dx + 32 ) & -64;
1610       dy = ( dy + 32 ) & -64;
1611       {
1612         FT_Outline  dummy;
1613
1614
1615         dummy.n_points = loader->base.outline.n_points - n_base_points;
1616         dummy.points   = loader->base.outline.points   + n_base_points;
1617
1618         FT_Outline_Translate( &dummy, dx, dy );
1619       }
1620
1621       /* restore the left side bearing and   */
1622       /* advance width of the base character */
1623       builder->left_bearing = left_bearing;
1624       builder->advance      = advance;
1625     }
1626     else
1627     {
1628       /* All right, pass 1 is finished, now grid-fit all stem hints */
1629       T1_Hint_Stems( &decoder->builder );
1630
1631       /* undo the end-char */
1632       builder->base->n_points   = old_points;
1633       builder->base->n_contours = old_contours;
1634
1635       /* Pass 2 -- record and scale/hint the points */
1636       T1_Reset_Builder( builder, 0 );
1637
1638       builder->pass       = 1;
1639       builder->no_recurse = 0;
1640
1641       error = T1_Parse_CharStrings( decoder,
1642                                     type1->charstrings    [glyph_index],
1643                                     type1->charstrings_len[glyph_index],
1644                                     type1->num_subrs,
1645                                     type1->subrs,
1646                                     type1->subrs_len );
1647     }
1648
1649     /* save new glyph tables */
1650     if ( recurse )
1651       T1_Done_Builder( builder );
1652
1653   Exit:
1654     return error;
1655   }
1656
1657
1658 #endif /* !T1_CONFIG_OPTION_DISABLE_HINTER */
1659
1660
1661   LOCAL_FUNC
1662   FT_Error  T1_Load_Glyph( T1_GlyphSlot  glyph,
1663                            T1_Size       size,
1664                            FT_Int        glyph_index,
1665                            FT_Int        load_flags )
1666   {
1667     FT_Error    error;
1668     T1_Decoder  decoder;
1669     T1_Face     face = (T1_Face)glyph->root.face;
1670     FT_Bool     hinting;
1671     T1_Font*    type1 = &face->type1;
1672
1673
1674     if ( load_flags & FT_LOAD_NO_RECURSE )
1675       load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
1676
1677     glyph->x_scale = size->root.metrics.x_scale;
1678     glyph->y_scale = size->root.metrics.y_scale;
1679
1680     glyph->root.outline.n_points   = 0;
1681     glyph->root.outline.n_contours = 0;
1682
1683     glyph->root.format = ft_glyph_format_outline;  /* by default */
1684
1685     hinting = 0;
1686
1687 #ifndef T1_CONFIG_OPTION_DISABLE_HINTER
1688
1689     hinting = ( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0;
1690
1691     if ( hinting )
1692     {
1693       T1_Init_Decoder( &decoder, &t1_hinter_funcs );
1694       T1_Init_Builder( &decoder.builder, face, size, glyph,
1695                        &gload_builder_interface );
1696
1697       error = t1_load_hinted_glyph( &decoder, glyph_index, 1 );
1698     }
1699     else
1700
1701 #endif /* !T1_CONFIG_OPTION_DISABLE_HINTER */
1702
1703     {
1704       T1_Init_Decoder( &decoder, &gload_hinter_interface );
1705
1706       T1_Init_Builder( &decoder.builder, face, size, glyph,
1707                        &gload_builder_interface );
1708
1709       decoder.builder.no_recurse = ( load_flags & FT_LOAD_NO_RECURSE ) != 0;
1710
1711       /* now load the unscaled outline */
1712       error = T1_Parse_CharStrings( &decoder,
1713                                     type1->charstrings    [glyph_index],
1714                                     type1->charstrings_len[glyph_index],
1715                                     type1->num_subrs,
1716                                     type1->subrs,
1717                                     type1->subrs_len );
1718
1719       /* save new glyph tables */
1720       T1_Done_Builder( &decoder.builder );
1721     }
1722
1723     /* Now, set the metrics -- this is rather simple, as   */
1724     /* the left side bearing is the xMin, and the top side */
1725     /* bearing the yMax                                    */
1726     if ( !error )
1727     {
1728       /* for composite glyphs, return only the left side bearing and the */
1729       /* advance width                                                   */
1730       if ( glyph->root.format == ft_glyph_format_composite )
1731       {
1732         glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
1733         glyph->root.metrics.horiAdvance  = decoder.builder.advance.x;
1734       }
1735       else
1736       {
1737         FT_BBox           cbox;
1738         FT_Glyph_Metrics* metrics = &glyph->root.metrics;
1739
1740
1741         /* apply the font matrix */
1742         FT_Outline_Transform( &glyph->root.outline,
1743                               &face->type1.font_matrix );
1744
1745         FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
1746
1747         /* grid fit the bounding box if necessary */
1748         if ( hinting )
1749         {
1750           cbox.xMin &= -64;
1751           cbox.yMin &= -64;
1752           cbox.xMax  = ( cbox.xMax + 63 ) & -64;
1753           cbox.yMax  = ( cbox.yMax + 63 ) & -64;
1754         }
1755
1756         metrics->width  = cbox.xMax - cbox.xMin;
1757         metrics->height = cbox.yMax - cbox.yMin;
1758
1759         metrics->horiBearingX = cbox.xMin;
1760         metrics->horiBearingY = cbox.yMax;
1761
1762         /* copy the _unscaled_ advance width */
1763         metrics->horiAdvance = decoder.builder.advance.x;
1764
1765         /* make up vertical metrics */
1766         metrics->vertBearingX = 0;
1767         metrics->vertBearingY = 0;
1768         metrics->vertAdvance  = 0;
1769
1770         glyph->root.format = ft_glyph_format_outline;
1771
1772         glyph->root.outline.flags = 0;
1773
1774         if ( size->root.metrics.y_ppem < 24 )
1775           glyph->root.outline.flags |= ft_outline_high_precision;
1776
1777         glyph->root.outline.flags |= ft_outline_reverse_fill;
1778
1779         if ( hinting )
1780         {
1781           /* adjust the advance width               */
1782           /* XXX TODO: consider stem hints grid-fit */
1783           metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,
1784                                              glyph->x_scale );
1785         }
1786         else if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
1787         {
1788           /* scale the outline and the metrics */
1789           FT_Int       n;
1790           FT_Outline*  cur = decoder.builder.base;
1791           FT_Vector*   vec = cur->points;
1792           FT_Fixed     x_scale = glyph->x_scale;
1793           FT_Fixed     y_scale = glyph->y_scale;
1794
1795
1796           /* First of all, scale the points */
1797           for ( n = cur->n_points; n > 0; n--, vec++ )
1798           {
1799             vec->x = FT_MulFix( vec->x, x_scale );
1800             vec->y = FT_MulFix( vec->y, y_scale );
1801           }
1802
1803           /* Then scale the metrics */
1804           metrics->width  = FT_MulFix( metrics->width,  x_scale );
1805           metrics->height = FT_MulFix( metrics->height, y_scale );
1806
1807           metrics->horiBearingX = FT_MulFix( metrics->horiBearingX, x_scale );
1808           metrics->horiBearingY = FT_MulFix( metrics->horiBearingY, y_scale );
1809
1810           metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
1811           metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
1812
1813           metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,  x_scale );
1814           metrics->vertAdvance  = FT_MulFix( metrics->vertAdvance,  y_scale );
1815         }
1816       }
1817     }
1818
1819     return error;
1820   }
1821
1822
1823 /* END */