• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  *
3  * psft.c
4  *
5  *   FreeType Glue Component to Adobe's Interpreter (body).
6  *
7  * Copyright 2013-2014 Adobe Systems Incorporated.
8  *
9  * This software, and all works of authorship, whether in source or
10  * object code form as indicated by the copyright notice(s) included
11  * herein (collectively, the "Work") is made available, and may only be
12  * used, modified, and distributed under the FreeType Project License,
13  * LICENSE.TXT.  Additionally, subject to the terms and conditions of the
14  * FreeType Project License, each contributor to the Work hereby grants
15  * to any individual or legal entity exercising permissions granted by
16  * the FreeType Project License and this section (hereafter, "You" or
17  * "Your") a perpetual, worldwide, non-exclusive, no-charge,
18  * royalty-free, irrevocable (except as stated in this section) patent
19  * license to make, have made, use, offer to sell, sell, import, and
20  * otherwise transfer the Work, where such license applies only to those
21  * patent claims licensable by such contributor that are necessarily
22  * infringed by their contribution(s) alone or by combination of their
23  * contribution(s) with the Work to which such contribution(s) was
24  * submitted.  If You institute patent litigation against any entity
25  * (including a cross-claim or counterclaim in a lawsuit) alleging that
26  * the Work or a contribution incorporated within the Work constitutes
27  * direct or contributory patent infringement, then any patent licenses
28  * granted to You under this License for that Work shall terminate as of
29  * the date such litigation is filed.
30  *
31  * By using, modifying, or distributing the Work you indicate that you
32  * have read and understood the terms and conditions of the
33  * FreeType Project License as well as those provided in this section,
34  * and you accept them fully.
35  *
36  */
37 
38 
39 #include "psft.h"
40 #include <freetype/internal/ftdebug.h>
41 
42 #include "psfont.h"
43 #include "pserror.h"
44 #include "psobjs.h"
45 #include "cffdecode.h"
46 
47 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
48 #include <freetype/ftmm.h>
49 #include <freetype/internal/services/svmm.h>
50 #endif
51 
52 #include <freetype/internal/services/svcfftl.h>
53 
54 
55 #define CF2_MAX_SIZE  cf2_intToFixed( 2000 )    /* max ppem */
56 
57 
58   /*
59    * This check should avoid most internal overflow cases.  Clients should
60    * generally respond to `Glyph_Too_Big' by getting a glyph outline
61    * at EM size, scaling it and filling it as a graphics operation.
62    *
63    */
64   static FT_Error
cf2_checkTransform(const CF2_Matrix * transform,CF2_Int unitsPerEm)65   cf2_checkTransform( const CF2_Matrix*  transform,
66                       CF2_Int            unitsPerEm )
67   {
68     CF2_Fixed  maxScale;
69 
70 
71     if ( transform->a <= 0 || transform->d <= 0 )
72       return FT_THROW( Invalid_Size_Handle );
73 
74     FT_ASSERT( unitsPerEm > 0 );
75     FT_ASSERT( transform->b == 0 && transform->c == 0 );
76     FT_ASSERT( transform->tx == 0 && transform->ty == 0 );
77 
78     if ( unitsPerEm > 0x7FFF )
79       return FT_THROW( Glyph_Too_Big );
80 
81     maxScale = FT_DivFix( CF2_MAX_SIZE, cf2_intToFixed( unitsPerEm ) );
82 
83     if ( transform->a > maxScale || transform->d > maxScale )
84       return FT_THROW( Glyph_Too_Big );
85 
86     return FT_Err_Ok;
87   }
88 
89 
90   static void
cf2_setGlyphWidth(CF2_Outline outline,CF2_Fixed width)91   cf2_setGlyphWidth( CF2_Outline  outline,
92                      CF2_Fixed    width )
93   {
94     PS_Decoder*  decoder = outline->decoder;
95 
96 
97     FT_ASSERT( decoder );
98 
99     if ( !decoder->builder.is_t1 )
100       *decoder->glyph_width = cf2_fixedToInt( width );
101   }
102 
103 
104   /* Clean up font instance. */
105   static void
cf2_free_instance(void * ptr)106   cf2_free_instance( void*  ptr )
107   {
108     CF2_Font  font = (CF2_Font)ptr;
109 
110 
111     if ( font )
112     {
113       FT_Memory  memory = font->memory;
114 
115 
116       FT_FREE( font->blend.lastNDV );
117       FT_FREE( font->blend.BV );
118     }
119   }
120 
121 
122   /*********************************************
123    *
124    * functions for handling client outline;
125    * FreeType uses coordinates in 26.6 format
126    *
127    */
128 
129   static void
cf2_builder_moveTo(CF2_OutlineCallbacks callbacks,const CF2_CallbackParams params)130   cf2_builder_moveTo( CF2_OutlineCallbacks      callbacks,
131                       const CF2_CallbackParams  params )
132   {
133     /* downcast the object pointer */
134     CF2_Outline  outline = (CF2_Outline)callbacks;
135     PS_Builder*  builder;
136 
137     (void)params;        /* only used in debug mode */
138 
139 
140     FT_ASSERT( outline && outline->decoder );
141     FT_ASSERT( params->op == CF2_PathOpMoveTo );
142 
143     builder = &outline->decoder->builder;
144 
145     /* note: two successive moves simply close the contour twice */
146     ps_builder_close_contour( builder );
147     builder->path_begun = 0;
148   }
149 
150 
151   static void
cf2_builder_lineTo(CF2_OutlineCallbacks callbacks,const CF2_CallbackParams params)152   cf2_builder_lineTo( CF2_OutlineCallbacks      callbacks,
153                       const CF2_CallbackParams  params )
154   {
155     FT_Error  error;
156 
157     /* downcast the object pointer */
158     CF2_Outline  outline = (CF2_Outline)callbacks;
159     PS_Builder*  builder;
160 
161 
162     FT_ASSERT( outline && outline->decoder );
163     FT_ASSERT( params->op == CF2_PathOpLineTo );
164 
165     builder = &outline->decoder->builder;
166 
167     if ( !builder->path_begun )
168     {
169       /* record the move before the line; also check points and set */
170       /* `path_begun'                                               */
171       error = ps_builder_start_point( builder,
172                                       params->pt0.x,
173                                       params->pt0.y );
174       if ( error )
175       {
176         if ( !*callbacks->error )
177           *callbacks->error =  error;
178         return;
179       }
180     }
181 
182     /* `ps_builder_add_point1' includes a check_points call for one point */
183     error = ps_builder_add_point1( builder,
184                                    params->pt1.x,
185                                    params->pt1.y );
186     if ( error )
187     {
188       if ( !*callbacks->error )
189         *callbacks->error =  error;
190       return;
191     }
192   }
193 
194 
195   static void
cf2_builder_cubeTo(CF2_OutlineCallbacks callbacks,const CF2_CallbackParams params)196   cf2_builder_cubeTo( CF2_OutlineCallbacks      callbacks,
197                       const CF2_CallbackParams  params )
198   {
199     FT_Error  error;
200 
201     /* downcast the object pointer */
202     CF2_Outline  outline = (CF2_Outline)callbacks;
203     PS_Builder*  builder;
204 
205 
206     FT_ASSERT( outline && outline->decoder );
207     FT_ASSERT( params->op == CF2_PathOpCubeTo );
208 
209     builder = &outline->decoder->builder;
210 
211     if ( !builder->path_begun )
212     {
213       /* record the move before the line; also check points and set */
214       /* `path_begun'                                               */
215       error = ps_builder_start_point( builder,
216                                       params->pt0.x,
217                                       params->pt0.y );
218       if ( error )
219       {
220         if ( !*callbacks->error )
221           *callbacks->error =  error;
222         return;
223       }
224     }
225 
226     /* prepare room for 3 points: 2 off-curve, 1 on-curve */
227     error = ps_builder_check_points( builder, 3 );
228     if ( error )
229     {
230       if ( !*callbacks->error )
231         *callbacks->error =  error;
232       return;
233     }
234 
235     ps_builder_add_point( builder,
236                           params->pt1.x,
237                           params->pt1.y, 0 );
238     ps_builder_add_point( builder,
239                           params->pt2.x,
240                           params->pt2.y, 0 );
241     ps_builder_add_point( builder,
242                           params->pt3.x,
243                           params->pt3.y, 1 );
244   }
245 
246 
247   static void
cf2_outline_init(CF2_Outline outline,FT_Memory memory,FT_Error * error)248   cf2_outline_init( CF2_Outline  outline,
249                     FT_Memory    memory,
250                     FT_Error*    error )
251   {
252     FT_ZERO( outline );
253 
254     outline->root.memory = memory;
255     outline->root.error  = error;
256 
257     outline->root.moveTo = cf2_builder_moveTo;
258     outline->root.lineTo = cf2_builder_lineTo;
259     outline->root.cubeTo = cf2_builder_cubeTo;
260   }
261 
262 
263   /* get scaling and hint flag from GlyphSlot */
264   static void
cf2_getScaleAndHintFlag(PS_Decoder * decoder,CF2_Fixed * x_scale,CF2_Fixed * y_scale,FT_Bool * hinted,FT_Bool * scaled)265   cf2_getScaleAndHintFlag( PS_Decoder*  decoder,
266                            CF2_Fixed*   x_scale,
267                            CF2_Fixed*   y_scale,
268                            FT_Bool*     hinted,
269                            FT_Bool*     scaled )
270   {
271     FT_ASSERT( decoder && decoder->builder.glyph );
272 
273     /* note: FreeType scale includes a factor of 64 */
274     *hinted = decoder->builder.glyph->hint;
275     *scaled = decoder->builder.glyph->scaled;
276 
277     if ( *hinted )
278     {
279       *x_scale = ADD_INT32( decoder->builder.glyph->x_scale, 32 ) / 64;
280       *y_scale = ADD_INT32( decoder->builder.glyph->y_scale, 32 ) / 64;
281     }
282     else
283     {
284       /* for unhinted outlines, `cff_slot_load' does the scaling, */
285       /* thus render at `unity' scale                             */
286 
287       *x_scale = 0x0400;   /* 1/64 as 16.16 */
288       *y_scale = 0x0400;
289     }
290   }
291 
292 
293   /* get units per em from `FT_Face' */
294   /* TODO: should handle font matrix concatenation? */
295   static FT_UShort
cf2_getUnitsPerEm(PS_Decoder * decoder)296   cf2_getUnitsPerEm( PS_Decoder*  decoder )
297   {
298     FT_ASSERT( decoder && decoder->builder.face );
299 
300     return decoder->builder.face->units_per_EM;
301   }
302 
303 
304   /* Main entry point: Render one glyph. */
305   FT_LOCAL_DEF( FT_Error )
cf2_decoder_parse_charstrings(PS_Decoder * decoder,FT_Byte * charstring_base,FT_ULong charstring_len)306   cf2_decoder_parse_charstrings( PS_Decoder*  decoder,
307                                  FT_Byte*     charstring_base,
308                                  FT_ULong     charstring_len )
309   {
310     FT_Memory  memory;
311     FT_Error   error = FT_Err_Ok;
312     CF2_Font   font;
313 
314     FT_Bool  is_t1 = decoder->builder.is_t1;
315 
316 
317     FT_ASSERT( decoder &&
318                ( is_t1 || decoder->cff ) );
319 
320     if ( is_t1 && !decoder->current_subfont )
321     {
322       FT_ERROR(( "cf2_decoder_parse_charstrings (Type 1): "
323                  "SubFont missing. Use `t1_make_subfont' first\n" ));
324       return FT_THROW( Invalid_Table );
325     }
326 
327     memory = decoder->builder.memory;
328 
329     /* CF2 data is saved here across glyphs */
330     font = (CF2_Font)decoder->cf2_instance->data;
331 
332     /* on first glyph, allocate instance structure */
333     if ( !decoder->cf2_instance->data )
334     {
335       decoder->cf2_instance->finalizer =
336         (FT_Generic_Finalizer)cf2_free_instance;
337 
338       if ( FT_ALLOC( decoder->cf2_instance->data,
339                      sizeof ( CF2_FontRec ) ) )
340         return FT_THROW( Out_Of_Memory );
341 
342       font = (CF2_Font)decoder->cf2_instance->data;
343 
344       font->memory = memory;
345 
346       if ( !is_t1 )
347         font->cffload = (FT_Service_CFFLoad)decoder->cff->cffload;
348 
349       /* initialize a client outline, to be shared by each glyph rendered */
350       cf2_outline_init( &font->outline, font->memory, &font->error );
351     }
352 
353     /* save decoder; it is a stack variable and will be different on each */
354     /* call                                                               */
355     font->decoder         = decoder;
356     font->outline.decoder = decoder;
357 
358     {
359       /* build parameters for Adobe engine */
360 
361       PS_Builder*  builder = &decoder->builder;
362       PS_Driver    driver  = (PS_Driver)FT_FACE_DRIVER( builder->face );
363 
364       FT_Bool  no_stem_darkening_driver =
365                  driver->no_stem_darkening;
366       FT_Char  no_stem_darkening_font =
367                  builder->face->internal->no_stem_darkening;
368 
369       /* local error */
370       FT_Error       error2 = FT_Err_Ok;
371       CF2_BufferRec  buf;
372       CF2_Matrix     transform;
373       CF2_F16Dot16   glyphWidth;
374 
375       FT_Bool  hinted;
376       FT_Bool  scaled;
377 
378 
379       /* FreeType has already looked up the GID; convert to         */
380       /* `RegionBuffer', assuming that the input has been validated */
381       FT_ASSERT( charstring_base + charstring_len >= charstring_base );
382 
383       FT_ZERO( &buf );
384       buf.start =
385       buf.ptr   = charstring_base;
386       buf.end   = FT_OFFSET( charstring_base, charstring_len );
387 
388       FT_ZERO( &transform );
389 
390       cf2_getScaleAndHintFlag( decoder,
391                                &transform.a,
392                                &transform.d,
393                                &hinted,
394                                &scaled );
395 
396       if ( is_t1 )
397         font->isCFF2 = FALSE;
398       else
399       {
400         /* copy isCFF2 boolean from TT_Face to CF2_Font */
401         font->isCFF2 = ((TT_Face)builder->face)->is_cff2;
402       }
403       font->isT1 = is_t1;
404 
405       font->renderingFlags = 0;
406       if ( hinted )
407         font->renderingFlags |= CF2_FlagsHinted;
408       if ( scaled && ( !no_stem_darkening_font        ||
409                        ( no_stem_darkening_font < 0 &&
410                          !no_stem_darkening_driver  ) ) )
411         font->renderingFlags |= CF2_FlagsDarkened;
412 
413       font->darkenParams[0] = driver->darken_params[0];
414       font->darkenParams[1] = driver->darken_params[1];
415       font->darkenParams[2] = driver->darken_params[2];
416       font->darkenParams[3] = driver->darken_params[3];
417       font->darkenParams[4] = driver->darken_params[4];
418       font->darkenParams[5] = driver->darken_params[5];
419       font->darkenParams[6] = driver->darken_params[6];
420       font->darkenParams[7] = driver->darken_params[7];
421 
422       /* now get an outline for this glyph;      */
423       /* also get units per em to validate scale */
424       font->unitsPerEm = (CF2_Int)cf2_getUnitsPerEm( decoder );
425 
426       if ( scaled )
427       {
428         error2 = cf2_checkTransform( &transform, font->unitsPerEm );
429         if ( error2 )
430           return error2;
431       }
432 
433       error2 = cf2_getGlyphOutline( font, &buf, &transform, &glyphWidth );
434       if ( error2 )
435         return FT_ERR( Invalid_File_Format );
436 
437       cf2_setGlyphWidth( &font->outline, glyphWidth );
438 
439       return FT_Err_Ok;
440     }
441   }
442 
443 
444   /* get pointer to current FreeType subfont (based on current glyphID) */
445   FT_LOCAL_DEF( CFF_SubFont )
cf2_getSubfont(PS_Decoder * decoder)446   cf2_getSubfont( PS_Decoder*  decoder )
447   {
448     FT_ASSERT( decoder && decoder->current_subfont );
449 
450     return decoder->current_subfont;
451   }
452 
453 
454   /* get pointer to VStore structure */
455   FT_LOCAL_DEF( CFF_VStore )
cf2_getVStore(PS_Decoder * decoder)456   cf2_getVStore( PS_Decoder*  decoder )
457   {
458     FT_ASSERT( decoder && decoder->cff );
459 
460     return &decoder->cff->vstore;
461   }
462 
463 
464   /* get maxstack value from CFF2 Top DICT */
465   FT_LOCAL_DEF( FT_UInt )
cf2_getMaxstack(PS_Decoder * decoder)466   cf2_getMaxstack( PS_Decoder*  decoder )
467   {
468     FT_ASSERT( decoder && decoder->cff );
469 
470     return decoder->cff->top_font.font_dict.maxstack;
471   }
472 
473 
474 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
475   /* Get normalized design vector for current render request; */
476   /* return pointer and length.                               */
477   /*                                                          */
478   /* Note: Uses FT_Fixed not CF2_Fixed for the vector.        */
479   FT_LOCAL_DEF( FT_Error )
cf2_getNormalizedVector(PS_Decoder * decoder,CF2_UInt * len,FT_Fixed ** vec)480   cf2_getNormalizedVector( PS_Decoder*  decoder,
481                            CF2_UInt     *len,
482                            FT_Fixed*    *vec )
483   {
484     TT_Face                  face;
485     FT_Service_MultiMasters  mm;
486 
487 
488     FT_ASSERT( decoder && decoder->builder.face );
489     FT_ASSERT( vec && len );
490     FT_ASSERT( !decoder->builder.is_t1 );
491 
492     face = (TT_Face)decoder->builder.face;
493     mm   = (FT_Service_MultiMasters)face->mm;
494 
495     return mm->get_var_blend( FT_FACE( face ), len, NULL, vec, NULL );
496   }
497 #endif
498 
499 
500   /* get `y_ppem' from `CFF_Size' */
501   FT_LOCAL_DEF( CF2_Fixed )
cf2_getPpemY(PS_Decoder * decoder)502   cf2_getPpemY( PS_Decoder*  decoder )
503   {
504     FT_ASSERT( decoder                     &&
505                decoder->builder.face       &&
506                decoder->builder.face->size );
507 
508     /*
509      * Note that `y_ppem' can be zero if there wasn't a call to
510      * `FT_Set_Char_Size' or something similar.  However, this isn't a
511      * problem since we come to this place in the code only if
512      * FT_LOAD_NO_SCALE is set (the other case gets caught by
513      * `cf2_checkTransform').  The ppem value is needed to compute the stem
514      * darkening, which is disabled for getting the unscaled outline.
515      *
516      */
517     return cf2_intToFixed(
518              decoder->builder.face->size->metrics.y_ppem );
519   }
520 
521 
522   /* get standard stem widths for the current subfont; */
523   /* FreeType stores these as integer font units       */
524   /* (note: variable names seem swapped)               */
525   FT_LOCAL_DEF( CF2_Fixed )
cf2_getStdVW(PS_Decoder * decoder)526   cf2_getStdVW( PS_Decoder*  decoder )
527   {
528     FT_ASSERT( decoder && decoder->current_subfont );
529 
530     return cf2_intToFixed(
531              decoder->current_subfont->private_dict.standard_height );
532   }
533 
534 
535   FT_LOCAL_DEF( CF2_Fixed )
cf2_getStdHW(PS_Decoder * decoder)536   cf2_getStdHW( PS_Decoder*  decoder )
537   {
538     FT_ASSERT( decoder && decoder->current_subfont );
539 
540     return cf2_intToFixed(
541              decoder->current_subfont->private_dict.standard_width );
542   }
543 
544 
545   /* note: FreeType stores 1000 times the actual value for `BlueScale' */
546   FT_LOCAL_DEF( void )
cf2_getBlueMetrics(PS_Decoder * decoder,CF2_Fixed * blueScale,CF2_Fixed * blueShift,CF2_Fixed * blueFuzz)547   cf2_getBlueMetrics( PS_Decoder*  decoder,
548                       CF2_Fixed*   blueScale,
549                       CF2_Fixed*   blueShift,
550                       CF2_Fixed*   blueFuzz )
551   {
552     FT_ASSERT( decoder && decoder->current_subfont );
553 
554     *blueScale = FT_DivFix(
555                    decoder->current_subfont->private_dict.blue_scale,
556                    cf2_intToFixed( 1000 ) );
557     *blueShift = cf2_intToFixed(
558                    decoder->current_subfont->private_dict.blue_shift );
559     *blueFuzz  = cf2_intToFixed(
560                    decoder->current_subfont->private_dict.blue_fuzz );
561   }
562 
563 
564   /* get blue values counts and arrays; the FreeType parser has validated */
565   /* the counts and verified that each is an even number                  */
566   FT_LOCAL_DEF( void )
cf2_getBlueValues(PS_Decoder * decoder,size_t * count,FT_Pos ** data)567   cf2_getBlueValues( PS_Decoder*  decoder,
568                      size_t*      count,
569                      FT_Pos*     *data )
570   {
571     FT_ASSERT( decoder && decoder->current_subfont );
572 
573     *count = decoder->current_subfont->private_dict.num_blue_values;
574     *data  = (FT_Pos*)
575                &decoder->current_subfont->private_dict.blue_values;
576   }
577 
578 
579   FT_LOCAL_DEF( void )
cf2_getOtherBlues(PS_Decoder * decoder,size_t * count,FT_Pos ** data)580   cf2_getOtherBlues( PS_Decoder*  decoder,
581                      size_t*      count,
582                      FT_Pos*     *data )
583   {
584     FT_ASSERT( decoder && decoder->current_subfont );
585 
586     *count = decoder->current_subfont->private_dict.num_other_blues;
587     *data  = (FT_Pos*)
588                &decoder->current_subfont->private_dict.other_blues;
589   }
590 
591 
592   FT_LOCAL_DEF( void )
cf2_getFamilyBlues(PS_Decoder * decoder,size_t * count,FT_Pos ** data)593   cf2_getFamilyBlues( PS_Decoder*  decoder,
594                       size_t*      count,
595                       FT_Pos*     *data )
596   {
597     FT_ASSERT( decoder && decoder->current_subfont );
598 
599     *count = decoder->current_subfont->private_dict.num_family_blues;
600     *data  = (FT_Pos*)
601                &decoder->current_subfont->private_dict.family_blues;
602   }
603 
604 
605   FT_LOCAL_DEF( void )
cf2_getFamilyOtherBlues(PS_Decoder * decoder,size_t * count,FT_Pos ** data)606   cf2_getFamilyOtherBlues( PS_Decoder*  decoder,
607                            size_t*      count,
608                            FT_Pos*     *data )
609   {
610     FT_ASSERT( decoder && decoder->current_subfont );
611 
612     *count = decoder->current_subfont->private_dict.num_family_other_blues;
613     *data  = (FT_Pos*)
614                &decoder->current_subfont->private_dict.family_other_blues;
615   }
616 
617 
618   FT_LOCAL_DEF( CF2_Int )
cf2_getLanguageGroup(PS_Decoder * decoder)619   cf2_getLanguageGroup( PS_Decoder*  decoder )
620   {
621     FT_ASSERT( decoder && decoder->current_subfont );
622 
623     return decoder->current_subfont->private_dict.language_group;
624   }
625 
626 
627   /* convert unbiased subroutine index to `CF2_Buffer' and */
628   /* return 0 on success                                   */
629   FT_LOCAL_DEF( CF2_Int )
cf2_initGlobalRegionBuffer(PS_Decoder * decoder,CF2_Int subrNum,CF2_Buffer buf)630   cf2_initGlobalRegionBuffer( PS_Decoder*  decoder,
631                               CF2_Int      subrNum,
632                               CF2_Buffer   buf )
633   {
634     CF2_UInt  idx;
635 
636 
637     FT_ASSERT( decoder );
638 
639     FT_ZERO( buf );
640 
641     idx = (CF2_UInt)( subrNum + decoder->globals_bias );
642     if ( idx >= decoder->num_globals )
643       return TRUE;     /* error */
644 
645     FT_ASSERT( decoder->globals );
646 
647     buf->start =
648     buf->ptr   = decoder->globals[idx];
649     buf->end   = decoder->globals[idx + 1];
650 
651     return FALSE;      /* success */
652   }
653 
654 
655   /* convert AdobeStandardEncoding code to CF2_Buffer; */
656   /* used for seac component                           */
657   FT_LOCAL_DEF( FT_Error )
cf2_getSeacComponent(PS_Decoder * decoder,CF2_Int code,CF2_Buffer buf)658   cf2_getSeacComponent( PS_Decoder*  decoder,
659                         CF2_Int      code,
660                         CF2_Buffer   buf )
661   {
662     CF2_Int   gid;
663     FT_Byte*  charstring;
664     FT_ULong  len;
665     FT_Error  error;
666 
667 
668     FT_ASSERT( decoder );
669     FT_ASSERT( !decoder->builder.is_t1 );
670 
671     FT_ZERO( buf );
672 
673 #ifdef FT_CONFIG_OPTION_INCREMENTAL
674     /* Incremental fonts don't necessarily have valid charsets.        */
675     /* They use the character code, not the glyph index, in this case. */
676     if ( decoder->builder.face->internal->incremental_interface )
677       gid = code;
678     else
679 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
680     {
681       gid = cff_lookup_glyph_by_stdcharcode( decoder->cff, code );
682       if ( gid < 0 )
683         return FT_THROW( Invalid_Glyph_Format );
684     }
685 
686     error = decoder->get_glyph_callback( (TT_Face)decoder->builder.face,
687                                          (CF2_UInt)gid,
688                                          &charstring,
689                                          &len );
690     /* TODO: for now, just pass the FreeType error through */
691     if ( error )
692       return error;
693 
694     /* assume input has been validated */
695     FT_ASSERT( charstring + len >= charstring );
696 
697     buf->start = charstring;
698     buf->end   = FT_OFFSET( charstring, len );
699     buf->ptr   = buf->start;
700 
701     return FT_Err_Ok;
702   }
703 
704 
705   FT_LOCAL_DEF( void )
cf2_freeSeacComponent(PS_Decoder * decoder,CF2_Buffer buf)706   cf2_freeSeacComponent( PS_Decoder*  decoder,
707                          CF2_Buffer   buf )
708   {
709     FT_ASSERT( decoder );
710     FT_ASSERT( !decoder->builder.is_t1 );
711 
712     decoder->free_glyph_callback( (TT_Face)decoder->builder.face,
713                                   (FT_Byte**)&buf->start,
714                                   (FT_ULong)( buf->end - buf->start ) );
715   }
716 
717 
718   FT_LOCAL_DEF( FT_Error )
cf2_getT1SeacComponent(PS_Decoder * decoder,FT_UInt glyph_index,CF2_Buffer buf)719   cf2_getT1SeacComponent( PS_Decoder*  decoder,
720                           FT_UInt      glyph_index,
721                           CF2_Buffer   buf )
722   {
723     FT_Data   glyph_data;
724     FT_Error  error = FT_Err_Ok;
725     T1_Face   face  = (T1_Face)decoder->builder.face;
726     T1_Font   type1 = &face->type1;
727 
728 #ifdef FT_CONFIG_OPTION_INCREMENTAL
729     FT_Incremental_InterfaceRec  *inc =
730       face->root.internal->incremental_interface;
731 
732 
733     /* For incremental fonts get the character data using the */
734     /* callback function.                                     */
735     if ( inc )
736       error = inc->funcs->get_glyph_data( inc->object,
737                                           glyph_index, &glyph_data );
738     else
739 #endif
740     /* For ordinary fonts get the character data stored in the face record. */
741     {
742       glyph_data.pointer = type1->charstrings[glyph_index];
743       glyph_data.length  = type1->charstrings_len[glyph_index];
744     }
745 
746     if ( !error )
747     {
748       FT_Byte*  charstring_base = (FT_Byte*)glyph_data.pointer;
749       FT_ULong  charstring_len  = glyph_data.length;
750 
751 
752       FT_ASSERT( charstring_base + charstring_len >= charstring_base );
753 
754       FT_ZERO( buf );
755       buf->start =
756       buf->ptr   = charstring_base;
757       buf->end   = charstring_base + charstring_len;
758     }
759 
760     return error;
761   }
762 
763 
764   FT_LOCAL_DEF( void )
cf2_freeT1SeacComponent(PS_Decoder * decoder,CF2_Buffer buf)765   cf2_freeT1SeacComponent( PS_Decoder*  decoder,
766                            CF2_Buffer   buf )
767   {
768 #ifdef FT_CONFIG_OPTION_INCREMENTAL
769 
770     T1_Face  face;
771     FT_Data  data;
772 
773 
774     FT_ASSERT( decoder );
775 
776     face = (T1_Face)decoder->builder.face;
777 
778     data.pointer = buf->start;
779     data.length  = (FT_UInt)( buf->end - buf->start );
780 
781     if ( face->root.internal->incremental_interface )
782       face->root.internal->incremental_interface->funcs->free_glyph_data(
783         face->root.internal->incremental_interface->object,
784         &data );
785 
786 #else /* !FT_CONFIG_OPTION_INCREMENTAL */
787 
788     FT_UNUSED( decoder );
789     FT_UNUSED( buf );
790 
791 #endif /* !FT_CONFIG_OPTION_INCREMENTAL */
792   }
793 
794 
795   FT_LOCAL_DEF( CF2_Int )
cf2_initLocalRegionBuffer(PS_Decoder * decoder,CF2_Int subrNum,CF2_Buffer buf)796   cf2_initLocalRegionBuffer( PS_Decoder*  decoder,
797                              CF2_Int      subrNum,
798                              CF2_Buffer   buf )
799   {
800     CF2_UInt  idx;
801 
802 
803     FT_ASSERT( decoder );
804 
805     FT_ZERO( buf );
806 
807     idx = (CF2_UInt)( subrNum + decoder->locals_bias );
808     if ( idx >= decoder->num_locals )
809       return TRUE;     /* error */
810 
811     FT_ASSERT( decoder->locals );
812 
813     buf->start = decoder->locals[idx];
814 
815     if ( decoder->builder.is_t1 )
816     {
817       /* The Type 1 driver stores subroutines without the seed bytes. */
818       /* The CID driver stores subroutines with seed bytes.  This     */
819       /* case is taken care of when decoder->subrs_len == 0.          */
820       if ( decoder->locals_len )
821         buf->end = FT_OFFSET( buf->start, decoder->locals_len[idx] );
822       else
823       {
824         /* We are using subroutines from a CID font.  We must adjust */
825         /* for the seed bytes.                                       */
826         buf->start += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
827         buf->end    = decoder->locals[idx + 1];
828       }
829 
830       if ( !buf->start )
831       {
832         FT_ERROR(( "cf2_initLocalRegionBuffer (Type 1 mode):"
833                    " invoking empty subrs\n" ));
834       }
835     }
836     else
837     {
838       buf->end = decoder->locals[idx + 1];
839     }
840 
841     buf->ptr = buf->start;
842 
843     return FALSE;      /* success */
844   }
845 
846 
847   FT_LOCAL_DEF( CF2_Fixed )
cf2_getDefaultWidthX(PS_Decoder * decoder)848   cf2_getDefaultWidthX( PS_Decoder*  decoder )
849   {
850     FT_ASSERT( decoder && decoder->current_subfont );
851 
852     return cf2_intToFixed(
853              decoder->current_subfont->private_dict.default_width );
854   }
855 
856 
857   FT_LOCAL_DEF( CF2_Fixed )
cf2_getNominalWidthX(PS_Decoder * decoder)858   cf2_getNominalWidthX( PS_Decoder*  decoder )
859   {
860     FT_ASSERT( decoder && decoder->current_subfont );
861 
862     return cf2_intToFixed(
863              decoder->current_subfont->private_dict.nominal_width );
864   }
865 
866 
867   FT_LOCAL_DEF( void )
cf2_outline_reset(CF2_Outline outline)868   cf2_outline_reset( CF2_Outline  outline )
869   {
870     PS_Decoder*  decoder = outline->decoder;
871 
872 
873     FT_ASSERT( decoder );
874 
875     outline->root.windingMomentum = 0;
876 
877     FT_GlyphLoader_Rewind( decoder->builder.loader );
878   }
879 
880 
881   FT_LOCAL_DEF( void )
cf2_outline_close(CF2_Outline outline)882   cf2_outline_close( CF2_Outline  outline )
883   {
884     PS_Decoder*  decoder = outline->decoder;
885 
886 
887     FT_ASSERT( decoder );
888 
889     ps_builder_close_contour( &decoder->builder );
890 
891     FT_GlyphLoader_Add( decoder->builder.loader );
892   }
893 
894 
895 /* END */
896