source: trunk/poppler/freetype2/src/cff/cffgload.c @ 251

Last change on this file since 251 was 251, checked in by Eugene Romanenko, 13 years ago

PDF plugin: freetype library updated to version 2.3.5

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