1 /****************************************************************************
   2  *
   3  * cffdrivr.c
   4  *
   5  *   OpenType font driver implementation (body).
   6  *
   7  * Copyright (C) 1996-2019 by
   8  * David Turner, Robert Wilhelm, and Werner Lemberg.
   9  *
  10  * This file is part of the FreeType project, and may only be used,
  11  * modified, and distributed under the terms of the FreeType project
  12  * license, LICENSE.TXT.  By continuing to use, modify, or distribute
  13  * this file you indicate that you have read the license and
  14  * understand and accept it fully.
  15  *
  16  */
  17 
  18 
  19 #include <ft2build.h>
  20 #include FT_FREETYPE_H
  21 #include FT_INTERNAL_DEBUG_H
  22 #include FT_INTERNAL_STREAM_H
  23 #include FT_INTERNAL_SFNT_H
  24 #include FT_INTERNAL_POSTSCRIPT_AUX_H
  25 #include FT_INTERNAL_POSTSCRIPT_PROPS_H
  26 #include FT_SERVICE_CID_H
  27 #include FT_SERVICE_POSTSCRIPT_INFO_H
  28 #include FT_SERVICE_POSTSCRIPT_NAME_H
  29 #include FT_SERVICE_TT_CMAP_H
  30 #include FT_SERVICE_CFF_TABLE_LOAD_H
  31 
  32 #include "cffdrivr.h"
  33 #include "cffgload.h"
  34 #include "cffload.h"
  35 #include "cffcmap.h"
  36 #include "cffparse.h"
  37 #include "cffobjs.h"
  38 
  39 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
  40 #include FT_SERVICE_MULTIPLE_MASTERS_H
  41 #include FT_SERVICE_METRICS_VARIATIONS_H
  42 #endif
  43 
  44 #include "cfferrs.h"
  45 
  46 #include FT_SERVICE_FONT_FORMAT_H
  47 #include FT_SERVICE_GLYPH_DICT_H
  48 #include FT_SERVICE_PROPERTIES_H
  49 #include FT_DRIVER_H
  50 
  51 
  52   /**************************************************************************
  53    *
  54    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
  55    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
  56    * messages during execution.
  57    */
  58 #undef  FT_COMPONENT
  59 #define FT_COMPONENT  cffdriver
  60 
  61 
  62   /*************************************************************************/
  63   /*************************************************************************/
  64   /*************************************************************************/
  65   /****                                                                 ****/
  66   /****                                                                 ****/
  67   /****                          F A C E S                              ****/
  68   /****                                                                 ****/
  69   /****                                                                 ****/
  70   /*************************************************************************/
  71   /*************************************************************************/
  72   /*************************************************************************/
  73 
  74 
  75   /**************************************************************************
  76    *
  77    * @Function:
  78    *   cff_get_kerning
  79    *
  80    * @Description:
  81    *   A driver method used to return the kerning vector between two
  82    *   glyphs of the same face.
  83    *
  84    * @Input:
  85    *   face ::
  86    *     A handle to the source face object.
  87    *
  88    *   left_glyph ::
  89    *     The index of the left glyph in the kern pair.
  90    *
  91    *   right_glyph ::
  92    *     The index of the right glyph in the kern pair.
  93    *
  94    * @Output:
  95    *   kerning ::
  96    *     The kerning vector.  This is in font units for
  97    *     scalable formats, and in pixels for fixed-sizes
  98    *     formats.
  99    *
 100    * @Return:
 101    *   FreeType error code.  0 means success.
 102    *
 103    * @Note:
 104    *   Only horizontal layouts (left-to-right & right-to-left) are
 105    *   supported by this function.  Other layouts, or more sophisticated
 106    *   kernings, are out of scope of this method (the basic driver
 107    *   interface is meant to be simple).
 108    *
 109    *   They can be implemented by format-specific interfaces.
 110    */
 111   FT_CALLBACK_DEF( FT_Error )
 112   cff_get_kerning( FT_Face     ttface,          /* TT_Face */
 113                    FT_UInt     left_glyph,
 114                    FT_UInt     right_glyph,
 115                    FT_Vector*  kerning )
 116   {
 117     TT_Face       face = (TT_Face)ttface;
 118     SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
 119 
 120 
 121     kerning->x = 0;
 122     kerning->y = 0;
 123 
 124     if ( sfnt )
 125       kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph );
 126 
 127     return FT_Err_Ok;
 128   }
 129 
 130 
 131   /**************************************************************************
 132    *
 133    * @Function:
 134    *   cff_glyph_load
 135    *
 136    * @Description:
 137    *   A driver method used to load a glyph within a given glyph slot.
 138    *
 139    * @Input:
 140    *   slot ::
 141    *     A handle to the target slot object where the glyph
 142    *     will be loaded.
 143    *
 144    *   size ::
 145    *     A handle to the source face size at which the glyph
 146    *     must be scaled, loaded, etc.
 147    *
 148    *   glyph_index ::
 149    *     The index of the glyph in the font file.
 150    *
 151    *   load_flags ::
 152    *     A flag indicating what to load for this glyph.  The
 153    *     FT_LOAD_??? constants can be used to control the
 154    *     glyph loading process (e.g., whether the outline
 155    *     should be scaled, whether to load bitmaps or not,
 156    *     whether to hint the outline, etc).
 157    *
 158    * @Return:
 159    *   FreeType error code.  0 means success.
 160    */
 161   FT_CALLBACK_DEF( FT_Error )
 162   cff_glyph_load( FT_GlyphSlot  cffslot,      /* CFF_GlyphSlot */
 163                   FT_Size       cffsize,      /* CFF_Size      */
 164                   FT_UInt       glyph_index,
 165                   FT_Int32      load_flags )
 166   {
 167     FT_Error       error;
 168     CFF_GlyphSlot  slot = (CFF_GlyphSlot)cffslot;
 169     CFF_Size       size = (CFF_Size)cffsize;
 170 
 171 
 172     if ( !slot )
 173       return FT_THROW( Invalid_Slot_Handle );
 174 
 175     FT_TRACE1(( "cff_glyph_load: glyph index %d\n", glyph_index ));
 176 
 177     /* check whether we want a scaled outline or bitmap */
 178     if ( !size )
 179       load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
 180 
 181     /* reset the size object if necessary */
 182     if ( load_flags & FT_LOAD_NO_SCALE )
 183       size = NULL;
 184 
 185     if ( size )
 186     {
 187       /* these two objects must have the same parent */
 188       if ( cffsize->face != cffslot->face )
 189         return FT_THROW( Invalid_Face_Handle );
 190     }
 191 
 192     /* now load the glyph outline if necessary */
 193     error = cff_slot_load( slot, size, glyph_index, load_flags );
 194 
 195     /* force drop-out mode to 2 - irrelevant now */
 196     /* slot->outline.dropout_mode = 2; */
 197 
 198     return error;
 199   }
 200 
 201 
 202   FT_CALLBACK_DEF( FT_Error )
 203   cff_get_advances( FT_Face    face,
 204                     FT_UInt    start,
 205                     FT_UInt    count,
 206                     FT_Int32   flags,
 207                     FT_Fixed*  advances )
 208   {
 209     FT_UInt       nn;
 210     FT_Error      error = FT_Err_Ok;
 211     FT_GlyphSlot  slot  = face->glyph;
 212 
 213 
 214     if ( FT_IS_SFNT( face ) )
 215     {
 216       /* OpenType 1.7 mandates that the data from `hmtx' table be used; */
 217       /* it is no longer necessary that those values are identical to   */
 218       /* the values in the `CFF' table                                  */
 219 
 220       TT_Face   ttface = (TT_Face)face;
 221       FT_Short  dummy;
 222 
 223 
 224       if ( flags & FT_LOAD_VERTICAL_LAYOUT )
 225       {
 226 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 227         /* no fast retrieval for blended MM fonts without VVAR table */
 228         if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) &&
 229              !( ttface->variation_support & TT_FACE_FLAG_VAR_VADVANCE )  )
 230           return FT_THROW( Unimplemented_Feature );
 231 #endif
 232 
 233         /* check whether we have data from the `vmtx' table at all; */
 234         /* otherwise we extract the info from the CFF glyphstrings  */
 235         /* (instead of synthesizing a global value using the `OS/2' */
 236         /* table)                                                   */
 237         if ( !ttface->vertical_info )
 238           goto Missing_Table;
 239 
 240         for ( nn = 0; nn < count; nn++ )
 241         {
 242           FT_UShort  ah;
 243 
 244 
 245           ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface,
 246                                                        1,
 247                                                        start + nn,
 248                                                        &dummy,
 249                                                        &ah );
 250 
 251           FT_TRACE5(( "  idx %d: advance height %d font unit%s\n",
 252                       start + nn,
 253                       ah,
 254                       ah == 1 ? "" : "s" ));
 255           advances[nn] = ah;
 256         }
 257       }
 258       else
 259       {
 260 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 261         /* no fast retrieval for blended MM fonts without HVAR table */
 262         if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) &&
 263              !( ttface->variation_support & TT_FACE_FLAG_VAR_HADVANCE )  )
 264           return FT_THROW( Unimplemented_Feature );
 265 #endif
 266 
 267         /* check whether we have data from the `hmtx' table at all */
 268         if ( !ttface->horizontal.number_Of_HMetrics )
 269           goto Missing_Table;
 270 
 271         for ( nn = 0; nn < count; nn++ )
 272         {
 273           FT_UShort  aw;
 274 
 275 
 276           ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface,
 277                                                        0,
 278                                                        start + nn,
 279                                                        &dummy,
 280                                                        &aw );
 281 
 282           FT_TRACE5(( "  idx %d: advance width %d font unit%s\n",
 283                       start + nn,
 284                       aw,
 285                       aw == 1 ? "" : "s" ));
 286           advances[nn] = aw;
 287         }
 288       }
 289 
 290       return error;
 291     }
 292 
 293   Missing_Table:
 294     flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
 295 
 296     for ( nn = 0; nn < count; nn++ )
 297     {
 298       error = cff_glyph_load( slot, face->size, start + nn, flags );
 299       if ( error )
 300         break;
 301 
 302       advances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
 303                      ? slot->linearVertAdvance
 304                      : slot->linearHoriAdvance;
 305     }
 306 
 307     return error;
 308   }
 309 
 310 
 311   /*
 312    * GLYPH DICT SERVICE
 313    *
 314    */
 315 
 316   static FT_Error
 317   cff_get_glyph_name( CFF_Face    face,
 318                       FT_UInt     glyph_index,
 319                       FT_Pointer  buffer,
 320                       FT_UInt     buffer_max )
 321   {
 322     CFF_Font    font   = (CFF_Font)face->extra.data;
 323     FT_String*  gname;
 324     FT_UShort   sid;
 325     FT_Error    error;
 326 
 327 
 328     /* CFF2 table does not have glyph names; */
 329     /* we need to use `post' table method    */
 330     if ( font->version_major == 2 )
 331     {
 332       FT_Library            library     = FT_FACE_LIBRARY( face );
 333       FT_Module             sfnt_module = FT_Get_Module( library, "sfnt" );
 334       FT_Service_GlyphDict  service     =
 335         (FT_Service_GlyphDict)ft_module_get_service(
 336                                  sfnt_module,
 337                                  FT_SERVICE_ID_GLYPH_DICT,
 338                                  0 );
 339 
 340 
 341       if ( service && service->get_name )
 342         return service->get_name( FT_FACE( face ),
 343                                   glyph_index,
 344                                   buffer,
 345                                   buffer_max );
 346       else
 347       {
 348         FT_ERROR(( "cff_get_glyph_name:"
 349                    " cannot get glyph name from a CFF2 font\n"
 350                    "                   "
 351                    " without the `psnames' module\n" ));
 352         error = FT_THROW( Missing_Module );
 353         goto Exit;
 354       }
 355     }
 356 
 357     if ( !font->psnames )
 358     {
 359       FT_ERROR(( "cff_get_glyph_name:"
 360                  " cannot get glyph name from CFF & CEF fonts\n"
 361                  "                   "
 362                  " without the `psnames' module\n" ));
 363       error = FT_THROW( Missing_Module );
 364       goto Exit;
 365     }
 366 
 367     /* first, locate the sid in the charset table */
 368     sid = font->charset.sids[glyph_index];
 369 
 370     /* now, lookup the name itself */
 371     gname = cff_index_get_sid_string( font, sid );
 372 
 373     if ( gname )
 374       FT_STRCPYN( buffer, gname, buffer_max );
 375 
 376     error = FT_Err_Ok;
 377 
 378   Exit:
 379     return error;
 380   }
 381 
 382 
 383   static FT_UInt
 384   cff_get_name_index( CFF_Face    face,
 385                       FT_String*  glyph_name )
 386   {
 387     CFF_Font            cff;
 388     CFF_Charset         charset;
 389     FT_Service_PsCMaps  psnames;
 390     FT_String*          name;
 391     FT_UShort           sid;
 392     FT_UInt             i;
 393 
 394 
 395     cff     = (CFF_FontRec *)face->extra.data;
 396     charset = &cff->charset;
 397 
 398     /* CFF2 table does not have glyph names; */
 399     /* we need to use `post' table method    */
 400     if ( cff->version_major == 2 )
 401     {
 402       FT_Library            library     = FT_FACE_LIBRARY( face );
 403       FT_Module             sfnt_module = FT_Get_Module( library, "sfnt" );
 404       FT_Service_GlyphDict  service     =
 405         (FT_Service_GlyphDict)ft_module_get_service(
 406                                  sfnt_module,
 407                                  FT_SERVICE_ID_GLYPH_DICT,
 408                                  0 );
 409 
 410 
 411       if ( service && service->name_index )
 412         return service->name_index( FT_FACE( face ), glyph_name );
 413       else
 414       {
 415         FT_ERROR(( "cff_get_name_index:"
 416                    " cannot get glyph index from a CFF2 font\n"
 417                    "                   "
 418                    " without the `psnames' module\n" ));
 419         return 0;
 420       }
 421     }
 422 
 423     FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
 424     if ( !psnames )
 425       return 0;
 426 
 427     for ( i = 0; i < cff->num_glyphs; i++ )
 428     {
 429       sid = charset->sids[i];
 430 
 431       if ( sid > 390 )
 432         name = cff_index_get_string( cff, sid - 391 );
 433       else
 434         name = (FT_String *)psnames->adobe_std_strings( sid );
 435 
 436       if ( !name )
 437         continue;
 438 
 439       if ( !ft_strcmp( glyph_name, name ) )
 440         return i;
 441     }
 442 
 443     return 0;
 444   }
 445 
 446 
 447   FT_DEFINE_SERVICE_GLYPHDICTREC(
 448     cff_service_glyph_dict,
 449 
 450     (FT_GlyphDict_GetNameFunc)  cff_get_glyph_name,      /* get_name   */
 451     (FT_GlyphDict_NameIndexFunc)cff_get_name_index       /* name_index */
 452   )
 453 
 454 
 455   /*
 456    * POSTSCRIPT INFO SERVICE
 457    *
 458    */
 459 
 460   static FT_Int
 461   cff_ps_has_glyph_names( FT_Face  face )
 462   {
 463     return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0;
 464   }
 465 
 466 
 467   static FT_Error
 468   cff_ps_get_font_info( CFF_Face         face,
 469                         PS_FontInfoRec*  afont_info )
 470   {
 471     CFF_Font  cff   = (CFF_Font)face->extra.data;
 472     FT_Error  error = FT_Err_Ok;
 473 
 474 
 475     if ( cff && !cff->font_info )
 476     {
 477       CFF_FontRecDict  dict      = &cff->top_font.font_dict;
 478       PS_FontInfoRec  *font_info = NULL;
 479       FT_Memory        memory    = face->root.memory;
 480 
 481 
 482       if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) )
 483         goto Fail;
 484 
 485       font_info->version     = cff_index_get_sid_string( cff,
 486                                                          dict->version );
 487       font_info->notice      = cff_index_get_sid_string( cff,
 488                                                          dict->notice );
 489       font_info->full_name   = cff_index_get_sid_string( cff,
 490                                                          dict->full_name );
 491       font_info->family_name = cff_index_get_sid_string( cff,
 492                                                          dict->family_name );
 493       font_info->weight      = cff_index_get_sid_string( cff,
 494                                                          dict->weight );
 495       font_info->italic_angle        = dict->italic_angle;
 496       font_info->is_fixed_pitch      = dict->is_fixed_pitch;
 497       font_info->underline_position  = (FT_Short)dict->underline_position;
 498       font_info->underline_thickness = (FT_UShort)dict->underline_thickness;
 499 
 500       cff->font_info = font_info;
 501     }
 502 
 503     if ( cff )
 504       *afont_info = *cff->font_info;
 505 
 506   Fail:
 507     return error;
 508   }
 509 
 510 
 511   static FT_Error
 512   cff_ps_get_font_extra( CFF_Face          face,
 513                          PS_FontExtraRec*  afont_extra )
 514   {
 515     CFF_Font  cff   = (CFF_Font)face->extra.data;
 516     FT_Error  error = FT_Err_Ok;
 517 
 518 
 519     if ( cff && cff->font_extra == NULL )
 520     {
 521       CFF_FontRecDict   dict       = &cff->top_font.font_dict;
 522       PS_FontExtraRec*  font_extra = NULL;
 523       FT_Memory         memory     = face->root.memory;
 524       FT_String*        embedded_postscript;
 525 
 526 
 527       if ( FT_ALLOC( font_extra, sizeof ( *font_extra ) ) )
 528         goto Fail;
 529 
 530       font_extra->fs_type = 0U;
 531 
 532       embedded_postscript = cff_index_get_sid_string(
 533                               cff,
 534                               dict->embedded_postscript );
 535       if ( embedded_postscript )
 536       {
 537         FT_String*  start_fstype;
 538         FT_String*  start_def;
 539 
 540 
 541         /* Identify the XYZ integer in `/FSType XYZ def' substring. */
 542         if ( ( start_fstype = ft_strstr( embedded_postscript,
 543                                          "/FSType" ) ) != NULL    &&
 544              ( start_def = ft_strstr( start_fstype +
 545                                         sizeof ( "/FSType" ) - 1,
 546                                       "def" ) ) != NULL           )
 547         {
 548           FT_String*  s;
 549 
 550 
 551           for ( s = start_fstype + sizeof ( "/FSType" ) - 1;
 552                 s != start_def;
 553                 s++ )
 554           {
 555             if ( *s >= '0' && *s <= '9' )
 556             {
 557               if ( font_extra->fs_type >= ( FT_USHORT_MAX - 9 ) / 10 )
 558               {
 559                 /* Overflow - ignore the FSType value.  */
 560                 font_extra->fs_type = 0U;
 561                 break;
 562               }
 563 
 564               font_extra->fs_type *= 10;
 565               font_extra->fs_type += (FT_UShort)( *s - '0' );
 566             }
 567             else if ( *s != ' ' && *s != '\n' && *s != '\r' )
 568             {
 569               /* Non-whitespace character between `/FSType' and next `def' */
 570               /* - ignore the FSType value.                                */
 571               font_extra->fs_type = 0U;
 572               break;
 573             }
 574           }
 575         }
 576       }
 577 
 578       cff->font_extra = font_extra;
 579     }
 580 
 581     if ( cff )
 582       *afont_extra = *cff->font_extra;
 583 
 584   Fail:
 585     return error;
 586   }
 587 
 588 
 589   FT_DEFINE_SERVICE_PSINFOREC(
 590     cff_service_ps_info,
 591 
 592     (PS_GetFontInfoFunc)   cff_ps_get_font_info,    /* ps_get_font_info    */
 593     (PS_GetFontExtraFunc)  cff_ps_get_font_extra,   /* ps_get_font_extra   */
 594     (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names,  /* ps_has_glyph_names  */
 595     /* unsupported with CFF fonts */
 596     (PS_GetFontPrivateFunc)NULL,                    /* ps_get_font_private */
 597     /* not implemented            */
 598     (PS_GetFontValueFunc)  NULL                     /* ps_get_font_value   */
 599   )
 600 
 601 
 602   /*
 603    * POSTSCRIPT NAME SERVICE
 604    *
 605    */
 606 
 607   static const char*
 608   cff_get_ps_name( CFF_Face  face )
 609   {
 610     CFF_Font      cff  = (CFF_Font)face->extra.data;
 611     SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
 612 
 613 
 614     /* following the OpenType specification 1.7, we return the name stored */
 615     /* in the `name' table for a CFF wrapped into an SFNT container        */
 616 
 617     if ( FT_IS_SFNT( FT_FACE( face ) ) && sfnt )
 618     {
 619       FT_Library             library     = FT_FACE_LIBRARY( face );
 620       FT_Module              sfnt_module = FT_Get_Module( library, "sfnt" );
 621       FT_Service_PsFontName  service     =
 622         (FT_Service_PsFontName)ft_module_get_service(
 623                                  sfnt_module,
 624                                  FT_SERVICE_ID_POSTSCRIPT_FONT_NAME,
 625                                  0 );
 626 
 627 
 628       if ( service && service->get_ps_font_name )
 629         return service->get_ps_font_name( FT_FACE( face ) );
 630     }
 631 
 632     return (const char*)cff->font_name;
 633   }
 634 
 635 
 636   FT_DEFINE_SERVICE_PSFONTNAMEREC(
 637     cff_service_ps_name,
 638 
 639     (FT_PsName_GetFunc)cff_get_ps_name      /* get_ps_font_name */
 640   )
 641 
 642 
 643   /*
 644    * TT CMAP INFO
 645    *
 646    * If the charmap is a synthetic Unicode encoding cmap or
 647    * a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO
 648    * service defined in SFNT module.
 649    *
 650    * Otherwise call the service function in the sfnt module.
 651    *
 652    */
 653   static FT_Error
 654   cff_get_cmap_info( FT_CharMap    charmap,
 655                      TT_CMapInfo  *cmap_info )
 656   {
 657     FT_CMap   cmap  = FT_CMAP( charmap );
 658     FT_Error  error = FT_Err_Ok;
 659 
 660     FT_Face     face    = FT_CMAP_FACE( cmap );
 661     FT_Library  library = FT_FACE_LIBRARY( face );
 662 
 663 
 664     if ( cmap->clazz != &cff_cmap_encoding_class_rec &&
 665          cmap->clazz != &cff_cmap_unicode_class_rec  )
 666     {
 667       FT_Module           sfnt    = FT_Get_Module( library, "sfnt" );
 668       FT_Service_TTCMaps  service =
 669         (FT_Service_TTCMaps)ft_module_get_service( sfnt,
 670                                                    FT_SERVICE_ID_TT_CMAP,
 671                                                    0 );
 672 
 673 
 674       if ( service && service->get_cmap_info )
 675         error = service->get_cmap_info( charmap, cmap_info );
 676     }
 677     else
 678       error = FT_THROW( Invalid_CharMap_Format );
 679 
 680     return error;
 681   }
 682 
 683 
 684   FT_DEFINE_SERVICE_TTCMAPSREC(
 685     cff_service_get_cmap_info,
 686 
 687     (TT_CMap_Info_GetFunc)cff_get_cmap_info    /* get_cmap_info */
 688   )
 689 
 690 
 691   /*
 692    * CID INFO SERVICE
 693    *
 694    */
 695   static FT_Error
 696   cff_get_ros( CFF_Face      face,
 697                const char*  *registry,
 698                const char*  *ordering,
 699                FT_Int       *supplement )
 700   {
 701     FT_Error  error = FT_Err_Ok;
 702     CFF_Font  cff   = (CFF_Font)face->extra.data;
 703 
 704 
 705     if ( cff )
 706     {
 707       CFF_FontRecDict  dict = &cff->top_font.font_dict;
 708 
 709 
 710       if ( dict->cid_registry == 0xFFFFU )
 711       {
 712         error = FT_THROW( Invalid_Argument );
 713         goto Fail;
 714       }
 715 
 716       if ( registry )
 717       {
 718         if ( !cff->registry )
 719           cff->registry = cff_index_get_sid_string( cff,
 720                                                     dict->cid_registry );
 721         *registry = cff->registry;
 722       }
 723 
 724       if ( ordering )
 725       {
 726         if ( !cff->ordering )
 727           cff->ordering = cff_index_get_sid_string( cff,
 728                                                     dict->cid_ordering );
 729         *ordering = cff->ordering;
 730       }
 731 
 732       /*
 733        * XXX: According to Adobe TechNote #5176, the supplement in CFF
 734        *      can be a real number. We truncate it to fit public API
 735        *      since freetype-2.3.6.
 736        */
 737       if ( supplement )
 738       {
 739         if ( dict->cid_supplement < FT_INT_MIN ||
 740              dict->cid_supplement > FT_INT_MAX )
 741           FT_TRACE1(( "cff_get_ros: too large supplement %d is truncated\n",
 742                       dict->cid_supplement ));
 743         *supplement = (FT_Int)dict->cid_supplement;
 744       }
 745     }
 746 
 747   Fail:
 748     return error;
 749   }
 750 
 751 
 752   static FT_Error
 753   cff_get_is_cid( CFF_Face  face,
 754                   FT_Bool  *is_cid )
 755   {
 756     FT_Error  error = FT_Err_Ok;
 757     CFF_Font  cff   = (CFF_Font)face->extra.data;
 758 
 759 
 760     *is_cid = 0;
 761 
 762     if ( cff )
 763     {
 764       CFF_FontRecDict  dict = &cff->top_font.font_dict;
 765 
 766 
 767       if ( dict->cid_registry != 0xFFFFU )
 768         *is_cid = 1;
 769     }
 770 
 771     return error;
 772   }
 773 
 774 
 775   static FT_Error
 776   cff_get_cid_from_glyph_index( CFF_Face  face,
 777                                 FT_UInt   glyph_index,
 778                                 FT_UInt  *cid )
 779   {
 780     FT_Error  error = FT_Err_Ok;
 781     CFF_Font  cff;
 782 
 783 
 784     cff = (CFF_Font)face->extra.data;
 785 
 786     if ( cff )
 787     {
 788       FT_UInt          c;
 789       CFF_FontRecDict  dict = &cff->top_font.font_dict;
 790 
 791 
 792       if ( dict->cid_registry == 0xFFFFU )
 793       {
 794         error = FT_THROW( Invalid_Argument );
 795         goto Fail;
 796       }
 797 
 798       if ( glyph_index >= cff->num_glyphs )
 799       {
 800         error = FT_THROW( Invalid_Argument );
 801         goto Fail;
 802       }
 803 
 804       c = cff->charset.sids[glyph_index];
 805 
 806       if ( cid )
 807         *cid = c;
 808     }
 809 
 810   Fail:
 811     return error;
 812   }
 813 
 814 
 815   FT_DEFINE_SERVICE_CIDREC(
 816     cff_service_cid_info,
 817 
 818     (FT_CID_GetRegistryOrderingSupplementFunc)
 819       cff_get_ros,                             /* get_ros                  */
 820     (FT_CID_GetIsInternallyCIDKeyedFunc)
 821       cff_get_is_cid,                          /* get_is_cid               */
 822     (FT_CID_GetCIDFromGlyphIndexFunc)
 823       cff_get_cid_from_glyph_index             /* get_cid_from_glyph_index */
 824   )
 825 
 826 
 827   /*
 828    * PROPERTY SERVICE
 829    *
 830    */
 831 
 832   FT_DEFINE_SERVICE_PROPERTIESREC(
 833     cff_service_properties,
 834 
 835     (FT_Properties_SetFunc)ps_property_set,      /* set_property */
 836     (FT_Properties_GetFunc)ps_property_get )     /* get_property */
 837 
 838 
 839 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 840 
 841   /*
 842    * MULTIPLE MASTER SERVICE
 843    *
 844    */
 845 
 846   static FT_Error
 847   cff_set_mm_blend( CFF_Face   face,
 848                     FT_UInt    num_coords,
 849                     FT_Fixed*  coords )
 850   {
 851     FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
 852 
 853 
 854     return mm->set_mm_blend( FT_FACE( face ), num_coords, coords );
 855   }
 856 
 857 
 858   static FT_Error
 859   cff_get_mm_blend( CFF_Face   face,
 860                     FT_UInt    num_coords,
 861                     FT_Fixed*  coords )
 862   {
 863     FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
 864 
 865 
 866     return mm->get_mm_blend( FT_FACE( face ), num_coords, coords );
 867   }
 868 
 869 
 870   static FT_Error
 871   cff_set_mm_weightvector( CFF_Face   face,
 872                            FT_UInt    len,
 873                            FT_Fixed*  weightvector )
 874   {
 875     FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
 876 
 877 
 878     return mm->set_mm_weightvector( FT_FACE( face ), len, weightvector );
 879   }
 880 
 881 
 882   static FT_Error
 883   cff_get_mm_weightvector( CFF_Face   face,
 884                            FT_UInt*   len,
 885                            FT_Fixed*  weightvector )
 886   {
 887     FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
 888 
 889 
 890     return mm->get_mm_weightvector( FT_FACE( face ), len, weightvector );
 891   }
 892 
 893 
 894   static FT_Error
 895   cff_get_mm_var( CFF_Face     face,
 896                   FT_MM_Var*  *master )
 897   {
 898     FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
 899 
 900 
 901     return mm->get_mm_var( FT_FACE( face ), master );
 902   }
 903 
 904 
 905   static FT_Error
 906   cff_set_var_design( CFF_Face   face,
 907                       FT_UInt    num_coords,
 908                       FT_Fixed*  coords )
 909   {
 910     FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
 911 
 912 
 913     return mm->set_var_design( FT_FACE( face ), num_coords, coords );
 914   }
 915 
 916 
 917   static FT_Error
 918   cff_get_var_design( CFF_Face   face,
 919                       FT_UInt    num_coords,
 920                       FT_Fixed*  coords )
 921   {
 922     FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
 923 
 924 
 925     return mm->get_var_design( FT_FACE( face ), num_coords, coords );
 926   }
 927 
 928 
 929   static FT_Error
 930   cff_set_instance( CFF_Face  face,
 931                     FT_UInt   instance_index )
 932   {
 933     FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
 934 
 935 
 936     return mm->set_instance( FT_FACE( face ), instance_index );
 937   }
 938 
 939 
 940   FT_DEFINE_SERVICE_MULTIMASTERSREC(
 941     cff_service_multi_masters,
 942 
 943     (FT_Get_MM_Func)             NULL,                    /* get_mm              */
 944     (FT_Set_MM_Design_Func)      NULL,                    /* set_mm_design       */
 945     (FT_Set_MM_Blend_Func)       cff_set_mm_blend,        /* set_mm_blend        */
 946     (FT_Get_MM_Blend_Func)       cff_get_mm_blend,        /* get_mm_blend        */
 947     (FT_Get_MM_Var_Func)         cff_get_mm_var,          /* get_mm_var          */
 948     (FT_Set_Var_Design_Func)     cff_set_var_design,      /* set_var_design      */
 949     (FT_Get_Var_Design_Func)     cff_get_var_design,      /* get_var_design      */
 950     (FT_Set_Instance_Func)       cff_set_instance,        /* set_instance        */
 951     (FT_Set_MM_WeightVector_Func)cff_set_mm_weightvector, /* set_mm_weightvector */
 952     (FT_Get_MM_WeightVector_Func)cff_get_mm_weightvector, /* get_mm_weightvector */
 953 
 954     (FT_Get_Var_Blend_Func)      cff_get_var_blend,       /* get_var_blend       */
 955     (FT_Done_Blend_Func)         cff_done_blend           /* done_blend          */
 956   )
 957 
 958 
 959   /*
 960    * METRICS VARIATIONS SERVICE
 961    *
 962    */
 963 
 964   static FT_Error
 965   cff_hadvance_adjust( CFF_Face  face,
 966                        FT_UInt   gindex,
 967                        FT_Int   *avalue )
 968   {
 969     FT_Service_MetricsVariations  var = (FT_Service_MetricsVariations)face->var;
 970 
 971 
 972     return var->hadvance_adjust( FT_FACE( face ), gindex, avalue );
 973   }
 974 
 975 
 976   static void
 977   cff_metrics_adjust( CFF_Face  face )
 978   {
 979     FT_Service_MetricsVariations  var = (FT_Service_MetricsVariations)face->var;
 980 
 981 
 982     var->metrics_adjust( FT_FACE( face ) );
 983   }
 984 
 985 
 986   FT_DEFINE_SERVICE_METRICSVARIATIONSREC(
 987     cff_service_metrics_variations,
 988 
 989     (FT_HAdvance_Adjust_Func)cff_hadvance_adjust,    /* hadvance_adjust */
 990     (FT_LSB_Adjust_Func)     NULL,                   /* lsb_adjust      */
 991     (FT_RSB_Adjust_Func)     NULL,                   /* rsb_adjust      */
 992 
 993     (FT_VAdvance_Adjust_Func)NULL,                   /* vadvance_adjust */
 994     (FT_TSB_Adjust_Func)     NULL,                   /* tsb_adjust      */
 995     (FT_BSB_Adjust_Func)     NULL,                   /* bsb_adjust      */
 996     (FT_VOrg_Adjust_Func)    NULL,                   /* vorg_adjust     */
 997 
 998     (FT_Metrics_Adjust_Func) cff_metrics_adjust      /* metrics_adjust  */
 999   )
1000 #endif
1001 
1002 
1003   /*
1004    * CFFLOAD SERVICE
1005    *
1006    */
1007 
1008   FT_DEFINE_SERVICE_CFFLOADREC(
1009     cff_service_cff_load,
1010 
1011     (FT_Get_Standard_Encoding_Func)cff_get_standard_encoding,
1012     (FT_Load_Private_Dict_Func)    cff_load_private_dict,
1013     (FT_FD_Select_Get_Func)        cff_fd_select_get,
1014     (FT_Blend_Check_Vector_Func)   cff_blend_check_vector,
1015     (FT_Blend_Build_Vector_Func)   cff_blend_build_vector
1016   )
1017 
1018 
1019   /*************************************************************************/
1020   /*************************************************************************/
1021   /*************************************************************************/
1022   /****                                                                 ****/
1023   /****                                                                 ****/
1024   /****                D R I V E R  I N T E R F A C E                   ****/
1025   /****                                                                 ****/
1026   /****                                                                 ****/
1027   /*************************************************************************/
1028   /*************************************************************************/
1029   /*************************************************************************/
1030 
1031 #if !defined FT_CONFIG_OPTION_NO_GLYPH_NAMES && \
1032      defined TT_CONFIG_OPTION_GX_VAR_SUPPORT
1033   FT_DEFINE_SERVICEDESCREC10(
1034     cff_services,
1035 
1036     FT_SERVICE_ID_FONT_FORMAT,          FT_FONT_FORMAT_CFF,
1037     FT_SERVICE_ID_MULTI_MASTERS,        &cff_service_multi_masters,
1038     FT_SERVICE_ID_METRICS_VARIATIONS,   &cff_service_metrics_variations,
1039     FT_SERVICE_ID_POSTSCRIPT_INFO,      &cff_service_ps_info,
1040     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name,
1041     FT_SERVICE_ID_GLYPH_DICT,           &cff_service_glyph_dict,
1042     FT_SERVICE_ID_TT_CMAP,              &cff_service_get_cmap_info,
1043     FT_SERVICE_ID_CID,                  &cff_service_cid_info,
1044     FT_SERVICE_ID_PROPERTIES,           &cff_service_properties,
1045     FT_SERVICE_ID_CFF_LOAD,             &cff_service_cff_load
1046   )
1047 #elif !defined FT_CONFIG_OPTION_NO_GLYPH_NAMES
1048   FT_DEFINE_SERVICEDESCREC8(
1049     cff_services,
1050 
1051     FT_SERVICE_ID_FONT_FORMAT,          FT_FONT_FORMAT_CFF,
1052     FT_SERVICE_ID_POSTSCRIPT_INFO,      &cff_service_ps_info,
1053     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name,
1054     FT_SERVICE_ID_GLYPH_DICT,           &cff_service_glyph_dict,
1055     FT_SERVICE_ID_TT_CMAP,              &cff_service_get_cmap_info,
1056     FT_SERVICE_ID_CID,                  &cff_service_cid_info,
1057     FT_SERVICE_ID_PROPERTIES,           &cff_service_properties,
1058     FT_SERVICE_ID_CFF_LOAD,             &cff_service_cff_load
1059   )
1060 #elif defined TT_CONFIG_OPTION_GX_VAR_SUPPORT
1061   FT_DEFINE_SERVICEDESCREC9(
1062     cff_services,
1063 
1064     FT_SERVICE_ID_FONT_FORMAT,          FT_FONT_FORMAT_CFF,
1065     FT_SERVICE_ID_MULTI_MASTERS,        &cff_service_multi_masters,
1066     FT_SERVICE_ID_METRICS_VARIATIONS,   &cff_service_metrics_var,
1067     FT_SERVICE_ID_POSTSCRIPT_INFO,      &cff_service_ps_info,
1068     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name,
1069     FT_SERVICE_ID_TT_CMAP,              &cff_service_get_cmap_info,
1070     FT_SERVICE_ID_CID,                  &cff_service_cid_info,
1071     FT_SERVICE_ID_PROPERTIES,           &cff_service_properties,
1072     FT_SERVICE_ID_CFF_LOAD,             &cff_service_cff_load
1073   )
1074 #else
1075   FT_DEFINE_SERVICEDESCREC7(
1076     cff_services,
1077 
1078     FT_SERVICE_ID_FONT_FORMAT,          FT_FONT_FORMAT_CFF,
1079     FT_SERVICE_ID_POSTSCRIPT_INFO,      &cff_service_ps_info,
1080     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name,
1081     FT_SERVICE_ID_TT_CMAP,              &cff_service_get_cmap_info,
1082     FT_SERVICE_ID_CID,                  &cff_service_cid_info,
1083     FT_SERVICE_ID_PROPERTIES,           &cff_service_properties,
1084     FT_SERVICE_ID_CFF_LOAD,             &cff_service_cff_load
1085   )
1086 #endif
1087 
1088 
1089   FT_CALLBACK_DEF( FT_Module_Interface )
1090   cff_get_interface( FT_Module    driver,       /* CFF_Driver */
1091                      const char*  module_interface )
1092   {
1093     FT_Library           library;
1094     FT_Module            sfnt;
1095     FT_Module_Interface  result;
1096 
1097 
1098     result = ft_service_list_lookup( cff_services, module_interface );
1099     if ( result )
1100       return result;
1101 
1102     /* `driver' is not yet evaluated */
1103     if ( !driver )
1104       return NULL;
1105     library = driver->library;
1106     if ( !library )
1107       return NULL;
1108 
1109     /* we pass our request to the `sfnt' module */
1110     sfnt = FT_Get_Module( library, "sfnt" );
1111 
1112     return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0;
1113   }
1114 
1115 
1116   /* The FT_DriverInterface structure is defined in ftdriver.h. */
1117 
1118 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
1119 #define CFF_SIZE_SELECT cff_size_select
1120 #else
1121 #define CFF_SIZE_SELECT 0
1122 #endif
1123 
1124   FT_DEFINE_DRIVER(
1125     cff_driver_class,
1126 
1127       FT_MODULE_FONT_DRIVER          |
1128       FT_MODULE_DRIVER_SCALABLE      |
1129       FT_MODULE_DRIVER_HAS_HINTER    |
1130       FT_MODULE_DRIVER_HINTS_LIGHTLY,
1131 
1132       sizeof ( PS_DriverRec ),
1133       "cff",
1134       0x10000L,
1135       0x20000L,
1136 
1137       NULL,   /* module-specific interface */
1138 
1139       cff_driver_init,          /* FT_Module_Constructor  module_init   */
1140       cff_driver_done,          /* FT_Module_Destructor   module_done   */
1141       cff_get_interface,        /* FT_Module_Requester    get_interface */
1142 
1143     sizeof ( TT_FaceRec ),
1144     sizeof ( CFF_SizeRec ),
1145     sizeof ( CFF_GlyphSlotRec ),
1146 
1147     cff_face_init,              /* FT_Face_InitFunc  init_face */
1148     cff_face_done,              /* FT_Face_DoneFunc  done_face */
1149     cff_size_init,              /* FT_Size_InitFunc  init_size */
1150     cff_size_done,              /* FT_Size_DoneFunc  done_size */
1151     cff_slot_init,              /* FT_Slot_InitFunc  init_slot */
1152     cff_slot_done,              /* FT_Slot_DoneFunc  done_slot */
1153 
1154     cff_glyph_load,             /* FT_Slot_LoadFunc  load_glyph */
1155 
1156     cff_get_kerning,            /* FT_Face_GetKerningFunc   get_kerning  */
1157     NULL,                       /* FT_Face_AttachFunc       attach_file  */
1158     cff_get_advances,           /* FT_Face_GetAdvancesFunc  get_advances */
1159 
1160     cff_size_request,           /* FT_Size_RequestFunc  request_size */
1161     CFF_SIZE_SELECT             /* FT_Size_SelectFunc   select_size  */
1162   )
1163 
1164 
1165 /* END */