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