tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

psft.c (25628B)


      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
     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
     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
    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
    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
    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
    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
    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
    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
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    567  cf2_getBlueValues( PS_Decoder*  decoder,
    568                     size_t*      count,
    569                     FT_Fixed*   *data )
    570  {
    571    FT_ASSERT( decoder && decoder->current_subfont );
    572 
    573    *count = decoder->current_subfont->private_dict.num_blue_values;
    574    *data  = (FT_Fixed*)
    575               &decoder->current_subfont->private_dict.blue_values;
    576  }
    577 
    578 
    579  FT_LOCAL_DEF( void )
    580  cf2_getOtherBlues( PS_Decoder*  decoder,
    581                     size_t*      count,
    582                     FT_Fixed*   *data )
    583  {
    584    FT_ASSERT( decoder && decoder->current_subfont );
    585 
    586    *count = decoder->current_subfont->private_dict.num_other_blues;
    587    *data  = (FT_Fixed*)
    588               &decoder->current_subfont->private_dict.other_blues;
    589  }
    590 
    591 
    592  FT_LOCAL_DEF( void )
    593  cf2_getFamilyBlues( PS_Decoder*  decoder,
    594                      size_t*      count,
    595                      FT_Fixed*   *data )
    596  {
    597    FT_ASSERT( decoder && decoder->current_subfont );
    598 
    599    *count = decoder->current_subfont->private_dict.num_family_blues;
    600    *data  = (FT_Fixed*)
    601               &decoder->current_subfont->private_dict.family_blues;
    602  }
    603 
    604 
    605  FT_LOCAL_DEF( void )
    606  cf2_getFamilyOtherBlues( PS_Decoder*  decoder,
    607                           size_t*      count,
    608                           FT_Fixed*   *data )
    609  {
    610    FT_ASSERT( decoder && decoder->current_subfont );
    611 
    612    *count = decoder->current_subfont->private_dict.num_family_other_blues;
    613    *data  = (FT_Fixed*)
    614               &decoder->current_subfont->private_dict.family_other_blues;
    615  }
    616 
    617 
    618  FT_LOCAL_DEF( CF2_Int )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 )
    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 */