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 */