tor-browser

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

cffdrivr.c (38045B)


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