cffgload.c revision 049d6fea481044fcc000e7782e5bc7046fc70844
1/***************************************************************************/
2/*                                                                         */
3/*  cffgload.c                                                             */
4/*                                                                         */
5/*    OpenType Glyph Loader (body).                                        */
6/*                                                                         */
7/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by       */
8/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9/*                                                                         */
10/*  This file is part of the FreeType project, and may only be used,       */
11/*  modified, and distributed under the terms of the FreeType project      */
12/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13/*  this file you indicate that you have read the license and              */
14/*  understand and accept it fully.                                        */
15/*                                                                         */
16/***************************************************************************/
17
18
19#include <ft2build.h>
20#include FT_INTERNAL_DEBUG_H
21#include FT_INTERNAL_CALC_H
22#include FT_INTERNAL_STREAM_H
23#include FT_INTERNAL_SFNT_H
24#include FT_OUTLINE_H
25#include FT_TRUETYPE_TAGS_H
26#include FT_INTERNAL_POSTSCRIPT_HINTS_H
27
28#include "cffobjs.h"
29#include "cffload.h"
30#include "cffgload.h"
31
32#include "cfferrs.h"
33
34
35  /*************************************************************************/
36  /*                                                                       */
37  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
38  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
39  /* messages during execution.                                            */
40  /*                                                                       */
41#undef  FT_COMPONENT
42#define FT_COMPONENT  trace_cffgload
43
44
45  typedef enum  CFF_Operator_
46  {
47    cff_op_unknown = 0,
48
49    cff_op_rmoveto,
50    cff_op_hmoveto,
51    cff_op_vmoveto,
52
53    cff_op_rlineto,
54    cff_op_hlineto,
55    cff_op_vlineto,
56
57    cff_op_rrcurveto,
58    cff_op_hhcurveto,
59    cff_op_hvcurveto,
60    cff_op_rcurveline,
61    cff_op_rlinecurve,
62    cff_op_vhcurveto,
63    cff_op_vvcurveto,
64
65    cff_op_flex,
66    cff_op_hflex,
67    cff_op_hflex1,
68    cff_op_flex1,
69
70    cff_op_endchar,
71
72    cff_op_hstem,
73    cff_op_vstem,
74    cff_op_hstemhm,
75    cff_op_vstemhm,
76
77    cff_op_hintmask,
78    cff_op_cntrmask,
79    cff_op_dotsection,  /* deprecated, acts as no-op */
80
81    cff_op_abs,
82    cff_op_add,
83    cff_op_sub,
84    cff_op_div,
85    cff_op_neg,
86    cff_op_random,
87    cff_op_mul,
88    cff_op_sqrt,
89
90    cff_op_blend,
91
92    cff_op_drop,
93    cff_op_exch,
94    cff_op_index,
95    cff_op_roll,
96    cff_op_dup,
97
98    cff_op_put,
99    cff_op_get,
100    cff_op_store,
101    cff_op_load,
102
103    cff_op_and,
104    cff_op_or,
105    cff_op_not,
106    cff_op_eq,
107    cff_op_ifelse,
108
109    cff_op_callsubr,
110    cff_op_callgsubr,
111    cff_op_return,
112
113    cff_op_hsbw,        /* Type 1 opcode: invalid but seen in real life */
114    cff_op_closepath,   /* ditto */
115
116    /* do not remove */
117    cff_op_max
118
119  } CFF_Operator;
120
121
122#define CFF_COUNT_CHECK_WIDTH  0x80
123#define CFF_COUNT_EXACT        0x40
124#define CFF_COUNT_CLEAR_STACK  0x20
125
126
127  static const FT_Byte  cff_argument_counts[] =
128  {
129    0,  /* unknown */
130
131    2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */
132    1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
133    1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
134
135    0 | CFF_COUNT_CLEAR_STACK, /* rlineto */
136    0 | CFF_COUNT_CLEAR_STACK,
137    0 | CFF_COUNT_CLEAR_STACK,
138
139    0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */
140    0 | CFF_COUNT_CLEAR_STACK,
141    0 | CFF_COUNT_CLEAR_STACK,
142    0 | CFF_COUNT_CLEAR_STACK,
143    0 | CFF_COUNT_CLEAR_STACK,
144    0 | CFF_COUNT_CLEAR_STACK,
145    0 | CFF_COUNT_CLEAR_STACK,
146
147    13, /* flex */
148    7,
149    9,
150    11,
151
152    0 | CFF_COUNT_CHECK_WIDTH, /* endchar */
153
154    2 | CFF_COUNT_CHECK_WIDTH, /* hstem */
155    2 | CFF_COUNT_CHECK_WIDTH,
156    2 | CFF_COUNT_CHECK_WIDTH,
157    2 | CFF_COUNT_CHECK_WIDTH,
158
159    0 | CFF_COUNT_CHECK_WIDTH, /* hintmask */
160    0 | CFF_COUNT_CHECK_WIDTH, /* cntrmask */
161    0, /* dotsection */
162
163    1, /* abs */
164    2,
165    2,
166    2,
167    1,
168    0,
169    2,
170    1,
171
172    1, /* blend */
173
174    1, /* drop */
175    2,
176    1,
177    2,
178    1,
179
180    2, /* put */
181    1,
182    4,
183    3,
184
185    2, /* and */
186    2,
187    1,
188    2,
189    4,
190
191    1, /* callsubr */
192    1,
193    0,
194
195    2, /* hsbw */
196    0
197  };
198
199
200  /*************************************************************************/
201  /*************************************************************************/
202  /*************************************************************************/
203  /**********                                                      *********/
204  /**********                                                      *********/
205  /**********             GENERIC CHARSTRING PARSING               *********/
206  /**********                                                      *********/
207  /**********                                                      *********/
208  /*************************************************************************/
209  /*************************************************************************/
210  /*************************************************************************/
211
212
213  /*************************************************************************/
214  /*                                                                       */
215  /* <Function>                                                            */
216  /*    cff_builder_init                                                   */
217  /*                                                                       */
218  /* <Description>                                                         */
219  /*    Initializes a given glyph builder.                                 */
220  /*                                                                       */
221  /* <InOut>                                                               */
222  /*    builder :: A pointer to the glyph builder to initialize.           */
223  /*                                                                       */
224  /* <Input>                                                               */
225  /*    face    :: The current face object.                                */
226  /*                                                                       */
227  /*    size    :: The current size object.                                */
228  /*                                                                       */
229  /*    glyph   :: The current glyph object.                               */
230  /*                                                                       */
231  /*    hinting :: Whether hinting is active.                              */
232  /*                                                                       */
233  static void
234  cff_builder_init( CFF_Builder*   builder,
235                    TT_Face        face,
236                    CFF_Size       size,
237                    CFF_GlyphSlot  glyph,
238                    FT_Bool        hinting )
239  {
240    builder->path_begun  = 0;
241    builder->load_points = 1;
242
243    builder->face   = face;
244    builder->glyph  = glyph;
245    builder->memory = face->root.memory;
246
247    if ( glyph )
248    {
249      FT_GlyphLoader  loader = glyph->root.internal->loader;
250
251
252      builder->loader  = loader;
253      builder->base    = &loader->base.outline;
254      builder->current = &loader->current.outline;
255      FT_GlyphLoader_Rewind( loader );
256
257      builder->hints_globals = 0;
258      builder->hints_funcs   = 0;
259
260      if ( hinting && size )
261      {
262        CFF_Internal  internal = (CFF_Internal)size->root.internal;
263
264
265        builder->hints_globals = (void *)internal->topfont;
266        builder->hints_funcs   = glyph->root.internal->glyph_hints;
267      }
268    }
269
270    builder->pos_x = 0;
271    builder->pos_y = 0;
272
273    builder->left_bearing.x = 0;
274    builder->left_bearing.y = 0;
275    builder->advance.x      = 0;
276    builder->advance.y      = 0;
277  }
278
279
280  /*************************************************************************/
281  /*                                                                       */
282  /* <Function>                                                            */
283  /*    cff_builder_done                                                   */
284  /*                                                                       */
285  /* <Description>                                                         */
286  /*    Finalizes a given glyph builder.  Its contents can still be used   */
287  /*    after the call, but the function saves important information       */
288  /*    within the corresponding glyph slot.                               */
289  /*                                                                       */
290  /* <Input>                                                               */
291  /*    builder :: A pointer to the glyph builder to finalize.             */
292  /*                                                                       */
293  static void
294  cff_builder_done( CFF_Builder*  builder )
295  {
296    CFF_GlyphSlot  glyph = builder->glyph;
297
298
299    if ( glyph )
300      glyph->root.outline = *builder->base;
301  }
302
303
304  /*************************************************************************/
305  /*                                                                       */
306  /* <Function>                                                            */
307  /*    cff_compute_bias                                                   */
308  /*                                                                       */
309  /* <Description>                                                         */
310  /*    Computes the bias value in dependence of the number of glyph       */
311  /*    subroutines.                                                       */
312  /*                                                                       */
313  /* <Input>                                                               */
314  /*    num_subrs :: The number of glyph subroutines.                      */
315  /*                                                                       */
316  /* <Return>                                                              */
317  /*    The bias value.                                                    */
318  static FT_Int
319  cff_compute_bias( FT_UInt  num_subrs )
320  {
321    FT_Int  result;
322
323
324    if ( num_subrs < 1240 )
325      result = 107;
326    else if ( num_subrs < 33900U )
327      result = 1131;
328    else
329      result = 32768U;
330
331    return result;
332  }
333
334
335  /*************************************************************************/
336  /*                                                                       */
337  /* <Function>                                                            */
338  /*    cff_decoder_init                                                   */
339  /*                                                                       */
340  /* <Description>                                                         */
341  /*    Initializes a given glyph decoder.                                 */
342  /*                                                                       */
343  /* <InOut>                                                               */
344  /*    decoder :: A pointer to the glyph builder to initialize.           */
345  /*                                                                       */
346  /* <Input>                                                               */
347  /*    face      :: The current face object.                              */
348  /*                                                                       */
349  /*    size      :: The current size object.                              */
350  /*                                                                       */
351  /*    slot      :: The current glyph object.                             */
352  /*                                                                       */
353  /*    hinting   :: Whether hinting is active.                            */
354  /*                                                                       */
355  /*    hint_mode :: The hinting mode.                                     */
356  /*                                                                       */
357  FT_LOCAL_DEF( void )
358  cff_decoder_init( CFF_Decoder*    decoder,
359                    TT_Face         face,
360                    CFF_Size        size,
361                    CFF_GlyphSlot   slot,
362                    FT_Bool         hinting,
363                    FT_Render_Mode  hint_mode )
364  {
365    CFF_Font  cff = (CFF_Font)face->extra.data;
366
367
368    /* clear everything */
369    FT_MEM_ZERO( decoder, sizeof ( *decoder ) );
370
371    /* initialize builder */
372    cff_builder_init( &decoder->builder, face, size, slot, hinting );
373
374    /* initialize Type2 decoder */
375    decoder->num_globals  = cff->num_global_subrs;
376    decoder->globals      = cff->global_subrs;
377    decoder->globals_bias = cff_compute_bias( decoder->num_globals );
378
379    decoder->hint_mode    = hint_mode;
380  }
381
382  FT_LOCAL_DEF( void )
383  cff_decoder_set_width_only( CFF_Decoder*  decoder )
384  {
385    decoder->width_only = 1;
386  }
387
388  /* this function is used to select the subfont */
389  /* and the locals subrs array                  */
390  FT_LOCAL_DEF( FT_Error )
391  cff_decoder_prepare( CFF_Decoder*  decoder,
392                       CFF_Size      size,
393                       FT_UInt       glyph_index )
394  {
395    CFF_Builder  *builder = &decoder->builder;
396    CFF_Font      cff     = (CFF_Font)builder->face->extra.data;
397    CFF_SubFont   sub     = &cff->top_font;
398    FT_Error      error   = CFF_Err_Ok;
399
400
401    /* manage CID fonts */
402    if ( cff->num_subfonts )
403    {
404      FT_Byte  fd_index = cff_fd_select_get( &cff->fd_select, glyph_index );
405
406
407      if ( fd_index >= cff->num_subfonts )
408      {
409        FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" ));
410        error = CFF_Err_Invalid_File_Format;
411        goto Exit;
412      }
413
414      sub = cff->subfonts[fd_index];
415      if ( builder->hints_funcs )
416      {
417        CFF_Internal  internal = (CFF_Internal)size->root.internal;
418
419
420        /* for CFFs without subfonts, this value has already been set */
421        builder->hints_globals = (void *)internal->subfonts[fd_index];
422      }
423    }
424
425    decoder->num_locals    = sub->num_local_subrs;
426    decoder->locals        = sub->local_subrs;
427    decoder->locals_bias   = cff_compute_bias( decoder->num_locals );
428
429    decoder->glyph_width   = sub->private_dict.default_width;
430    decoder->nominal_width = sub->private_dict.nominal_width;
431
432  Exit:
433    return error;
434  }
435
436
437  /* check that there is enough space for `count' more points */
438  static FT_Error
439  check_points( CFF_Builder*  builder,
440                FT_Int        count )
441  {
442    return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
443  }
444
445
446  /* add a new point, do not check space */
447  static void
448  cff_builder_add_point( CFF_Builder*  builder,
449                         FT_Pos        x,
450                         FT_Pos        y,
451                         FT_Byte       flag )
452  {
453    FT_Outline*  outline = builder->current;
454
455
456    if ( builder->load_points )
457    {
458      FT_Vector*  point   = outline->points + outline->n_points;
459      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
460
461
462      point->x = x >> 16;
463      point->y = y >> 16;
464      *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
465
466      builder->last = *point;
467    }
468
469    outline->n_points++;
470  }
471
472
473  /* check space for a new on-curve point, then add it */
474  static FT_Error
475  cff_builder_add_point1( CFF_Builder*  builder,
476                          FT_Pos        x,
477                          FT_Pos        y )
478  {
479    FT_Error  error;
480
481
482    error = check_points( builder, 1 );
483    if ( !error )
484      cff_builder_add_point( builder, x, y, 1 );
485
486    return error;
487  }
488
489
490  /* check space for a new contour, then add it */
491  static FT_Error
492  cff_builder_add_contour( CFF_Builder*  builder )
493  {
494    FT_Outline*  outline = builder->current;
495    FT_Error     error;
496
497
498    if ( !builder->load_points )
499    {
500      outline->n_contours++;
501      return CFF_Err_Ok;
502    }
503
504    error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
505    if ( !error )
506    {
507      if ( outline->n_contours > 0 )
508        outline->contours[outline->n_contours - 1] =
509          (short)( outline->n_points - 1 );
510
511      outline->n_contours++;
512    }
513
514    return error;
515  }
516
517
518  /* if a path was begun, add its first on-curve point */
519  static FT_Error
520  cff_builder_start_point( CFF_Builder*  builder,
521                           FT_Pos        x,
522                           FT_Pos        y )
523  {
524    FT_Error  error = CFF_Err_Ok;
525
526
527    /* test whether we are building a new contour */
528    if ( !builder->path_begun )
529    {
530      builder->path_begun = 1;
531      error = cff_builder_add_contour( builder );
532      if ( !error )
533        error = cff_builder_add_point1( builder, x, y );
534    }
535
536    return error;
537  }
538
539
540  /* close the current contour */
541  static void
542  cff_builder_close_contour( CFF_Builder*  builder )
543  {
544    FT_Outline*  outline = builder->current;
545
546
547    if ( !outline )
548      return;
549
550    /* XXXX: We must not include the last point in the path if it */
551    /*       is located on the first point.                       */
552    if ( outline->n_points > 1 )
553    {
554      FT_Int      first   = 0;
555      FT_Vector*  p1      = outline->points + first;
556      FT_Vector*  p2      = outline->points + outline->n_points - 1;
557      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
558
559
560      if ( outline->n_contours > 1 )
561      {
562        first = outline->contours[outline->n_contours - 2] + 1;
563        p1    = outline->points + first;
564      }
565
566      /* `delete' last point only if it coincides with the first    */
567      /* point and if it is not a control point (which can happen). */
568      if ( p1->x == p2->x && p1->y == p2->y )
569        if ( *control == FT_CURVE_TAG_ON )
570          outline->n_points--;
571    }
572
573    if ( outline->n_contours > 0 )
574      outline->contours[outline->n_contours - 1] =
575        (short)( outline->n_points - 1 );
576  }
577
578
579  static FT_Int
580  cff_lookup_glyph_by_stdcharcode( CFF_Font  cff,
581                                   FT_Int    charcode )
582  {
583    FT_UInt    n;
584    FT_UShort  glyph_sid;
585
586
587    /* CID-keyed fonts don't have glyph names */
588    if ( !cff->charset.sids )
589      return -1;
590
591    /* check range of standard char code */
592    if ( charcode < 0 || charcode > 255 )
593      return -1;
594
595    /* Get code to SID mapping from `cff_standard_encoding'. */
596    glyph_sid = cff_get_standard_encoding( (FT_UInt)charcode );
597
598    for ( n = 0; n < cff->num_glyphs; n++ )
599    {
600      if ( cff->charset.sids[n] == glyph_sid )
601        return n;
602    }
603
604    return -1;
605  }
606
607
608  static FT_Error
609  cff_get_glyph_data( TT_Face    face,
610                      FT_UInt    glyph_index,
611                      FT_Byte**  pointer,
612                      FT_ULong*  length )
613  {
614#ifdef FT_CONFIG_OPTION_INCREMENTAL
615    /* For incremental fonts get the character data using the */
616    /* callback function.                                     */
617    if ( face->root.internal->incremental_interface )
618    {
619      FT_Data   data;
620      FT_Error  error =
621                  face->root.internal->incremental_interface->funcs->get_glyph_data(
622                    face->root.internal->incremental_interface->object,
623                    glyph_index, &data );
624
625
626      *pointer = (FT_Byte*)data.pointer;
627      *length = data.length;
628
629      return error;
630    }
631    else
632#endif /* FT_CONFIG_OPTION_INCREMENTAL */
633
634    {
635      CFF_Font  cff  = (CFF_Font)(face->extra.data);
636
637
638      return cff_index_access_element( &cff->charstrings_index, glyph_index,
639                                       pointer, length );
640    }
641  }
642
643
644  static void
645  cff_free_glyph_data( TT_Face    face,
646                       FT_Byte**  pointer,
647                       FT_ULong   length )
648  {
649#ifndef FT_CONFIG_OPTION_INCREMENTAL
650    FT_UNUSED( length );
651#endif
652
653#ifdef FT_CONFIG_OPTION_INCREMENTAL
654    /* For incremental fonts get the character data using the */
655    /* callback function.                                     */
656    if ( face->root.internal->incremental_interface )
657    {
658      FT_Data data;
659
660
661      data.pointer = *pointer;
662      data.length  = length;
663
664      face->root.internal->incremental_interface->funcs->free_glyph_data(
665        face->root.internal->incremental_interface->object,&data );
666    }
667    else
668#endif /* FT_CONFIG_OPTION_INCREMENTAL */
669
670    {
671      CFF_Font  cff = (CFF_Font)(face->extra.data);
672
673
674      cff_index_forget_element( &cff->charstrings_index, pointer );
675    }
676  }
677
678
679  static FT_Error
680  cff_operator_seac( CFF_Decoder*  decoder,
681                     FT_Pos        adx,
682                     FT_Pos        ady,
683                     FT_Int        bchar,
684                     FT_Int        achar )
685  {
686    FT_Error      error;
687    CFF_Builder*  builder = &decoder->builder;
688    FT_Int        bchar_index, achar_index;
689    TT_Face       face = decoder->builder.face;
690    FT_Vector     left_bearing, advance;
691    FT_Byte*      charstring;
692    FT_ULong      charstring_len;
693
694
695#ifdef FT_CONFIG_OPTION_INCREMENTAL
696    /* Incremental fonts don't necessarily have valid charsets.        */
697    /* They use the character code, not the glyph index, in this case. */
698    if ( face->root.internal->incremental_interface )
699    {
700      bchar_index = bchar;
701      achar_index = achar;
702    }
703    else
704#endif /* FT_CONFIG_OPTION_INCREMENTAL */
705    {
706      CFF_Font cff = (CFF_Font)(face->extra.data);
707
708
709      bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar );
710      achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar );
711    }
712
713    if ( bchar_index < 0 || achar_index < 0 )
714    {
715      FT_ERROR(( "cff_operator_seac:" ));
716      FT_ERROR(( " invalid seac character code arguments\n" ));
717      return CFF_Err_Syntax_Error;
718    }
719
720    /* If we are trying to load a composite glyph, do not load the */
721    /* accent character and return the array of subglyphs.         */
722    if ( builder->no_recurse )
723    {
724      FT_GlyphSlot    glyph  = (FT_GlyphSlot)builder->glyph;
725      FT_GlyphLoader  loader = glyph->internal->loader;
726      FT_SubGlyph     subg;
727
728
729      /* reallocate subglyph array if necessary */
730      error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
731      if ( error )
732        goto Exit;
733
734      subg = loader->current.subglyphs;
735
736      /* subglyph 0 = base character */
737      subg->index = bchar_index;
738      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
739                    FT_SUBGLYPH_FLAG_USE_MY_METRICS;
740      subg->arg1  = 0;
741      subg->arg2  = 0;
742      subg++;
743
744      /* subglyph 1 = accent character */
745      subg->index = achar_index;
746      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
747      subg->arg1  = (FT_Int)( adx >> 16 );
748      subg->arg2  = (FT_Int)( ady >> 16 );
749
750      /* set up remaining glyph fields */
751      glyph->num_subglyphs = 2;
752      glyph->subglyphs     = loader->base.subglyphs;
753      glyph->format        = FT_GLYPH_FORMAT_COMPOSITE;
754
755      loader->current.num_subglyphs = 2;
756    }
757
758    FT_GlyphLoader_Prepare( builder->loader );
759
760    /* First load `bchar' in builder */
761    error = cff_get_glyph_data( face, bchar_index,
762                                &charstring, &charstring_len );
763    if ( !error )
764    {
765      error = cff_decoder_parse_charstrings( decoder, charstring,
766                                             charstring_len );
767
768      if ( error )
769        goto Exit;
770
771      cff_free_glyph_data( face, &charstring, charstring_len );
772    }
773
774    /* Save the left bearing and width of the base character */
775    /* as they will be erased by the next load.              */
776
777    left_bearing = builder->left_bearing;
778    advance      = builder->advance;
779
780    builder->left_bearing.x = 0;
781    builder->left_bearing.y = 0;
782
783    builder->pos_x = adx;
784    builder->pos_y = ady;
785
786    /* Now load `achar' on top of the base outline. */
787    error = cff_get_glyph_data( face, achar_index,
788                                &charstring, &charstring_len );
789    if ( !error )
790    {
791      error = cff_decoder_parse_charstrings( decoder, charstring,
792                                             charstring_len );
793
794      if ( error )
795        goto Exit;
796
797      cff_free_glyph_data( face, &charstring, charstring_len );
798    }
799
800    /* Restore the left side bearing and advance width */
801    /* of the base character.                          */
802    builder->left_bearing = left_bearing;
803    builder->advance      = advance;
804
805    builder->pos_x = 0;
806    builder->pos_y = 0;
807
808  Exit:
809    return error;
810  }
811
812
813  /*************************************************************************/
814  /*                                                                       */
815  /* <Function>                                                            */
816  /*    cff_decoder_parse_charstrings                                      */
817  /*                                                                       */
818  /* <Description>                                                         */
819  /*    Parses a given Type 2 charstrings program.                         */
820  /*                                                                       */
821  /* <InOut>                                                               */
822  /*    decoder         :: The current Type 1 decoder.                     */
823  /*                                                                       */
824  /* <Input>                                                               */
825  /*    charstring_base :: The base of the charstring stream.              */
826  /*                                                                       */
827  /*    charstring_len  :: The length in bytes of the charstring stream.   */
828  /*                                                                       */
829  /* <Return>                                                              */
830  /*    FreeType error code.  0 means success.                             */
831  /*                                                                       */
832  FT_LOCAL_DEF( FT_Error )
833  cff_decoder_parse_charstrings( CFF_Decoder*  decoder,
834                                 FT_Byte*      charstring_base,
835                                 FT_ULong      charstring_len )
836  {
837    FT_Error           error;
838    CFF_Decoder_Zone*  zone;
839    FT_Byte*           ip;
840    FT_Byte*           limit;
841    CFF_Builder*       builder = &decoder->builder;
842    FT_Pos             x, y;
843    FT_Fixed           seed;
844    FT_Fixed*          stack;
845
846    T2_Hints_Funcs     hinter;
847
848
849    /* set default width */
850    decoder->num_hints  = 0;
851    decoder->read_width = 1;
852
853    /* compute random seed from stack address of parameter */
854    seed = (FT_Fixed)(char*)&seed           ^
855           (FT_Fixed)(char*)&decoder        ^
856           (FT_Fixed)(char*)&charstring_base;
857    seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL;
858    if ( seed == 0 )
859      seed = 0x7384;
860
861    /* initialize the decoder */
862    decoder->top  = decoder->stack;
863    decoder->zone = decoder->zones;
864    zone          = decoder->zones;
865    stack         = decoder->top;
866
867    hinter = (T2_Hints_Funcs)builder->hints_funcs;
868
869    builder->path_begun = 0;
870
871    zone->base           = charstring_base;
872    limit = zone->limit  = charstring_base + charstring_len;
873    ip    = zone->cursor = zone->base;
874
875    error = CFF_Err_Ok;
876
877    x = builder->pos_x;
878    y = builder->pos_y;
879
880    /* begin hints recording session, if any */
881    if ( hinter )
882      hinter->open( hinter->hints );
883
884    /* now execute loop */
885    while ( ip < limit )
886    {
887      CFF_Operator  op;
888      FT_Byte       v;
889
890
891      /********************************************************************/
892      /*                                                                  */
893      /* Decode operator or operand                                       */
894      /*                                                                  */
895      v = *ip++;
896      if ( v >= 32 || v == 28 )
897      {
898        FT_Int    shift = 16;
899        FT_Int32  val;
900
901
902        /* this is an operand, push it on the stack */
903        if ( v == 28 )
904        {
905          if ( ip + 1 >= limit )
906            goto Syntax_Error;
907          val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] );
908          ip += 2;
909        }
910        else if ( v < 247 )
911          val = (FT_Long)v - 139;
912        else if ( v < 251 )
913        {
914          if ( ip >= limit )
915            goto Syntax_Error;
916          val = ( (FT_Long)v - 247 ) * 256 + *ip++ + 108;
917        }
918        else if ( v < 255 )
919        {
920          if ( ip >= limit )
921            goto Syntax_Error;
922          val = -( (FT_Long)v - 251 ) * 256 - *ip++ - 108;
923        }
924        else
925        {
926          if ( ip + 3 >= limit )
927            goto Syntax_Error;
928          val = ( (FT_Int32)ip[0] << 24 ) |
929                ( (FT_Int32)ip[1] << 16 ) |
930                ( (FT_Int32)ip[2] <<  8 ) |
931                            ip[3];
932          ip    += 4;
933          shift  = 0;
934        }
935        if ( decoder->top - stack >= CFF_MAX_OPERANDS )
936          goto Stack_Overflow;
937
938        val           <<= shift;
939        *decoder->top++ = val;
940
941#ifdef FT_DEBUG_LEVEL_TRACE
942        if ( !( val & 0xFFFFL ) )
943          FT_TRACE4(( " %ld", (FT_Int32)( val >> 16 ) ));
944        else
945          FT_TRACE4(( " %.2f", val / 65536.0 ));
946#endif
947
948      }
949      else
950      {
951        FT_Fixed*  args     = decoder->top;
952        FT_Int     num_args = (FT_Int)( args - decoder->stack );
953        FT_Int     req_args;
954
955
956        /* find operator */
957        op = cff_op_unknown;
958
959        switch ( v )
960        {
961        case 1:
962          op = cff_op_hstem;
963          break;
964        case 3:
965          op = cff_op_vstem;
966          break;
967        case 4:
968          op = cff_op_vmoveto;
969          break;
970        case 5:
971          op = cff_op_rlineto;
972          break;
973        case 6:
974          op = cff_op_hlineto;
975          break;
976        case 7:
977          op = cff_op_vlineto;
978          break;
979        case 8:
980          op = cff_op_rrcurveto;
981          break;
982        case 9:
983          op = cff_op_closepath;
984          break;
985        case 10:
986          op = cff_op_callsubr;
987          break;
988        case 11:
989          op = cff_op_return;
990          break;
991        case 12:
992          {
993            if ( ip >= limit )
994              goto Syntax_Error;
995            v = *ip++;
996
997            switch ( v )
998            {
999            case 0:
1000              op = cff_op_dotsection;
1001              break;
1002            case 3:
1003              op = cff_op_and;
1004              break;
1005            case 4:
1006              op = cff_op_or;
1007              break;
1008            case 5:
1009              op = cff_op_not;
1010              break;
1011            case 8:
1012              op = cff_op_store;
1013              break;
1014            case 9:
1015              op = cff_op_abs;
1016              break;
1017            case 10:
1018              op = cff_op_add;
1019              break;
1020            case 11:
1021              op = cff_op_sub;
1022              break;
1023            case 12:
1024              op = cff_op_div;
1025              break;
1026            case 13:
1027              op = cff_op_load;
1028              break;
1029            case 14:
1030              op = cff_op_neg;
1031              break;
1032            case 15:
1033              op = cff_op_eq;
1034              break;
1035            case 18:
1036              op = cff_op_drop;
1037              break;
1038            case 20:
1039              op = cff_op_put;
1040              break;
1041            case 21:
1042              op = cff_op_get;
1043              break;
1044            case 22:
1045              op = cff_op_ifelse;
1046              break;
1047            case 23:
1048              op = cff_op_random;
1049              break;
1050            case 24:
1051              op = cff_op_mul;
1052              break;
1053            case 26:
1054              op = cff_op_sqrt;
1055              break;
1056            case 27:
1057              op = cff_op_dup;
1058              break;
1059            case 28:
1060              op = cff_op_exch;
1061              break;
1062            case 29:
1063              op = cff_op_index;
1064              break;
1065            case 30:
1066              op = cff_op_roll;
1067              break;
1068            case 34:
1069              op = cff_op_hflex;
1070              break;
1071            case 35:
1072              op = cff_op_flex;
1073              break;
1074            case 36:
1075              op = cff_op_hflex1;
1076              break;
1077            case 37:
1078              op = cff_op_flex1;
1079              break;
1080            default:
1081              /* decrement ip for syntax error message */
1082              ip--;
1083            }
1084          }
1085          break;
1086        case 13:
1087          op = cff_op_hsbw;
1088          break;
1089        case 14:
1090          op = cff_op_endchar;
1091          break;
1092        case 16:
1093          op = cff_op_blend;
1094          break;
1095        case 18:
1096          op = cff_op_hstemhm;
1097          break;
1098        case 19:
1099          op = cff_op_hintmask;
1100          break;
1101        case 20:
1102          op = cff_op_cntrmask;
1103          break;
1104        case 21:
1105          op = cff_op_rmoveto;
1106          break;
1107        case 22:
1108          op = cff_op_hmoveto;
1109          break;
1110        case 23:
1111          op = cff_op_vstemhm;
1112          break;
1113        case 24:
1114          op = cff_op_rcurveline;
1115          break;
1116        case 25:
1117          op = cff_op_rlinecurve;
1118          break;
1119        case 26:
1120          op = cff_op_vvcurveto;
1121          break;
1122        case 27:
1123          op = cff_op_hhcurveto;
1124          break;
1125        case 29:
1126          op = cff_op_callgsubr;
1127          break;
1128        case 30:
1129          op = cff_op_vhcurveto;
1130          break;
1131        case 31:
1132          op = cff_op_hvcurveto;
1133          break;
1134        default:
1135          ;
1136        }
1137        if ( op == cff_op_unknown )
1138          goto Syntax_Error;
1139
1140        /* check arguments */
1141        req_args = cff_argument_counts[op];
1142        if ( req_args & CFF_COUNT_CHECK_WIDTH )
1143        {
1144          args = stack;
1145
1146          if ( num_args > 0 && decoder->read_width )
1147          {
1148            /* If `nominal_width' is non-zero, the number is really a      */
1149            /* difference against `nominal_width'.  Else, the number here  */
1150            /* is truly a width, not a difference against `nominal_width'. */
1151            /* If the font does not set `nominal_width', then              */
1152            /* `nominal_width' defaults to zero, and so we can set         */
1153            /* `glyph_width' to `nominal_width' plus number on the stack   */
1154            /* -- for either case.                                         */
1155
1156            FT_Int  set_width_ok;
1157
1158
1159            switch ( op )
1160            {
1161            case cff_op_hmoveto:
1162            case cff_op_vmoveto:
1163              set_width_ok = num_args & 2;
1164              break;
1165
1166            case cff_op_hstem:
1167            case cff_op_vstem:
1168            case cff_op_hstemhm:
1169            case cff_op_vstemhm:
1170            case cff_op_rmoveto:
1171            case cff_op_hintmask:
1172            case cff_op_cntrmask:
1173              set_width_ok = num_args & 1;
1174              break;
1175
1176            case cff_op_endchar:
1177              /* If there is a width specified for endchar, we either have */
1178              /* 1 argument or 5 arguments.  We like to argue.             */
1179              set_width_ok = ( ( num_args == 5 ) || ( num_args == 1 ) );
1180              break;
1181
1182            default:
1183              set_width_ok = 0;
1184              break;
1185            }
1186
1187            if ( set_width_ok )
1188            {
1189              decoder->glyph_width = decoder->nominal_width +
1190                                       ( stack[0] >> 16 );
1191
1192              if (decoder->width_only)
1193              {
1194                /* we only want the advance width, stop here */
1195                break;
1196              }
1197
1198              /* Consumed an argument. */
1199              num_args--;
1200              args++;
1201            }
1202          }
1203
1204          decoder->read_width = 0;
1205          req_args            = 0;
1206        }
1207
1208        req_args &= 0x000F;
1209        if ( num_args < req_args )
1210          goto Stack_Underflow;
1211        args     -= req_args;
1212        num_args -= req_args;
1213
1214        switch ( op )
1215        {
1216        case cff_op_hstem:
1217        case cff_op_vstem:
1218        case cff_op_hstemhm:
1219        case cff_op_vstemhm:
1220          /* the number of arguments is always even here */
1221          FT_TRACE4(( op == cff_op_hstem   ? " hstem"   :
1222                    ( op == cff_op_vstem   ? " vstem"   :
1223                    ( op == cff_op_hstemhm ? " hstemhm" : " vstemhm" ) ) ));
1224
1225          if ( hinter )
1226            hinter->stems( hinter->hints,
1227                           ( op == cff_op_hstem || op == cff_op_hstemhm ),
1228                           num_args / 2,
1229                           args );
1230
1231          decoder->num_hints += num_args / 2;
1232          args = stack;
1233          break;
1234
1235        case cff_op_hintmask:
1236        case cff_op_cntrmask:
1237          FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" ));
1238
1239          /* implement vstem when needed --                        */
1240          /* the specification doesn't say it, but this also works */
1241          /* with the 'cntrmask' operator                          */
1242          /*                                                       */
1243          if ( num_args > 0 )
1244          {
1245            if ( hinter )
1246              hinter->stems( hinter->hints,
1247                             0,
1248                             num_args / 2,
1249                             args );
1250
1251            decoder->num_hints += num_args / 2;
1252          }
1253
1254          if ( hinter )
1255          {
1256            if ( op == cff_op_hintmask )
1257              hinter->hintmask( hinter->hints,
1258                                builder->current->n_points,
1259                                decoder->num_hints,
1260                                ip );
1261            else
1262              hinter->counter( hinter->hints,
1263                               decoder->num_hints,
1264                               ip );
1265          }
1266
1267#ifdef FT_DEBUG_LEVEL_TRACE
1268          {
1269            FT_UInt maskbyte;
1270
1271
1272            FT_TRACE4(( " " ));
1273
1274            for ( maskbyte = 0;
1275                  maskbyte < (FT_UInt)(( decoder->num_hints + 7 ) >> 3);
1276                  maskbyte++, ip++ )
1277              FT_TRACE4(( "0x%02X", *ip ));
1278          }
1279#else
1280          ip += ( decoder->num_hints + 7 ) >> 3;
1281#endif
1282          if ( ip >= limit )
1283            goto Syntax_Error;
1284          args = stack;
1285          break;
1286
1287        case cff_op_rmoveto:
1288          FT_TRACE4(( " rmoveto" ));
1289
1290          cff_builder_close_contour( builder );
1291          builder->path_begun = 0;
1292          x   += args[0];
1293          y   += args[1];
1294          args = stack;
1295          break;
1296
1297        case cff_op_vmoveto:
1298          FT_TRACE4(( " vmoveto" ));
1299
1300          cff_builder_close_contour( builder );
1301          builder->path_begun = 0;
1302          y   += args[0];
1303          args = stack;
1304          break;
1305
1306        case cff_op_hmoveto:
1307          FT_TRACE4(( " hmoveto" ));
1308
1309          cff_builder_close_contour( builder );
1310          builder->path_begun = 0;
1311          x   += args[0];
1312          args = stack;
1313          break;
1314
1315        case cff_op_rlineto:
1316          FT_TRACE4(( " rlineto" ));
1317
1318          if ( cff_builder_start_point ( builder, x, y ) ||
1319               check_points( builder, num_args / 2 )     )
1320            goto Fail;
1321
1322          if ( num_args < 2 || num_args & 1 )
1323            goto Stack_Underflow;
1324
1325          args = stack;
1326          while ( args < decoder->top )
1327          {
1328            x += args[0];
1329            y += args[1];
1330            cff_builder_add_point( builder, x, y, 1 );
1331            args += 2;
1332          }
1333          args = stack;
1334          break;
1335
1336        case cff_op_hlineto:
1337        case cff_op_vlineto:
1338          {
1339            FT_Int  phase = ( op == cff_op_hlineto );
1340
1341
1342            FT_TRACE4(( op == cff_op_hlineto ? " hlineto"
1343                                             : " vlineto" ));
1344
1345            if ( cff_builder_start_point ( builder, x, y ) ||
1346                 check_points( builder, num_args )         )
1347              goto Fail;
1348
1349            args = stack;
1350            while ( args < decoder->top )
1351            {
1352              if ( phase )
1353                x += args[0];
1354              else
1355                y += args[0];
1356
1357              if ( cff_builder_add_point1( builder, x, y ) )
1358                goto Fail;
1359
1360              args++;
1361              phase ^= 1;
1362            }
1363            args = stack;
1364          }
1365          break;
1366
1367        case cff_op_rrcurveto:
1368          FT_TRACE4(( " rrcurveto" ));
1369
1370          /* check number of arguments; must be a multiple of 6 */
1371          if ( num_args % 6 != 0 )
1372            goto Stack_Underflow;
1373
1374          if ( cff_builder_start_point ( builder, x, y ) ||
1375               check_points( builder, num_args / 2 )     )
1376            goto Fail;
1377
1378          args = stack;
1379          while ( args < decoder->top )
1380          {
1381            x += args[0];
1382            y += args[1];
1383            cff_builder_add_point( builder, x, y, 0 );
1384            x += args[2];
1385            y += args[3];
1386            cff_builder_add_point( builder, x, y, 0 );
1387            x += args[4];
1388            y += args[5];
1389            cff_builder_add_point( builder, x, y, 1 );
1390            args += 6;
1391          }
1392          args = stack;
1393          break;
1394
1395        case cff_op_vvcurveto:
1396          FT_TRACE4(( " vvcurveto" ));
1397
1398          if ( cff_builder_start_point( builder, x, y ) )
1399            goto Fail;
1400
1401          args = stack;
1402          if ( num_args & 1 )
1403          {
1404            x += args[0];
1405            args++;
1406            num_args--;
1407          }
1408
1409          if ( num_args % 4 != 0 )
1410            goto Stack_Underflow;
1411
1412          if ( check_points( builder, 3 * ( num_args / 4 ) ) )
1413            goto Fail;
1414
1415          while ( args < decoder->top )
1416          {
1417            y += args[0];
1418            cff_builder_add_point( builder, x, y, 0 );
1419            x += args[1];
1420            y += args[2];
1421            cff_builder_add_point( builder, x, y, 0 );
1422            y += args[3];
1423            cff_builder_add_point( builder, x, y, 1 );
1424            args += 4;
1425          }
1426          args = stack;
1427          break;
1428
1429        case cff_op_hhcurveto:
1430          FT_TRACE4(( " hhcurveto" ));
1431
1432          if ( cff_builder_start_point( builder, x, y ) )
1433            goto Fail;
1434
1435          args = stack;
1436          if ( num_args & 1 )
1437          {
1438            y += args[0];
1439            args++;
1440            num_args--;
1441          }
1442
1443          if ( num_args % 4 != 0 )
1444            goto Stack_Underflow;
1445
1446          if ( check_points( builder, 3 * ( num_args / 4 ) ) )
1447            goto Fail;
1448
1449          while ( args < decoder->top )
1450          {
1451            x += args[0];
1452            cff_builder_add_point( builder, x, y, 0 );
1453            x += args[1];
1454            y += args[2];
1455            cff_builder_add_point( builder, x, y, 0 );
1456            x += args[3];
1457            cff_builder_add_point( builder, x, y, 1 );
1458            args += 4;
1459          }
1460          args = stack;
1461          break;
1462
1463        case cff_op_vhcurveto:
1464        case cff_op_hvcurveto:
1465          {
1466            FT_Int  phase;
1467
1468
1469            FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto"
1470                                               : " hvcurveto" ));
1471
1472            if ( cff_builder_start_point( builder, x, y ) )
1473              goto Fail;
1474
1475            args = stack;
1476            if ( num_args < 4 || ( num_args % 4 ) > 1 )
1477              goto Stack_Underflow;
1478
1479            if ( check_points( builder, ( num_args / 4 ) * 3 ) )
1480              goto Stack_Underflow;
1481
1482            phase = ( op == cff_op_hvcurveto );
1483
1484            while ( num_args >= 4 )
1485            {
1486              num_args -= 4;
1487              if ( phase )
1488              {
1489                x += args[0];
1490                cff_builder_add_point( builder, x, y, 0 );
1491                x += args[1];
1492                y += args[2];
1493                cff_builder_add_point( builder, x, y, 0 );
1494                y += args[3];
1495                if ( num_args == 1 )
1496                  x += args[4];
1497                cff_builder_add_point( builder, x, y, 1 );
1498              }
1499              else
1500              {
1501                y += args[0];
1502                cff_builder_add_point( builder, x, y, 0 );
1503                x += args[1];
1504                y += args[2];
1505                cff_builder_add_point( builder, x, y, 0 );
1506                x += args[3];
1507                if ( num_args == 1 )
1508                  y += args[4];
1509                cff_builder_add_point( builder, x, y, 1 );
1510              }
1511              args  += 4;
1512              phase ^= 1;
1513            }
1514            args = stack;
1515          }
1516          break;
1517
1518        case cff_op_rlinecurve:
1519          {
1520            FT_Int  num_lines = ( num_args - 6 ) / 2;
1521
1522
1523            FT_TRACE4(( " rlinecurve" ));
1524
1525            if ( num_args < 8 || ( num_args - 6 ) & 1 )
1526              goto Stack_Underflow;
1527
1528            if ( cff_builder_start_point( builder, x, y ) ||
1529                 check_points( builder, num_lines + 3 )   )
1530              goto Fail;
1531
1532            args = stack;
1533
1534            /* first, add the line segments */
1535            while ( num_lines > 0 )
1536            {
1537              x += args[0];
1538              y += args[1];
1539              cff_builder_add_point( builder, x, y, 1 );
1540              args += 2;
1541              num_lines--;
1542            }
1543
1544            /* then the curve */
1545            x += args[0];
1546            y += args[1];
1547            cff_builder_add_point( builder, x, y, 0 );
1548            x += args[2];
1549            y += args[3];
1550            cff_builder_add_point( builder, x, y, 0 );
1551            x += args[4];
1552            y += args[5];
1553            cff_builder_add_point( builder, x, y, 1 );
1554            args = stack;
1555          }
1556          break;
1557
1558        case cff_op_rcurveline:
1559          {
1560            FT_Int  num_curves = ( num_args - 2 ) / 6;
1561
1562
1563            FT_TRACE4(( " rcurveline" ));
1564
1565            if ( num_args < 8 || ( num_args - 2 ) % 6 )
1566              goto Stack_Underflow;
1567
1568            if ( cff_builder_start_point ( builder, x, y ) ||
1569                 check_points( builder, num_curves*3 + 2 ) )
1570              goto Fail;
1571
1572            args = stack;
1573
1574            /* first, add the curves */
1575            while ( num_curves > 0 )
1576            {
1577              x += args[0];
1578              y += args[1];
1579              cff_builder_add_point( builder, x, y, 0 );
1580              x += args[2];
1581              y += args[3];
1582              cff_builder_add_point( builder, x, y, 0 );
1583              x += args[4];
1584              y += args[5];
1585              cff_builder_add_point( builder, x, y, 1 );
1586              args += 6;
1587              num_curves--;
1588            }
1589
1590            /* then the final line */
1591            x += args[0];
1592            y += args[1];
1593            cff_builder_add_point( builder, x, y, 1 );
1594            args = stack;
1595          }
1596          break;
1597
1598        case cff_op_hflex1:
1599          {
1600            FT_Pos start_y;
1601
1602
1603            FT_TRACE4(( " hflex1" ));
1604
1605            args = stack;
1606
1607            /* adding five more points; 4 control points, 1 on-curve point */
1608            /* make sure we have enough space for the start point if it    */
1609            /* needs to be added                                           */
1610            if ( cff_builder_start_point( builder, x, y ) ||
1611                 check_points( builder, 6 )               )
1612              goto Fail;
1613
1614            /* Record the starting point's y position for later use */
1615            start_y = y;
1616
1617            /* first control point */
1618            x += args[0];
1619            y += args[1];
1620            cff_builder_add_point( builder, x, y, 0 );
1621
1622            /* second control point */
1623            x += args[2];
1624            y += args[3];
1625            cff_builder_add_point( builder, x, y, 0 );
1626
1627            /* join point; on curve, with y-value the same as the last */
1628            /* control point's y-value                                 */
1629            x += args[4];
1630            cff_builder_add_point( builder, x, y, 1 );
1631
1632            /* third control point, with y-value the same as the join */
1633            /* point's y-value                                        */
1634            x += args[5];
1635            cff_builder_add_point( builder, x, y, 0 );
1636
1637            /* fourth control point */
1638            x += args[6];
1639            y += args[7];
1640            cff_builder_add_point( builder, x, y, 0 );
1641
1642            /* ending point, with y-value the same as the start   */
1643            x += args[8];
1644            y  = start_y;
1645            cff_builder_add_point( builder, x, y, 1 );
1646
1647            args = stack;
1648            break;
1649          }
1650
1651        case cff_op_hflex:
1652          {
1653            FT_Pos start_y;
1654
1655
1656            FT_TRACE4(( " hflex" ));
1657
1658            args = stack;
1659
1660            /* adding six more points; 4 control points, 2 on-curve points */
1661            if ( cff_builder_start_point( builder, x, y ) ||
1662                 check_points( builder, 6 )               )
1663              goto Fail;
1664
1665            /* record the starting point's y-position for later use */
1666            start_y = y;
1667
1668            /* first control point */
1669            x += args[0];
1670            cff_builder_add_point( builder, x, y, 0 );
1671
1672            /* second control point */
1673            x += args[1];
1674            y += args[2];
1675            cff_builder_add_point( builder, x, y, 0 );
1676
1677            /* join point; on curve, with y-value the same as the last */
1678            /* control point's y-value                                 */
1679            x += args[3];
1680            cff_builder_add_point( builder, x, y, 1 );
1681
1682            /* third control point, with y-value the same as the join */
1683            /* point's y-value                                        */
1684            x += args[4];
1685            cff_builder_add_point( builder, x, y, 0 );
1686
1687            /* fourth control point */
1688            x += args[5];
1689            y  = start_y;
1690            cff_builder_add_point( builder, x, y, 0 );
1691
1692            /* ending point, with y-value the same as the start point's */
1693            /* y-value -- we don't add this point, though               */
1694            x += args[6];
1695            cff_builder_add_point( builder, x, y, 1 );
1696
1697            args = stack;
1698            break;
1699          }
1700
1701        case cff_op_flex1:
1702          {
1703            FT_Pos    start_x, start_y; /* record start x, y values for */
1704                                        /* alter use                                */
1705            FT_Fixed  dx = 0, dy = 0;   /* used in horizontal/vertical  */
1706                                        /* algorithm below              */
1707            FT_Int    horizontal, count;
1708
1709
1710            FT_TRACE4(( " flex1" ));
1711
1712            /* adding six more points; 4 control points, 2 on-curve points */
1713            if ( cff_builder_start_point( builder, x, y ) ||
1714                 check_points( builder, 6 )               )
1715              goto Fail;
1716
1717            /* record the starting point's x, y position for later use */
1718            start_x = x;
1719            start_y = y;
1720
1721            /* XXX: figure out whether this is supposed to be a horizontal */
1722            /*      or vertical flex; the Type 2 specification is vague... */
1723
1724            args = stack;
1725
1726            /* grab up to the last argument */
1727            for ( count = 5; count > 0; count-- )
1728            {
1729              dx += args[0];
1730              dy += args[1];
1731              args += 2;
1732            }
1733
1734            /* rewind */
1735            args = stack;
1736
1737            if ( dx < 0 ) dx = -dx;
1738            if ( dy < 0 ) dy = -dy;
1739
1740            /* strange test, but here it is... */
1741            horizontal = ( dx > dy );
1742
1743            for ( count = 5; count > 0; count-- )
1744            {
1745              x += args[0];
1746              y += args[1];
1747              cff_builder_add_point( builder, x, y, (FT_Bool)( count == 3 ) );
1748              args += 2;
1749            }
1750
1751            /* is last operand an x- or y-delta? */
1752            if ( horizontal )
1753            {
1754              x += args[0];
1755              y  = start_y;
1756            }
1757            else
1758            {
1759              x  = start_x;
1760              y += args[0];
1761            }
1762
1763            cff_builder_add_point( builder, x, y, 1 );
1764
1765            args = stack;
1766            break;
1767           }
1768
1769        case cff_op_flex:
1770          {
1771            FT_UInt  count;
1772
1773
1774            FT_TRACE4(( " flex" ));
1775
1776            if ( cff_builder_start_point( builder, x, y ) ||
1777                 check_points( builder, 6 )               )
1778              goto Fail;
1779
1780            args = stack;
1781            for ( count = 6; count > 0; count-- )
1782            {
1783              x += args[0];
1784              y += args[1];
1785              cff_builder_add_point( builder, x, y,
1786                                     (FT_Bool)( count == 4 || count == 1 ) );
1787              args += 2;
1788            }
1789
1790            args = stack;
1791          }
1792          break;
1793
1794        case cff_op_endchar:
1795          FT_TRACE4(( " endchar" ));
1796
1797          /* We are going to emulate the seac operator. */
1798          if ( num_args == 4 )
1799          {
1800            /* Save glyph width so that the subglyphs don't overwrite it. */
1801            FT_Pos  glyph_width = decoder->glyph_width;
1802
1803
1804            error = cff_operator_seac( decoder,
1805                                       args[0],
1806                                       args[1],
1807                                       (FT_Int)( args[2] >> 16 ),
1808                                       (FT_Int)( args[3] >> 16 ) );
1809            args += 4;
1810
1811            decoder->glyph_width = glyph_width;
1812          }
1813          else
1814          {
1815            if ( !error )
1816              error = CFF_Err_Ok;
1817
1818            cff_builder_close_contour( builder );
1819
1820            /* close hints recording session */
1821            if ( hinter )
1822            {
1823              if ( hinter->close( hinter->hints,
1824                                  builder->current->n_points ) )
1825                goto Syntax_Error;
1826
1827              /* apply hints to the loaded glyph outline now */
1828              hinter->apply( hinter->hints,
1829                             builder->current,
1830                             (PSH_Globals)builder->hints_globals,
1831                             decoder->hint_mode );
1832            }
1833
1834            /* add current outline to the glyph slot */
1835            FT_GlyphLoader_Add( builder->loader );
1836          }
1837
1838          /* return now! */
1839          FT_TRACE4(( "\n\n" ));
1840          return error;
1841
1842        case cff_op_abs:
1843          FT_TRACE4(( " abs" ));
1844
1845          if ( args[0] < 0 )
1846            args[0] = -args[0];
1847          args++;
1848          break;
1849
1850        case cff_op_add:
1851          FT_TRACE4(( " add" ));
1852
1853          args[0] += args[1];
1854          args++;
1855          break;
1856
1857        case cff_op_sub:
1858          FT_TRACE4(( " sub" ));
1859
1860          args[0] -= args[1];
1861          args++;
1862          break;
1863
1864        case cff_op_div:
1865          FT_TRACE4(( " div" ));
1866
1867          args[0] = FT_DivFix( args[0], args[1] );
1868          args++;
1869          break;
1870
1871        case cff_op_neg:
1872          FT_TRACE4(( " neg" ));
1873
1874          args[0] = -args[0];
1875          args++;
1876          break;
1877
1878        case cff_op_random:
1879          {
1880            FT_Fixed  Rand;
1881
1882
1883            FT_TRACE4(( " rand" ));
1884
1885            Rand = seed;
1886            if ( Rand >= 0x8000L )
1887              Rand++;
1888
1889            args[0] = Rand;
1890            seed    = FT_MulFix( seed, 0x10000L - seed );
1891            if ( seed == 0 )
1892              seed += 0x2873;
1893            args++;
1894          }
1895          break;
1896
1897        case cff_op_mul:
1898          FT_TRACE4(( " mul" ));
1899
1900          args[0] = FT_MulFix( args[0], args[1] );
1901          args++;
1902          break;
1903
1904        case cff_op_sqrt:
1905          FT_TRACE4(( " sqrt" ));
1906
1907          if ( args[0] > 0 )
1908          {
1909            FT_Int    count = 9;
1910            FT_Fixed  root  = args[0];
1911            FT_Fixed  new_root;
1912
1913
1914            for (;;)
1915            {
1916              new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1;
1917              if ( new_root == root || count <= 0 )
1918                break;
1919              root = new_root;
1920            }
1921            args[0] = new_root;
1922          }
1923          else
1924            args[0] = 0;
1925          args++;
1926          break;
1927
1928        case cff_op_drop:
1929          /* nothing */
1930          FT_TRACE4(( " drop" ));
1931
1932          break;
1933
1934        case cff_op_exch:
1935          {
1936            FT_Fixed  tmp;
1937
1938
1939            FT_TRACE4(( " exch" ));
1940
1941            tmp     = args[0];
1942            args[0] = args[1];
1943            args[1] = tmp;
1944            args   += 2;
1945          }
1946          break;
1947
1948        case cff_op_index:
1949          {
1950            FT_Int  idx = (FT_Int)( args[0] >> 16 );
1951
1952
1953            FT_TRACE4(( " index" ));
1954
1955            if ( idx < 0 )
1956              idx = 0;
1957            else if ( idx > num_args - 2 )
1958              idx = num_args - 2;
1959            args[0] = args[-( idx + 1 )];
1960            args++;
1961          }
1962          break;
1963
1964        case cff_op_roll:
1965          {
1966            FT_Int  count = (FT_Int)( args[0] >> 16 );
1967            FT_Int  idx   = (FT_Int)( args[1] >> 16 );
1968
1969
1970            FT_TRACE4(( " roll" ));
1971
1972            if ( count <= 0 )
1973              count = 1;
1974
1975            args -= count;
1976            if ( args < stack )
1977              goto Stack_Underflow;
1978
1979            if ( idx >= 0 )
1980            {
1981              while ( idx > 0 )
1982              {
1983                FT_Fixed  tmp = args[count - 1];
1984                FT_Int    i;
1985
1986
1987                for ( i = count - 2; i >= 0; i-- )
1988                  args[i + 1] = args[i];
1989                args[0] = tmp;
1990                idx--;
1991              }
1992            }
1993            else
1994            {
1995              while ( idx < 0 )
1996              {
1997                FT_Fixed  tmp = args[0];
1998                FT_Int    i;
1999
2000
2001                for ( i = 0; i < count - 1; i++ )
2002                  args[i] = args[i + 1];
2003                args[count - 1] = tmp;
2004                idx++;
2005              }
2006            }
2007            args += count;
2008          }
2009          break;
2010
2011        case cff_op_dup:
2012          FT_TRACE4(( " dup" ));
2013
2014          args[1] = args[0];
2015          args++;
2016          break;
2017
2018        case cff_op_put:
2019          {
2020            FT_Fixed  val = args[0];
2021            FT_Int    idx = (FT_Int)( args[1] >> 16 );
2022
2023
2024            FT_TRACE4(( " put" ));
2025
2026            if ( idx >= 0 && idx < decoder->len_buildchar )
2027              decoder->buildchar[idx] = val;
2028          }
2029          break;
2030
2031        case cff_op_get:
2032          {
2033            FT_Int    idx = (FT_Int)( args[0] >> 16 );
2034            FT_Fixed  val = 0;
2035
2036
2037            FT_TRACE4(( " get" ));
2038
2039            if ( idx >= 0 && idx < decoder->len_buildchar )
2040              val = decoder->buildchar[idx];
2041
2042            args[0] = val;
2043            args++;
2044          }
2045          break;
2046
2047        case cff_op_store:
2048          FT_TRACE4(( " store "));
2049
2050          goto Unimplemented;
2051
2052        case cff_op_load:
2053          FT_TRACE4(( " load" ));
2054
2055          goto Unimplemented;
2056
2057        case cff_op_dotsection:
2058          /* this operator is deprecated and ignored by the parser */
2059          FT_TRACE4(( " dotsection" ));
2060          break;
2061
2062        case cff_op_closepath:
2063          /* this is an invalid Type 2 operator; however, there        */
2064          /* exist fonts which are incorrectly converted from probably */
2065          /* Type 1 to CFF, and some parsers seem to accept it         */
2066
2067          FT_TRACE4(( " closepath (invalid op)" ));
2068
2069          args = stack;
2070          break;
2071
2072        case cff_op_hsbw:
2073          /* this is an invalid Type 2 operator; however, there        */
2074          /* exist fonts which are incorrectly converted from probably */
2075          /* Type 1 to CFF, and some parsers seem to accept it         */
2076
2077          FT_TRACE4(( " hsbw (invalid op)" ));
2078
2079          decoder->glyph_width = decoder->nominal_width +
2080                                   (args[1] >> 16);
2081          x    = args[0];
2082          y    = 0;
2083          args = stack;
2084          break;
2085
2086        case cff_op_and:
2087          {
2088            FT_Fixed  cond = args[0] && args[1];
2089
2090
2091            FT_TRACE4(( " and" ));
2092
2093            args[0] = cond ? 0x10000L : 0;
2094            args++;
2095          }
2096          break;
2097
2098        case cff_op_or:
2099          {
2100            FT_Fixed  cond = args[0] || args[1];
2101
2102
2103            FT_TRACE4(( " or" ));
2104
2105            args[0] = cond ? 0x10000L : 0;
2106            args++;
2107          }
2108          break;
2109
2110        case cff_op_eq:
2111          {
2112            FT_Fixed  cond = !args[0];
2113
2114
2115            FT_TRACE4(( " eq" ));
2116
2117            args[0] = cond ? 0x10000L : 0;
2118            args++;
2119          }
2120          break;
2121
2122        case cff_op_ifelse:
2123          {
2124            FT_Fixed  cond = ( args[2] <= args[3] );
2125
2126
2127            FT_TRACE4(( " ifelse" ));
2128
2129            if ( !cond )
2130              args[0] = args[1];
2131            args++;
2132          }
2133          break;
2134
2135        case cff_op_callsubr:
2136          {
2137            FT_UInt  idx = (FT_UInt)( ( args[0] >> 16 ) +
2138                                      decoder->locals_bias );
2139
2140
2141            FT_TRACE4(( " callsubr(%d)", idx ));
2142
2143            if ( idx >= decoder->num_locals )
2144            {
2145              FT_ERROR(( "cff_decoder_parse_charstrings:" ));
2146              FT_ERROR(( " invalid local subr index\n" ));
2147              goto Syntax_Error;
2148            }
2149
2150            if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
2151            {
2152              FT_ERROR(( "cff_decoder_parse_charstrings:"
2153                         " too many nested subrs\n" ));
2154              goto Syntax_Error;
2155            }
2156
2157            zone->cursor = ip;  /* save current instruction pointer */
2158
2159            zone++;
2160            zone->base   = decoder->locals[idx];
2161            zone->limit  = decoder->locals[idx + 1];
2162            zone->cursor = zone->base;
2163
2164            if ( !zone->base || zone->limit == zone->base )
2165            {
2166              FT_ERROR(( "cff_decoder_parse_charstrings:"
2167                         " invoking empty subrs!\n" ));
2168              goto Syntax_Error;
2169            }
2170
2171            decoder->zone = zone;
2172            ip            = zone->base;
2173            limit         = zone->limit;
2174          }
2175          break;
2176
2177        case cff_op_callgsubr:
2178          {
2179            FT_UInt  idx = (FT_UInt)( ( args[0] >> 16 ) +
2180                                      decoder->globals_bias );
2181
2182
2183            FT_TRACE4(( " callgsubr(%d)", idx ));
2184
2185            if ( idx >= decoder->num_globals )
2186            {
2187              FT_ERROR(( "cff_decoder_parse_charstrings:" ));
2188              FT_ERROR(( " invalid global subr index\n" ));
2189              goto Syntax_Error;
2190            }
2191
2192            if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
2193            {
2194              FT_ERROR(( "cff_decoder_parse_charstrings:"
2195                         " too many nested subrs\n" ));
2196              goto Syntax_Error;
2197            }
2198
2199            zone->cursor = ip;  /* save current instruction pointer */
2200
2201            zone++;
2202            zone->base   = decoder->globals[idx];
2203            zone->limit  = decoder->globals[idx + 1];
2204            zone->cursor = zone->base;
2205
2206            if ( !zone->base || zone->limit == zone->base )
2207            {
2208              FT_ERROR(( "cff_decoder_parse_charstrings:"
2209                         " invoking empty subrs!\n" ));
2210              goto Syntax_Error;
2211            }
2212
2213            decoder->zone = zone;
2214            ip            = zone->base;
2215            limit         = zone->limit;
2216          }
2217          break;
2218
2219        case cff_op_return:
2220          FT_TRACE4(( " return" ));
2221
2222          if ( decoder->zone <= decoder->zones )
2223          {
2224            FT_ERROR(( "cff_decoder_parse_charstrings:"
2225                       " unexpected return\n" ));
2226            goto Syntax_Error;
2227          }
2228
2229          decoder->zone--;
2230          zone  = decoder->zone;
2231          ip    = zone->cursor;
2232          limit = zone->limit;
2233          break;
2234
2235        default:
2236        Unimplemented:
2237          FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
2238
2239          if ( ip[-1] == 12 )
2240            FT_ERROR(( " %d", ip[0] ));
2241          FT_ERROR(( "\n" ));
2242
2243          return CFF_Err_Unimplemented_Feature;
2244        }
2245
2246      decoder->top = args;
2247
2248      } /* general operator processing */
2249
2250    } /* while ip < limit */
2251
2252    FT_TRACE4(( "..end..\n\n" ));
2253
2254  Fail:
2255    return error;
2256
2257  Syntax_Error:
2258    FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error!" ));
2259    return CFF_Err_Invalid_File_Format;
2260
2261  Stack_Underflow:
2262    FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow!" ));
2263    return CFF_Err_Too_Few_Arguments;
2264
2265  Stack_Overflow:
2266    FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow!" ));
2267    return CFF_Err_Stack_Overflow;
2268  }
2269
2270
2271  /*************************************************************************/
2272  /*************************************************************************/
2273  /*************************************************************************/
2274  /**********                                                      *********/
2275  /**********                                                      *********/
2276  /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/
2277  /**********                                                      *********/
2278  /**********    The following code is in charge of computing      *********/
2279  /**********    the maximum advance width of the font.  It        *********/
2280  /**********    quickly processes each glyph charstring to        *********/
2281  /**********    extract the value from either a `sbw' or `seac'   *********/
2282  /**********    operator.                                         *********/
2283  /**********                                                      *********/
2284  /*************************************************************************/
2285  /*************************************************************************/
2286  /*************************************************************************/
2287
2288
2289#if 0 /* unused until we support pure CFF fonts */
2290
2291
2292  FT_LOCAL_DEF( FT_Error )
2293  cff_compute_max_advance( TT_Face  face,
2294                           FT_Int*  max_advance )
2295  {
2296    FT_Error     error = CFF_Err_Ok;
2297    CFF_Decoder  decoder;
2298    FT_Int       glyph_index;
2299    CFF_Font     cff = (CFF_Font)face->other;
2300
2301
2302    *max_advance = 0;
2303
2304    /* Initialize load decoder */
2305    cff_decoder_init( &decoder, face, 0, 0, 0, 0 );
2306
2307    decoder.builder.metrics_only = 1;
2308    decoder.builder.load_points  = 0;
2309
2310    /* For each glyph, parse the glyph charstring and extract */
2311    /* the advance width.                                     */
2312    for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
2313          glyph_index++ )
2314    {
2315      FT_Byte*  charstring;
2316      FT_ULong  charstring_len;
2317
2318
2319      /* now get load the unscaled outline */
2320      error = cff_get_glyph_data( face, glyph_index,
2321                                  &charstring, &charstring_len );
2322      if ( !error )
2323      {
2324        error = cff_decoder_prepare( &decoder, size, glyph_index );
2325        if ( !error )
2326          error = cff_decoder_parse_charstrings( &decoder,
2327                                                 charstring,
2328                                                 charstring_len );
2329
2330        cff_free_glyph_data( face, &charstring, &charstring_len );
2331      }
2332
2333      /* ignore the error if one has occurred -- skip to next glyph */
2334      error = CFF_Err_Ok;
2335    }
2336
2337    *max_advance = decoder.builder.advance.x;
2338
2339    return CFF_Err_Ok;
2340  }
2341
2342
2343#endif /* 0 */
2344
2345
2346  FT_LOCAL_DEF( FT_Error )
2347  cff_slot_load( CFF_GlyphSlot  glyph,
2348                 CFF_Size       size,
2349                 FT_UInt        glyph_index,
2350                 FT_Int32       load_flags )
2351  {
2352    FT_Error     error;
2353    CFF_Decoder  decoder;
2354    TT_Face      face     = (TT_Face)glyph->root.face;
2355    FT_Bool      hinting, force_scaling;
2356    CFF_Font     cff      = (CFF_Font)face->extra.data;
2357
2358    FT_Matrix    font_matrix;
2359    FT_Vector    font_offset;
2360
2361    force_scaling = FALSE;
2362
2363    /* in a CID-keyed font, consider `glyph_index' as a CID and map */
2364    /* it immediately to the real glyph_index -- if it isn't a      */
2365    /* subsetted font, glyph_indices and CIDs are identical, though */
2366    if ( cff->top_font.font_dict.cid_registry != 0xFFFFU &&
2367         cff->charset.cids                               )
2368    {
2369      glyph_index = cff_charset_cid_to_gindex( &cff->charset, glyph_index );
2370      if ( glyph_index == 0 )
2371        return CFF_Err_Invalid_Argument;
2372    }
2373    else if ( glyph_index >= cff->num_glyphs )
2374      return CFF_Err_Invalid_Argument;
2375
2376    if ( load_flags & FT_LOAD_NO_RECURSE )
2377      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
2378
2379    glyph->x_scale = 0x10000L;
2380    glyph->y_scale = 0x10000L;
2381    if ( size )
2382    {
2383      glyph->x_scale = size->root.metrics.x_scale;
2384      glyph->y_scale = size->root.metrics.y_scale;
2385    }
2386
2387#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
2388
2389    /* try to load embedded bitmap if any              */
2390    /*                                                 */
2391    /* XXX: The convention should be emphasized in     */
2392    /*      the documents because it can be confusing. */
2393    if ( size )
2394    {
2395      CFF_Face      cff_face = (CFF_Face)size->root.face;
2396      SFNT_Service  sfnt     = (SFNT_Service)cff_face->sfnt;
2397      FT_Stream     stream   = cff_face->root.stream;
2398
2399
2400      if ( size->strike_index != 0xFFFFFFFFUL      &&
2401           sfnt->load_eblc                         &&
2402           ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
2403      {
2404        TT_SBit_MetricsRec  metrics;
2405
2406
2407        error = sfnt->load_sbit_image( face,
2408                                       size->strike_index,
2409                                       glyph_index,
2410                                       (FT_Int)load_flags,
2411                                       stream,
2412                                       &glyph->root.bitmap,
2413                                       &metrics );
2414
2415        if ( !error )
2416        {
2417          glyph->root.outline.n_points   = 0;
2418          glyph->root.outline.n_contours = 0;
2419
2420          glyph->root.metrics.width  = (FT_Pos)metrics.width  << 6;
2421          glyph->root.metrics.height = (FT_Pos)metrics.height << 6;
2422
2423          glyph->root.metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
2424          glyph->root.metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
2425          glyph->root.metrics.horiAdvance  = (FT_Pos)metrics.horiAdvance  << 6;
2426
2427          glyph->root.metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
2428          glyph->root.metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
2429          glyph->root.metrics.vertAdvance  = (FT_Pos)metrics.vertAdvance  << 6;
2430
2431          glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
2432
2433          if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
2434          {
2435            glyph->root.bitmap_left = metrics.vertBearingX;
2436            glyph->root.bitmap_top  = metrics.vertBearingY;
2437          }
2438          else
2439          {
2440            glyph->root.bitmap_left = metrics.horiBearingX;
2441            glyph->root.bitmap_top  = metrics.horiBearingY;
2442          }
2443          return error;
2444        }
2445      }
2446    }
2447
2448#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
2449
2450    /* return immediately if we only want the embedded bitmaps */
2451    if ( load_flags & FT_LOAD_SBITS_ONLY )
2452      return CFF_Err_Invalid_Argument;
2453
2454    /* if we have a CID subfont, use its matrix (which has already */
2455    /* been multiplied with the root matrix)                       */
2456
2457    /* this scaling is only relevant if the PS hinter isn't active */
2458    if ( cff->num_subfonts )
2459    {
2460      FT_Byte  fd_index = cff_fd_select_get( &cff->fd_select,
2461                                             glyph_index );
2462
2463      FT_Int  top_upm = cff->top_font.font_dict.units_per_em;
2464      FT_Int  sub_upm = cff->subfonts[fd_index]->font_dict.units_per_em;
2465
2466
2467      font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix;
2468      font_offset = cff->subfonts[fd_index]->font_dict.font_offset;
2469
2470      if ( top_upm != sub_upm )
2471      {
2472        glyph->x_scale = FT_MulDiv( glyph->x_scale, top_upm, sub_upm );
2473        glyph->y_scale = FT_MulDiv( glyph->y_scale, top_upm, sub_upm );
2474
2475        force_scaling = TRUE;
2476      }
2477    }
2478    else
2479    {
2480      font_matrix = cff->top_font.font_dict.font_matrix;
2481      font_offset = cff->top_font.font_dict.font_offset;
2482    }
2483
2484    glyph->root.outline.n_points   = 0;
2485    glyph->root.outline.n_contours = 0;
2486
2487    hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE   ) == 0 &&
2488                       ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
2489
2490    glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;  /* by default */
2491
2492    {
2493      FT_Byte*  charstring;
2494      FT_ULong  charstring_len;
2495
2496
2497      cff_decoder_init( &decoder, face, size, glyph, hinting,
2498                        FT_LOAD_TARGET_MODE( load_flags ) );
2499
2500      if ((load_flags & FT_LOAD_ADVANCE_ONLY) != 0)
2501        cff_decoder_set_width_only( &decoder );
2502
2503      decoder.builder.no_recurse =
2504        (FT_Bool)( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 );
2505
2506      /* now load the unscaled outline */
2507      error = cff_get_glyph_data( face, glyph_index,
2508                                  &charstring, &charstring_len );
2509      if ( !error )
2510      {
2511        error = cff_decoder_prepare( &decoder, size, glyph_index );
2512        if ( !error )
2513        {
2514          error = cff_decoder_parse_charstrings( &decoder,
2515                                                 charstring,
2516                                                 charstring_len );
2517
2518          cff_free_glyph_data( face, &charstring, charstring_len );
2519
2520
2521#ifdef FT_CONFIG_OPTION_INCREMENTAL
2522          /* Control data and length may not be available for incremental */
2523          /* fonts.                                                       */
2524          if ( face->root.internal->incremental_interface )
2525          {
2526            glyph->root.control_data = 0;
2527            glyph->root.control_len = 0;
2528          }
2529          else
2530#endif /* FT_CONFIG_OPTION_INCREMENTAL */
2531
2532          /* We set control_data and control_len if charstrings is loaded. */
2533          /* See how charstring loads at cff_index_access_element() in     */
2534          /* cffload.c.                                                    */
2535          {
2536            CFF_Index  csindex = &cff->charstrings_index;
2537
2538
2539            if ( csindex->offsets )
2540            {
2541              glyph->root.control_data = csindex->bytes +
2542                                           csindex->offsets[glyph_index] - 1;
2543              glyph->root.control_len  = charstring_len;
2544            }
2545          }
2546        }
2547      }
2548
2549      /* save new glyph tables */
2550      cff_builder_done( &decoder.builder );
2551    }
2552
2553#ifdef FT_CONFIG_OPTION_INCREMENTAL
2554
2555    /* Incremental fonts can optionally override the metrics. */
2556    if ( !error                                                              &&
2557         face->root.internal->incremental_interface                          &&
2558         face->root.internal->incremental_interface->funcs->get_glyph_metrics )
2559    {
2560      FT_Incremental_MetricsRec  metrics;
2561
2562
2563      metrics.bearing_x = decoder.builder.left_bearing.x;
2564      metrics.bearing_y = decoder.builder.left_bearing.y;
2565      metrics.advance   = decoder.builder.advance.x;
2566      error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
2567                face->root.internal->incremental_interface->object,
2568                glyph_index, FALSE, &metrics );
2569      decoder.builder.left_bearing.x = metrics.bearing_x;
2570      decoder.builder.left_bearing.y = metrics.bearing_y;
2571      decoder.builder.advance.x      = metrics.advance;
2572      decoder.builder.advance.y      = 0;
2573    }
2574
2575#endif /* FT_CONFIG_OPTION_INCREMENTAL */
2576
2577    if ( !error )
2578    {
2579      /* Now, set the metrics -- this is rather simple, as   */
2580      /* the left side bearing is the xMin, and the top side */
2581      /* bearing the yMax.                                   */
2582
2583      /* For composite glyphs, return only left side bearing and */
2584      /* advance width.                                          */
2585      if ( load_flags & FT_LOAD_NO_RECURSE )
2586      {
2587        FT_Slot_Internal  internal = glyph->root.internal;
2588
2589
2590        glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
2591        glyph->root.metrics.horiAdvance  = decoder.glyph_width;
2592        internal->glyph_matrix           = font_matrix;
2593        internal->glyph_delta            = font_offset;
2594        internal->glyph_transformed      = 1;
2595      }
2596      else
2597      {
2598        FT_BBox            cbox;
2599        FT_Glyph_Metrics*  metrics = &glyph->root.metrics;
2600        FT_Vector          advance;
2601        FT_Bool            has_vertical_info;
2602
2603
2604        /* copy the _unscaled_ advance width */
2605        metrics->horiAdvance                    = decoder.glyph_width;
2606        glyph->root.linearHoriAdvance           = decoder.glyph_width;
2607        glyph->root.internal->glyph_transformed = 0;
2608
2609        has_vertical_info = FT_BOOL( face->vertical_info                   &&
2610                                     face->vertical.number_Of_VMetrics > 0 &&
2611                                     face->vertical.long_metrics != 0 );
2612
2613        /* get the vertical metrics from the vtmx table if we have one */
2614        if ( has_vertical_info )
2615        {
2616          FT_Short   vertBearingY = 0;
2617          FT_UShort  vertAdvance  = 0;
2618
2619
2620          ( (SFNT_Service)face->sfnt )->get_metrics( face, 1,
2621                                                     glyph_index,
2622                                                     &vertBearingY,
2623                                                     &vertAdvance );
2624          metrics->vertBearingY = vertBearingY;
2625          metrics->vertAdvance  = vertAdvance;
2626        }
2627        else
2628        {
2629          /* make up vertical ones */
2630          if ( face->os2.version != 0xFFFFU )
2631            metrics->vertAdvance = (FT_Pos)( face->os2.sTypoAscender -
2632                                             face->os2.sTypoDescender );
2633          else
2634            metrics->vertAdvance = (FT_Pos)( face->horizontal.Ascender -
2635                                             face->horizontal.Descender );
2636        }
2637
2638        glyph->root.linearVertAdvance = metrics->vertAdvance;
2639
2640        glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;
2641
2642        glyph->root.outline.flags = 0;
2643        if ( size && size->root.metrics.y_ppem < 24 )
2644          glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION;
2645
2646        glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL;
2647
2648        /* apply the font matrix -- `xx' has already been normalized */
2649        if ( !( font_matrix.yy == 0x10000L &&
2650                font_matrix.xy == 0        &&
2651                font_matrix.yx == 0        ) )
2652          FT_Outline_Transform( &glyph->root.outline, &font_matrix );
2653
2654        if ( !( font_offset.x == 0 &&
2655                font_offset.y == 0 ) )
2656          FT_Outline_Translate( &glyph->root.outline,
2657                                font_offset.x, font_offset.y );
2658
2659        advance.x = metrics->horiAdvance;
2660        advance.y = 0;
2661        FT_Vector_Transform( &advance, &font_matrix );
2662        metrics->horiAdvance = advance.x + font_offset.x;
2663
2664        advance.x = 0;
2665        advance.y = metrics->vertAdvance;
2666        FT_Vector_Transform( &advance, &font_matrix );
2667        metrics->vertAdvance = advance.y + font_offset.y;
2668
2669        if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling )
2670        {
2671          /* scale the outline and the metrics */
2672          FT_Int       n;
2673          FT_Outline*  cur     = &glyph->root.outline;
2674          FT_Vector*   vec     = cur->points;
2675          FT_Fixed     x_scale = glyph->x_scale;
2676          FT_Fixed     y_scale = glyph->y_scale;
2677
2678
2679          /* First of all, scale the points */
2680          if ( !hinting || !decoder.builder.hints_funcs )
2681            for ( n = cur->n_points; n > 0; n--, vec++ )
2682            {
2683              vec->x = FT_MulFix( vec->x, x_scale );
2684              vec->y = FT_MulFix( vec->y, y_scale );
2685            }
2686
2687          /* Then scale the metrics */
2688          metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
2689          metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
2690        }
2691
2692        /* compute the other metrics */
2693        FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
2694
2695        metrics->width  = cbox.xMax - cbox.xMin;
2696        metrics->height = cbox.yMax - cbox.yMin;
2697
2698        metrics->horiBearingX = cbox.xMin;
2699        metrics->horiBearingY = cbox.yMax;
2700
2701        if ( has_vertical_info )
2702          metrics->vertBearingX = -metrics->width / 2;
2703        else
2704          ft_synthesize_vertical_metrics( metrics,
2705                                          metrics->vertAdvance );
2706      }
2707    }
2708
2709    return error;
2710  }
2711
2712
2713/* END */
2714