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