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