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