Home | History | Annotate | Download | only in psaux
      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 FT_INTERNAL_DEBUG_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 FT_MULTIPLE_MASTERS_H
     49 #include FT_SERVICE_MULTIPLE_MASTERS_H
     50 #endif
     51 
     52 #include FT_SERVICE_CFF_TABLE_LOAD_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
     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
     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
    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
    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
    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
    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
    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
    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
    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 )
    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   = 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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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   = charstring + len;
    701     buf->ptr   = buf->start;
    702 
    703     return FT_Err_Ok;
    704   }
    705 
    706 
    707   FT_LOCAL_DEF( void )
    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 )
    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 )
    767   cf2_freeT1SeacComponent( PS_Decoder*  decoder,
    768                            CF2_Buffer   buf )
    769   {
    770     T1_Face  face;
    771     FT_Data  data;
    772 
    773 
    774     FT_ASSERT( decoder );
    775 
    776 #ifdef FT_CONFIG_OPTION_INCREMENTAL
    777     face = (T1_Face)decoder->builder.face;
    778 
    779     data.pointer = buf->start;
    780     data.length  = (FT_Int)( buf->end - buf->start );
    781 
    782     if ( face->root.internal->incremental_interface )
    783       face->root.internal->incremental_interface->funcs->free_glyph_data(
    784         face->root.internal->incremental_interface->object,
    785         &data );
    786 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
    787   }
    788 
    789 
    790   FT_LOCAL_DEF( CF2_Int )
    791   cf2_initLocalRegionBuffer( PS_Decoder*  decoder,
    792                              CF2_Int      subrNum,
    793                              CF2_Buffer   buf )
    794   {
    795     CF2_UInt  idx;
    796 
    797 
    798     FT_ASSERT( decoder );
    799 
    800     FT_ZERO( buf );
    801 
    802     idx = (CF2_UInt)( subrNum + decoder->locals_bias );
    803     if ( idx >= decoder->num_locals )
    804       return TRUE;     /* error */
    805 
    806     FT_ASSERT( decoder->locals );
    807 
    808     buf->start = decoder->locals[idx];
    809 
    810     if ( decoder->builder.is_t1 )
    811     {
    812       /* The Type 1 driver stores subroutines without the seed bytes. */
    813       /* The CID driver stores subroutines with seed bytes.  This     */
    814       /* case is taken care of when decoder->subrs_len == 0.          */
    815       if ( decoder->locals_len )
    816         buf->end = buf->start + decoder->locals_len[idx];
    817       else
    818       {
    819         /* We are using subroutines from a CID font.  We must adjust */
    820         /* for the seed bytes.                                       */
    821         buf->start += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
    822         buf->end    = decoder->locals[idx + 1];
    823       }
    824 
    825       if ( !buf->start )
    826       {
    827         FT_ERROR(( "cf2_initLocalRegionBuffer (Type 1 mode):"
    828                    " invoking empty subrs\n" ));
    829       }
    830     }
    831     else
    832     {
    833       buf->end = decoder->locals[idx + 1];
    834     }
    835 
    836     buf->ptr = buf->start;
    837 
    838     return FALSE;      /* success */
    839   }
    840 
    841 
    842   FT_LOCAL_DEF( CF2_Fixed )
    843   cf2_getDefaultWidthX( PS_Decoder*  decoder )
    844   {
    845     FT_ASSERT( decoder && decoder->current_subfont );
    846 
    847     return cf2_intToFixed(
    848              decoder->current_subfont->private_dict.default_width );
    849   }
    850 
    851 
    852   FT_LOCAL_DEF( CF2_Fixed )
    853   cf2_getNominalWidthX( PS_Decoder*  decoder )
    854   {
    855     FT_ASSERT( decoder && decoder->current_subfont );
    856 
    857     return cf2_intToFixed(
    858              decoder->current_subfont->private_dict.nominal_width );
    859   }
    860 
    861 
    862   FT_LOCAL_DEF( void )
    863   cf2_outline_reset( CF2_Outline  outline )
    864   {
    865     PS_Decoder*  decoder = outline->decoder;
    866 
    867 
    868     FT_ASSERT( decoder );
    869 
    870     outline->root.windingMomentum = 0;
    871 
    872     FT_GlyphLoader_Rewind( decoder->builder.loader );
    873   }
    874 
    875 
    876   FT_LOCAL_DEF( void )
    877   cf2_outline_close( CF2_Outline  outline )
    878   {
    879     PS_Decoder*  decoder = outline->decoder;
    880 
    881 
    882     FT_ASSERT( decoder );
    883 
    884     ps_builder_close_contour( &decoder->builder );
    885 
    886     FT_GlyphLoader_Add( decoder->builder.loader );
    887   }
    888 
    889 
    890 /* END */
    891