Home | History | Annotate | Download | only in cff
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  cffdrivr.c                                                             */
      4 /*                                                                         */
      5 /*    OpenType font driver implementation (body).                          */
      6 /*                                                                         */
      7 /*  Copyright 1996-2013 by                                                 */
      8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
      9 /*                                                                         */
     10 /*  This file is part of the FreeType project, and may only be used,       */
     11 /*  modified, and distributed under the terms of the FreeType project      */
     12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
     13 /*  this file you indicate that you have read the license and              */
     14 /*  understand and accept it fully.                                        */
     15 /*                                                                         */
     16 /***************************************************************************/
     17 
     18 
     19 #include <ft2build.h>
     20 #include FT_FREETYPE_H
     21 #include FT_INTERNAL_DEBUG_H
     22 #include FT_INTERNAL_STREAM_H
     23 #include FT_INTERNAL_SFNT_H
     24 #include FT_SERVICE_CID_H
     25 #include FT_SERVICE_POSTSCRIPT_INFO_H
     26 #include FT_SERVICE_POSTSCRIPT_NAME_H
     27 #include FT_SERVICE_TT_CMAP_H
     28 
     29 #include "cffdrivr.h"
     30 #include "cffgload.h"
     31 #include "cffload.h"
     32 #include "cffcmap.h"
     33 #include "cffparse.h"
     34 
     35 #include "cfferrs.h"
     36 #include "cffpic.h"
     37 
     38 #include FT_SERVICE_XFREE86_NAME_H
     39 #include FT_SERVICE_GLYPH_DICT_H
     40 #include FT_SERVICE_PROPERTIES_H
     41 #include FT_CFF_DRIVER_H
     42 
     43 
     44   /*************************************************************************/
     45   /*                                                                       */
     46   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
     47   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
     48   /* messages during execution.                                            */
     49   /*                                                                       */
     50 #undef  FT_COMPONENT
     51 #define FT_COMPONENT  trace_cffdriver
     52 
     53 
     54   /*************************************************************************/
     55   /*************************************************************************/
     56   /*************************************************************************/
     57   /****                                                                 ****/
     58   /****                                                                 ****/
     59   /****                          F A C E S                              ****/
     60   /****                                                                 ****/
     61   /****                                                                 ****/
     62   /*************************************************************************/
     63   /*************************************************************************/
     64   /*************************************************************************/
     65 
     66 
     67 #undef  PAIR_TAG
     68 #define PAIR_TAG( left, right )  ( ( (FT_ULong)left << 16 ) | \
     69                                      (FT_ULong)right        )
     70 
     71 
     72   /*************************************************************************/
     73   /*                                                                       */
     74   /* <Function>                                                            */
     75   /*    cff_get_kerning                                                    */
     76   /*                                                                       */
     77   /* <Description>                                                         */
     78   /*    A driver method used to return the kerning vector between two      */
     79   /*    glyphs of the same face.                                           */
     80   /*                                                                       */
     81   /* <Input>                                                               */
     82   /*    face        :: A handle to the source face object.                 */
     83   /*                                                                       */
     84   /*    left_glyph  :: The index of the left glyph in the kern pair.       */
     85   /*                                                                       */
     86   /*    right_glyph :: The index of the right glyph in the kern pair.      */
     87   /*                                                                       */
     88   /* <Output>                                                              */
     89   /*    kerning     :: The kerning vector.  This is in font units for      */
     90   /*                   scalable formats, and in pixels for fixed-sizes     */
     91   /*                   formats.                                            */
     92   /*                                                                       */
     93   /* <Return>                                                              */
     94   /*    FreeType error code.  0 means success.                             */
     95   /*                                                                       */
     96   /* <Note>                                                                */
     97   /*    Only horizontal layouts (left-to-right & right-to-left) are        */
     98   /*    supported by this function.  Other layouts, or more sophisticated  */
     99   /*    kernings, are out of scope of this method (the basic driver        */
    100   /*    interface is meant to be simple).                                  */
    101   /*                                                                       */
    102   /*    They can be implemented by format-specific interfaces.             */
    103   /*                                                                       */
    104   FT_CALLBACK_DEF( FT_Error )
    105   cff_get_kerning( FT_Face     ttface,          /* TT_Face */
    106                    FT_UInt     left_glyph,
    107                    FT_UInt     right_glyph,
    108                    FT_Vector*  kerning )
    109   {
    110     TT_Face       face = (TT_Face)ttface;
    111     SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
    112 
    113 
    114     kerning->x = 0;
    115     kerning->y = 0;
    116 
    117     if ( sfnt )
    118       kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph );
    119 
    120     return FT_Err_Ok;
    121   }
    122 
    123 
    124 #undef PAIR_TAG
    125 
    126 
    127   /*************************************************************************/
    128   /*                                                                       */
    129   /* <Function>                                                            */
    130   /*    cff_glyph_load                                                     */
    131   /*                                                                       */
    132   /* <Description>                                                         */
    133   /*    A driver method used to load a glyph within a given glyph slot.    */
    134   /*                                                                       */
    135   /* <Input>                                                               */
    136   /*    slot        :: A handle to the target slot object where the glyph  */
    137   /*                   will be loaded.                                     */
    138   /*                                                                       */
    139   /*    size        :: A handle to the source face size at which the glyph */
    140   /*                   must be scaled, loaded, etc.                        */
    141   /*                                                                       */
    142   /*    glyph_index :: The index of the glyph in the font file.            */
    143   /*                                                                       */
    144   /*    load_flags  :: A flag indicating what to load for this glyph.  The */
    145   /*                   FT_LOAD_??? constants can be used to control the    */
    146   /*                   glyph loading process (e.g., whether the outline    */
    147   /*                   should be scaled, whether to load bitmaps or not,   */
    148   /*                   whether to hint the outline, etc).                  */
    149   /*                                                                       */
    150   /* <Return>                                                              */
    151   /*    FreeType error code.  0 means success.                             */
    152   /*                                                                       */
    153   FT_CALLBACK_DEF( FT_Error )
    154   cff_glyph_load( FT_GlyphSlot  cffslot,      /* CFF_GlyphSlot */
    155                   FT_Size       cffsize,      /* CFF_Size      */
    156                   FT_UInt       glyph_index,
    157                   FT_Int32      load_flags )
    158   {
    159     FT_Error       error;
    160     CFF_GlyphSlot  slot = (CFF_GlyphSlot)cffslot;
    161     CFF_Size       size = (CFF_Size)cffsize;
    162 
    163 
    164     if ( !slot )
    165       return FT_THROW( Invalid_Slot_Handle );
    166 
    167     /* check whether we want a scaled outline or bitmap */
    168     if ( !size )
    169       load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
    170 
    171     /* reset the size object if necessary */
    172     if ( load_flags & FT_LOAD_NO_SCALE )
    173       size = NULL;
    174 
    175     if ( size )
    176     {
    177       /* these two objects must have the same parent */
    178       if ( cffsize->face != cffslot->face )
    179         return FT_THROW( Invalid_Face_Handle );
    180     }
    181 
    182     /* now load the glyph outline if necessary */
    183     error = cff_slot_load( slot, size, glyph_index, load_flags );
    184 
    185     /* force drop-out mode to 2 - irrelevant now */
    186     /* slot->outline.dropout_mode = 2; */
    187 
    188     return error;
    189   }
    190 
    191 
    192   FT_CALLBACK_DEF( FT_Error )
    193   cff_get_advances( FT_Face    face,
    194                     FT_UInt    start,
    195                     FT_UInt    count,
    196                     FT_Int32   flags,
    197                     FT_Fixed*  advances )
    198   {
    199     FT_UInt       nn;
    200     FT_Error      error = FT_Err_Ok;
    201     FT_GlyphSlot  slot  = face->glyph;
    202 
    203 
    204     flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
    205 
    206     for ( nn = 0; nn < count; nn++ )
    207     {
    208       error = cff_glyph_load( slot, face->size, start + nn, flags );
    209       if ( error )
    210         break;
    211 
    212       advances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
    213                      ? slot->linearVertAdvance
    214                      : slot->linearHoriAdvance;
    215     }
    216 
    217     return error;
    218   }
    219 
    220 
    221   /*
    222    *  GLYPH DICT SERVICE
    223    *
    224    */
    225 
    226   static FT_Error
    227   cff_get_glyph_name( CFF_Face    face,
    228                       FT_UInt     glyph_index,
    229                       FT_Pointer  buffer,
    230                       FT_UInt     buffer_max )
    231   {
    232     CFF_Font    font   = (CFF_Font)face->extra.data;
    233     FT_String*  gname;
    234     FT_UShort   sid;
    235     FT_Error    error;
    236 
    237 
    238     if ( !font->psnames )
    239     {
    240       FT_ERROR(( "cff_get_glyph_name:"
    241                  " cannot get glyph name from CFF & CEF fonts\n"
    242                  "                   "
    243                  " without the `PSNames' module\n" ));
    244       error = FT_THROW( Missing_Module );
    245       goto Exit;
    246     }
    247 
    248     /* first, locate the sid in the charset table */
    249     sid = font->charset.sids[glyph_index];
    250 
    251     /* now, lookup the name itself */
    252     gname = cff_index_get_sid_string( font, sid );
    253 
    254     if ( gname )
    255       FT_STRCPYN( buffer, gname, buffer_max );
    256 
    257     error = FT_Err_Ok;
    258 
    259   Exit:
    260     return error;
    261   }
    262 
    263 
    264   static FT_UInt
    265   cff_get_name_index( CFF_Face    face,
    266                       FT_String*  glyph_name )
    267   {
    268     CFF_Font            cff;
    269     CFF_Charset         charset;
    270     FT_Service_PsCMaps  psnames;
    271     FT_String*          name;
    272     FT_UShort           sid;
    273     FT_UInt             i;
    274 
    275 
    276     cff     = (CFF_FontRec *)face->extra.data;
    277     charset = &cff->charset;
    278 
    279     FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
    280     if ( !psnames )
    281       return 0;
    282 
    283     for ( i = 0; i < cff->num_glyphs; i++ )
    284     {
    285       sid = charset->sids[i];
    286 
    287       if ( sid > 390 )
    288         name = cff_index_get_string( cff, sid - 391 );
    289       else
    290         name = (FT_String *)psnames->adobe_std_strings( sid );
    291 
    292       if ( !name )
    293         continue;
    294 
    295       if ( !ft_strcmp( glyph_name, name ) )
    296         return i;
    297     }
    298 
    299     return 0;
    300   }
    301 
    302 
    303   FT_DEFINE_SERVICE_GLYPHDICTREC(
    304     cff_service_glyph_dict,
    305     (FT_GlyphDict_GetNameFunc)  cff_get_glyph_name,
    306     (FT_GlyphDict_NameIndexFunc)cff_get_name_index
    307   )
    308 
    309 
    310   /*
    311    *  POSTSCRIPT INFO SERVICE
    312    *
    313    */
    314 
    315   static FT_Int
    316   cff_ps_has_glyph_names( FT_Face  face )
    317   {
    318     return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0;
    319   }
    320 
    321 
    322   static FT_Error
    323   cff_ps_get_font_info( CFF_Face         face,
    324                         PS_FontInfoRec*  afont_info )
    325   {
    326     CFF_Font  cff   = (CFF_Font)face->extra.data;
    327     FT_Error  error = FT_Err_Ok;
    328 
    329 
    330     if ( cff && cff->font_info == NULL )
    331     {
    332       CFF_FontRecDict  dict   = &cff->top_font.font_dict;
    333       PS_FontInfoRec  *font_info = NULL;
    334       FT_Memory        memory = face->root.memory;
    335 
    336 
    337       if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) )
    338         goto Fail;
    339 
    340       font_info->version     = cff_index_get_sid_string( cff,
    341                                                          dict->version );
    342       font_info->notice      = cff_index_get_sid_string( cff,
    343                                                          dict->notice );
    344       font_info->full_name   = cff_index_get_sid_string( cff,
    345                                                          dict->full_name );
    346       font_info->family_name = cff_index_get_sid_string( cff,
    347                                                          dict->family_name );
    348       font_info->weight      = cff_index_get_sid_string( cff,
    349                                                          dict->weight );
    350       font_info->italic_angle        = dict->italic_angle;
    351       font_info->is_fixed_pitch      = dict->is_fixed_pitch;
    352       font_info->underline_position  = (FT_Short)dict->underline_position;
    353       font_info->underline_thickness = (FT_Short)dict->underline_thickness;
    354 
    355       cff->font_info = font_info;
    356     }
    357 
    358     if ( cff )
    359       *afont_info = *cff->font_info;
    360 
    361   Fail:
    362     return error;
    363   }
    364 
    365 
    366   FT_DEFINE_SERVICE_PSINFOREC(
    367     cff_service_ps_info,
    368     (PS_GetFontInfoFunc)   cff_ps_get_font_info,
    369     (PS_GetFontExtraFunc)  NULL,
    370     (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names,
    371     (PS_GetFontPrivateFunc)NULL,        /* unsupported with CFF fonts */
    372     (PS_GetFontValueFunc)  NULL         /* not implemented            */
    373   )
    374 
    375 
    376   /*
    377    *  POSTSCRIPT NAME SERVICE
    378    *
    379    */
    380 
    381   static const char*
    382   cff_get_ps_name( CFF_Face  face )
    383   {
    384     CFF_Font  cff = (CFF_Font)face->extra.data;
    385 
    386 
    387     return (const char*)cff->font_name;
    388   }
    389 
    390 
    391   FT_DEFINE_SERVICE_PSFONTNAMEREC(
    392     cff_service_ps_name,
    393     (FT_PsName_GetFunc)cff_get_ps_name
    394   )
    395 
    396 
    397   /*
    398    * TT CMAP INFO
    399    *
    400    * If the charmap is a synthetic Unicode encoding cmap or
    401    * a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO
    402    * service defined in SFNT module.
    403    *
    404    * Otherwise call the service function in the sfnt module.
    405    *
    406    */
    407   static FT_Error
    408   cff_get_cmap_info( FT_CharMap    charmap,
    409                      TT_CMapInfo  *cmap_info )
    410   {
    411     FT_CMap   cmap  = FT_CMAP( charmap );
    412     FT_Error  error = FT_Err_Ok;
    413 
    414     FT_Face     face    = FT_CMAP_FACE( cmap );
    415     FT_Library  library = FT_FACE_LIBRARY( face );
    416 
    417 
    418     cmap_info->language = 0;
    419     cmap_info->format   = 0;
    420 
    421     if ( cmap->clazz != &CFF_CMAP_ENCODING_CLASS_REC_GET &&
    422          cmap->clazz != &CFF_CMAP_UNICODE_CLASS_REC_GET  )
    423     {
    424       FT_Module           sfnt    = FT_Get_Module( library, "sfnt" );
    425       FT_Service_TTCMaps  service =
    426         (FT_Service_TTCMaps)ft_module_get_service( sfnt,
    427                                                    FT_SERVICE_ID_TT_CMAP );
    428 
    429 
    430       if ( service && service->get_cmap_info )
    431         error = service->get_cmap_info( charmap, cmap_info );
    432     }
    433 
    434     return error;
    435   }
    436 
    437 
    438   FT_DEFINE_SERVICE_TTCMAPSREC(
    439     cff_service_get_cmap_info,
    440     (TT_CMap_Info_GetFunc)cff_get_cmap_info
    441   )
    442 
    443 
    444   /*
    445    *  CID INFO SERVICE
    446    *
    447    */
    448   static FT_Error
    449   cff_get_ros( CFF_Face      face,
    450                const char*  *registry,
    451                const char*  *ordering,
    452                FT_Int       *supplement )
    453   {
    454     FT_Error  error = FT_Err_Ok;
    455     CFF_Font  cff   = (CFF_Font)face->extra.data;
    456 
    457 
    458     if ( cff )
    459     {
    460       CFF_FontRecDict  dict = &cff->top_font.font_dict;
    461 
    462 
    463       if ( dict->cid_registry == 0xFFFFU )
    464       {
    465         error = FT_THROW( Invalid_Argument );
    466         goto Fail;
    467       }
    468 
    469       if ( registry )
    470       {
    471         if ( cff->registry == NULL )
    472           cff->registry = cff_index_get_sid_string( cff,
    473                                                     dict->cid_registry );
    474         *registry = cff->registry;
    475       }
    476 
    477       if ( ordering )
    478       {
    479         if ( cff->ordering == NULL )
    480           cff->ordering = cff_index_get_sid_string( cff,
    481                                                     dict->cid_ordering );
    482         *ordering = cff->ordering;
    483       }
    484 
    485       /*
    486        * XXX: According to Adobe TechNote #5176, the supplement in CFF
    487        *      can be a real number. We truncate it to fit public API
    488        *      since freetype-2.3.6.
    489        */
    490       if ( supplement )
    491       {
    492         if ( dict->cid_supplement < FT_INT_MIN ||
    493              dict->cid_supplement > FT_INT_MAX )
    494           FT_TRACE1(( "cff_get_ros: too large supplement %d is truncated\n",
    495                       dict->cid_supplement ));
    496         *supplement = (FT_Int)dict->cid_supplement;
    497       }
    498     }
    499 
    500   Fail:
    501     return error;
    502   }
    503 
    504 
    505   static FT_Error
    506   cff_get_is_cid( CFF_Face  face,
    507                   FT_Bool  *is_cid )
    508   {
    509     FT_Error  error = FT_Err_Ok;
    510     CFF_Font  cff   = (CFF_Font)face->extra.data;
    511 
    512 
    513     *is_cid = 0;
    514 
    515     if ( cff )
    516     {
    517       CFF_FontRecDict  dict = &cff->top_font.font_dict;
    518 
    519 
    520       if ( dict->cid_registry != 0xFFFFU )
    521         *is_cid = 1;
    522     }
    523 
    524     return error;
    525   }
    526 
    527 
    528   static FT_Error
    529   cff_get_cid_from_glyph_index( CFF_Face  face,
    530                                 FT_UInt   glyph_index,
    531                                 FT_UInt  *cid )
    532   {
    533     FT_Error  error = FT_Err_Ok;
    534     CFF_Font  cff;
    535 
    536 
    537     cff = (CFF_Font)face->extra.data;
    538 
    539     if ( cff )
    540     {
    541       FT_UInt          c;
    542       CFF_FontRecDict  dict = &cff->top_font.font_dict;
    543 
    544 
    545       if ( dict->cid_registry == 0xFFFFU )
    546       {
    547         error = FT_THROW( Invalid_Argument );
    548         goto Fail;
    549       }
    550 
    551       if ( glyph_index > cff->num_glyphs )
    552       {
    553         error = FT_THROW( Invalid_Argument );
    554         goto Fail;
    555       }
    556 
    557       c = cff->charset.sids[glyph_index];
    558 
    559       if ( cid )
    560         *cid = c;
    561     }
    562 
    563   Fail:
    564     return error;
    565   }
    566 
    567 
    568   FT_DEFINE_SERVICE_CIDREC(
    569     cff_service_cid_info,
    570     (FT_CID_GetRegistryOrderingSupplementFunc)cff_get_ros,
    571     (FT_CID_GetIsInternallyCIDKeyedFunc)      cff_get_is_cid,
    572     (FT_CID_GetCIDFromGlyphIndexFunc)         cff_get_cid_from_glyph_index
    573   )
    574 
    575 
    576   /*
    577    *  PROPERTY SERVICE
    578    *
    579    */
    580   static FT_Error
    581   cff_property_set( FT_Module    module,         /* CFF_Driver */
    582                     const char*  property_name,
    583                     const void*  value )
    584   {
    585     FT_Error    error  = FT_Err_Ok;
    586     CFF_Driver  driver = (CFF_Driver)module;
    587 
    588 
    589     if ( !ft_strcmp( property_name, "hinting-engine" ) )
    590     {
    591       FT_UInt*  hinting_engine = (FT_UInt*)value;
    592 
    593 
    594 #ifndef CFF_CONFIG_OPTION_OLD_ENGINE
    595       if ( *hinting_engine != FT_CFF_HINTING_ADOBE )
    596         error = FT_ERR( Unimplemented_Feature );
    597       else
    598 #endif
    599         driver->hinting_engine = *hinting_engine;
    600 
    601       return error;
    602     }
    603     else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
    604     {
    605       FT_Bool*  no_stem_darkening = (FT_Bool*)value;
    606 
    607 
    608       driver->no_stem_darkening = *no_stem_darkening;
    609 
    610       return error;
    611     }
    612 
    613     FT_TRACE0(( "cff_property_set: missing property `%s'\n",
    614                 property_name ));
    615     return FT_THROW( Missing_Property );
    616   }
    617 
    618 
    619   static FT_Error
    620   cff_property_get( FT_Module    module,         /* CFF_Driver */
    621                     const char*  property_name,
    622                     const void*  value )
    623   {
    624     FT_Error    error  = FT_Err_Ok;
    625     CFF_Driver  driver = (CFF_Driver)module;
    626 
    627     FT_UInt  hinting_engine    = driver->hinting_engine;
    628     FT_Bool  no_stem_darkening = driver->no_stem_darkening;
    629 
    630 
    631     if ( !ft_strcmp( property_name, "hinting-engine" ) )
    632     {
    633       FT_UInt*  val = (FT_UInt*)value;
    634 
    635 
    636       *val = hinting_engine;
    637 
    638       return error;
    639     }
    640     else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
    641     {
    642       FT_Bool*  val = (FT_Bool*)value;
    643 
    644 
    645       *val = no_stem_darkening;
    646 
    647       return error;
    648     }
    649 
    650     FT_TRACE0(( "cff_property_get: missing property `%s'\n",
    651                 property_name ));
    652     return FT_THROW( Missing_Property );
    653   }
    654 
    655 
    656   FT_DEFINE_SERVICE_PROPERTIESREC(
    657     cff_service_properties,
    658     (FT_Properties_SetFunc)cff_property_set,
    659     (FT_Properties_GetFunc)cff_property_get )
    660 
    661 
    662   /*************************************************************************/
    663   /*************************************************************************/
    664   /*************************************************************************/
    665   /****                                                                 ****/
    666   /****                                                                 ****/
    667   /****                D R I V E R  I N T E R F A C E                   ****/
    668   /****                                                                 ****/
    669   /****                                                                 ****/
    670   /*************************************************************************/
    671   /*************************************************************************/
    672   /*************************************************************************/
    673 
    674 #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
    675   FT_DEFINE_SERVICEDESCREC7(
    676     cff_services,
    677     FT_SERVICE_ID_XF86_NAME,            FT_XF86_FORMAT_CFF,
    678     FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
    679     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
    680     FT_SERVICE_ID_GLYPH_DICT,           &CFF_SERVICE_GLYPH_DICT_GET,
    681     FT_SERVICE_ID_TT_CMAP,              &CFF_SERVICE_GET_CMAP_INFO_GET,
    682     FT_SERVICE_ID_CID,                  &CFF_SERVICE_CID_INFO_GET,
    683     FT_SERVICE_ID_PROPERTIES,           &CFF_SERVICE_PROPERTIES_GET
    684   )
    685 #else
    686   FT_DEFINE_SERVICEDESCREC6(
    687     cff_services,
    688     FT_SERVICE_ID_XF86_NAME,            FT_XF86_FORMAT_CFF,
    689     FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
    690     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
    691     FT_SERVICE_ID_TT_CMAP,              &CFF_SERVICE_GET_CMAP_INFO_GET,
    692     FT_SERVICE_ID_CID,                  &CFF_SERVICE_CID_INFO_GET,
    693     FT_SERVICE_ID_PROPERTIES,           &CFF_SERVICE_PROPERTIES_GET
    694   )
    695 #endif
    696 
    697 
    698   FT_CALLBACK_DEF( FT_Module_Interface )
    699   cff_get_interface( FT_Module    driver,       /* CFF_Driver */
    700                      const char*  module_interface )
    701   {
    702     FT_Library           library;
    703     FT_Module            sfnt;
    704     FT_Module_Interface  result;
    705 
    706 
    707     /* CFF_SERVICES_GET derefers `library' in PIC mode */
    708 #ifdef FT_CONFIG_OPTION_PIC
    709     if ( !driver )
    710       return NULL;
    711     library = driver->library;
    712     if ( !library )
    713       return NULL;
    714 #endif
    715 
    716     result = ft_service_list_lookup( CFF_SERVICES_GET, module_interface );
    717     if ( result != NULL )
    718       return result;
    719 
    720     /* `driver' is not yet evaluated in non-PIC mode */
    721 #ifndef FT_CONFIG_OPTION_PIC
    722     if ( !driver )
    723       return NULL;
    724     library = driver->library;
    725     if ( !library )
    726       return NULL;
    727 #endif
    728 
    729     /* we pass our request to the `sfnt' module */
    730     sfnt = FT_Get_Module( library, "sfnt" );
    731 
    732     return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0;
    733   }
    734 
    735 
    736   /* The FT_DriverInterface structure is defined in ftdriver.h. */
    737 
    738 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
    739 #define CFF_SIZE_SELECT cff_size_select
    740 #else
    741 #define CFF_SIZE_SELECT 0
    742 #endif
    743 
    744   FT_DEFINE_DRIVER(
    745     cff_driver_class,
    746 
    747       FT_MODULE_FONT_DRIVER       |
    748       FT_MODULE_DRIVER_SCALABLE   |
    749       FT_MODULE_DRIVER_HAS_HINTER,
    750 
    751       sizeof ( CFF_DriverRec ),
    752       "cff",
    753       0x10000L,
    754       0x20000L,
    755 
    756       0,   /* module-specific interface */
    757 
    758       cff_driver_init,
    759       cff_driver_done,
    760       cff_get_interface,
    761 
    762     /* now the specific driver fields */
    763     sizeof ( TT_FaceRec ),
    764     sizeof ( CFF_SizeRec ),
    765     sizeof ( CFF_GlyphSlotRec ),
    766 
    767     cff_face_init,
    768     cff_face_done,
    769     cff_size_init,
    770     cff_size_done,
    771     cff_slot_init,
    772     cff_slot_done,
    773 
    774     cff_glyph_load,
    775 
    776     cff_get_kerning,
    777     0,                       /* FT_Face_AttachFunc */
    778     cff_get_advances,
    779 
    780     cff_size_request,
    781 
    782     CFF_SIZE_SELECT
    783   )
    784 
    785 
    786 /* END */
    787