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     FT_TRACE1(( "cff_glyph_load: glyph index %d\n", glyph_index ));
    168 
    169     /* check whether we want a scaled outline or bitmap */
    170     if ( !size )
    171       load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
    172 
    173     /* reset the size object if necessary */
    174     if ( load_flags & FT_LOAD_NO_SCALE )
    175       size = NULL;
    176 
    177     if ( size )
    178     {
    179       /* these two objects must have the same parent */
    180       if ( cffsize->face != cffslot->face )
    181         return FT_THROW( Invalid_Face_Handle );
    182     }
    183 
    184     /* now load the glyph outline if necessary */
    185     error = cff_slot_load( slot, size, glyph_index, load_flags );
    186 
    187     /* force drop-out mode to 2 - irrelevant now */
    188     /* slot->outline.dropout_mode = 2; */
    189 
    190     return error;
    191   }
    192 
    193 
    194   FT_CALLBACK_DEF( FT_Error )
    195   cff_get_advances( FT_Face    face,
    196                     FT_UInt    start,
    197                     FT_UInt    count,
    198                     FT_Int32   flags,
    199                     FT_Fixed*  advances )
    200   {
    201     FT_UInt       nn;
    202     FT_Error      error = FT_Err_Ok;
    203     FT_GlyphSlot  slot  = face->glyph;
    204 
    205 
    206     flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
    207 
    208     for ( nn = 0; nn < count; nn++ )
    209     {
    210       error = cff_glyph_load( slot, face->size, start + nn, flags );
    211       if ( error )
    212         break;
    213 
    214       advances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
    215                      ? slot->linearVertAdvance
    216                      : slot->linearHoriAdvance;
    217     }
    218 
    219     return error;
    220   }
    221 
    222 
    223   /*
    224    *  GLYPH DICT SERVICE
    225    *
    226    */
    227 
    228   static FT_Error
    229   cff_get_glyph_name( CFF_Face    face,
    230                       FT_UInt     glyph_index,
    231                       FT_Pointer  buffer,
    232                       FT_UInt     buffer_max )
    233   {
    234     CFF_Font    font   = (CFF_Font)face->extra.data;
    235     FT_String*  gname;
    236     FT_UShort   sid;
    237     FT_Error    error;
    238 
    239 
    240     if ( !font->psnames )
    241     {
    242       FT_ERROR(( "cff_get_glyph_name:"
    243                  " cannot get glyph name from CFF & CEF fonts\n"
    244                  "                   "
    245                  " without the `PSNames' module\n" ));
    246       error = FT_THROW( Missing_Module );
    247       goto Exit;
    248     }
    249 
    250     /* first, locate the sid in the charset table */
    251     sid = font->charset.sids[glyph_index];
    252 
    253     /* now, lookup the name itself */
    254     gname = cff_index_get_sid_string( font, sid );
    255 
    256     if ( gname )
    257       FT_STRCPYN( buffer, gname, buffer_max );
    258 
    259     error = FT_Err_Ok;
    260 
    261   Exit:
    262     return error;
    263   }
    264 
    265 
    266   static FT_UInt
    267   cff_get_name_index( CFF_Face    face,
    268                       FT_String*  glyph_name )
    269   {
    270     CFF_Font            cff;
    271     CFF_Charset         charset;
    272     FT_Service_PsCMaps  psnames;
    273     FT_String*          name;
    274     FT_UShort           sid;
    275     FT_UInt             i;
    276 
    277 
    278     cff     = (CFF_FontRec *)face->extra.data;
    279     charset = &cff->charset;
    280 
    281     FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
    282     if ( !psnames )
    283       return 0;
    284 
    285     for ( i = 0; i < cff->num_glyphs; i++ )
    286     {
    287       sid = charset->sids[i];
    288 
    289       if ( sid > 390 )
    290         name = cff_index_get_string( cff, sid - 391 );
    291       else
    292         name = (FT_String *)psnames->adobe_std_strings( sid );
    293 
    294       if ( !name )
    295         continue;
    296 
    297       if ( !ft_strcmp( glyph_name, name ) )
    298         return i;
    299     }
    300 
    301     return 0;
    302   }
    303 
    304 
    305   FT_DEFINE_SERVICE_GLYPHDICTREC(
    306     cff_service_glyph_dict,
    307     (FT_GlyphDict_GetNameFunc)  cff_get_glyph_name,
    308     (FT_GlyphDict_NameIndexFunc)cff_get_name_index
    309   )
    310 
    311 
    312   /*
    313    *  POSTSCRIPT INFO SERVICE
    314    *
    315    */
    316 
    317   static FT_Int
    318   cff_ps_has_glyph_names( FT_Face  face )
    319   {
    320     return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0;
    321   }
    322 
    323 
    324   static FT_Error
    325   cff_ps_get_font_info( CFF_Face         face,
    326                         PS_FontInfoRec*  afont_info )
    327   {
    328     CFF_Font  cff   = (CFF_Font)face->extra.data;
    329     FT_Error  error = FT_Err_Ok;
    330 
    331 
    332     if ( cff && cff->font_info == NULL )
    333     {
    334       CFF_FontRecDict  dict   = &cff->top_font.font_dict;
    335       PS_FontInfoRec  *font_info = NULL;
    336       FT_Memory        memory = face->root.memory;
    337 
    338 
    339       if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) )
    340         goto Fail;
    341 
    342       font_info->version     = cff_index_get_sid_string( cff,
    343                                                          dict->version );
    344       font_info->notice      = cff_index_get_sid_string( cff,
    345                                                          dict->notice );
    346       font_info->full_name   = cff_index_get_sid_string( cff,
    347                                                          dict->full_name );
    348       font_info->family_name = cff_index_get_sid_string( cff,
    349                                                          dict->family_name );
    350       font_info->weight      = cff_index_get_sid_string( cff,
    351                                                          dict->weight );
    352       font_info->italic_angle        = dict->italic_angle;
    353       font_info->is_fixed_pitch      = dict->is_fixed_pitch;
    354       font_info->underline_position  = (FT_Short)dict->underline_position;
    355       font_info->underline_thickness = (FT_Short)dict->underline_thickness;
    356 
    357       cff->font_info = font_info;
    358     }
    359 
    360     if ( cff )
    361       *afont_info = *cff->font_info;
    362 
    363   Fail:
    364     return error;
    365   }
    366 
    367 
    368   FT_DEFINE_SERVICE_PSINFOREC(
    369     cff_service_ps_info,
    370     (PS_GetFontInfoFunc)   cff_ps_get_font_info,
    371     (PS_GetFontExtraFunc)  NULL,
    372     (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names,
    373     (PS_GetFontPrivateFunc)NULL,        /* unsupported with CFF fonts */
    374     (PS_GetFontValueFunc)  NULL         /* not implemented            */
    375   )
    376 
    377 
    378   /*
    379    *  POSTSCRIPT NAME SERVICE
    380    *
    381    */
    382 
    383   static const char*
    384   cff_get_ps_name( CFF_Face  face )
    385   {
    386     CFF_Font  cff = (CFF_Font)face->extra.data;
    387 
    388 
    389     return (const char*)cff->font_name;
    390   }
    391 
    392 
    393   FT_DEFINE_SERVICE_PSFONTNAMEREC(
    394     cff_service_ps_name,
    395     (FT_PsName_GetFunc)cff_get_ps_name
    396   )
    397 
    398 
    399   /*
    400    * TT CMAP INFO
    401    *
    402    * If the charmap is a synthetic Unicode encoding cmap or
    403    * a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO
    404    * service defined in SFNT module.
    405    *
    406    * Otherwise call the service function in the sfnt module.
    407    *
    408    */
    409   static FT_Error
    410   cff_get_cmap_info( FT_CharMap    charmap,
    411                      TT_CMapInfo  *cmap_info )
    412   {
    413     FT_CMap   cmap  = FT_CMAP( charmap );
    414     FT_Error  error = FT_Err_Ok;
    415 
    416     FT_Face     face    = FT_CMAP_FACE( cmap );
    417     FT_Library  library = FT_FACE_LIBRARY( face );
    418 
    419 
    420     cmap_info->language = 0;
    421     cmap_info->format   = 0;
    422 
    423     if ( cmap->clazz != &CFF_CMAP_ENCODING_CLASS_REC_GET &&
    424          cmap->clazz != &CFF_CMAP_UNICODE_CLASS_REC_GET  )
    425     {
    426       FT_Module           sfnt    = FT_Get_Module( library, "sfnt" );
    427       FT_Service_TTCMaps  service =
    428         (FT_Service_TTCMaps)ft_module_get_service( sfnt,
    429                                                    FT_SERVICE_ID_TT_CMAP );
    430 
    431 
    432       if ( service && service->get_cmap_info )
    433         error = service->get_cmap_info( charmap, cmap_info );
    434     }
    435 
    436     return error;
    437   }
    438 
    439 
    440   FT_DEFINE_SERVICE_TTCMAPSREC(
    441     cff_service_get_cmap_info,
    442     (TT_CMap_Info_GetFunc)cff_get_cmap_info
    443   )
    444 
    445 
    446   /*
    447    *  CID INFO SERVICE
    448    *
    449    */
    450   static FT_Error
    451   cff_get_ros( CFF_Face      face,
    452                const char*  *registry,
    453                const char*  *ordering,
    454                FT_Int       *supplement )
    455   {
    456     FT_Error  error = FT_Err_Ok;
    457     CFF_Font  cff   = (CFF_Font)face->extra.data;
    458 
    459 
    460     if ( cff )
    461     {
    462       CFF_FontRecDict  dict = &cff->top_font.font_dict;
    463 
    464 
    465       if ( dict->cid_registry == 0xFFFFU )
    466       {
    467         error = FT_THROW( Invalid_Argument );
    468         goto Fail;
    469       }
    470 
    471       if ( registry )
    472       {
    473         if ( cff->registry == NULL )
    474           cff->registry = cff_index_get_sid_string( cff,
    475                                                     dict->cid_registry );
    476         *registry = cff->registry;
    477       }
    478 
    479       if ( ordering )
    480       {
    481         if ( cff->ordering == NULL )
    482           cff->ordering = cff_index_get_sid_string( cff,
    483                                                     dict->cid_ordering );
    484         *ordering = cff->ordering;
    485       }
    486 
    487       /*
    488        * XXX: According to Adobe TechNote #5176, the supplement in CFF
    489        *      can be a real number. We truncate it to fit public API
    490        *      since freetype-2.3.6.
    491        */
    492       if ( supplement )
    493       {
    494         if ( dict->cid_supplement < FT_INT_MIN ||
    495              dict->cid_supplement > FT_INT_MAX )
    496           FT_TRACE1(( "cff_get_ros: too large supplement %d is truncated\n",
    497                       dict->cid_supplement ));
    498         *supplement = (FT_Int)dict->cid_supplement;
    499       }
    500     }
    501 
    502   Fail:
    503     return error;
    504   }
    505 
    506 
    507   static FT_Error
    508   cff_get_is_cid( CFF_Face  face,
    509                   FT_Bool  *is_cid )
    510   {
    511     FT_Error  error = FT_Err_Ok;
    512     CFF_Font  cff   = (CFF_Font)face->extra.data;
    513 
    514 
    515     *is_cid = 0;
    516 
    517     if ( cff )
    518     {
    519       CFF_FontRecDict  dict = &cff->top_font.font_dict;
    520 
    521 
    522       if ( dict->cid_registry != 0xFFFFU )
    523         *is_cid = 1;
    524     }
    525 
    526     return error;
    527   }
    528 
    529 
    530   static FT_Error
    531   cff_get_cid_from_glyph_index( CFF_Face  face,
    532                                 FT_UInt   glyph_index,
    533                                 FT_UInt  *cid )
    534   {
    535     FT_Error  error = FT_Err_Ok;
    536     CFF_Font  cff;
    537 
    538 
    539     cff = (CFF_Font)face->extra.data;
    540 
    541     if ( cff )
    542     {
    543       FT_UInt          c;
    544       CFF_FontRecDict  dict = &cff->top_font.font_dict;
    545 
    546 
    547       if ( dict->cid_registry == 0xFFFFU )
    548       {
    549         error = FT_THROW( Invalid_Argument );
    550         goto Fail;
    551       }
    552 
    553       if ( glyph_index > cff->num_glyphs )
    554       {
    555         error = FT_THROW( Invalid_Argument );
    556         goto Fail;
    557       }
    558 
    559       c = cff->charset.sids[glyph_index];
    560 
    561       if ( cid )
    562         *cid = c;
    563     }
    564 
    565   Fail:
    566     return error;
    567   }
    568 
    569 
    570   FT_DEFINE_SERVICE_CIDREC(
    571     cff_service_cid_info,
    572     (FT_CID_GetRegistryOrderingSupplementFunc)cff_get_ros,
    573     (FT_CID_GetIsInternallyCIDKeyedFunc)      cff_get_is_cid,
    574     (FT_CID_GetCIDFromGlyphIndexFunc)         cff_get_cid_from_glyph_index
    575   )
    576 
    577 
    578   /*
    579    *  PROPERTY SERVICE
    580    *
    581    */
    582   static FT_Error
    583   cff_property_set( FT_Module    module,         /* CFF_Driver */
    584                     const char*  property_name,
    585                     const void*  value )
    586   {
    587     FT_Error    error  = FT_Err_Ok;
    588     CFF_Driver  driver = (CFF_Driver)module;
    589 
    590 
    591     if ( !ft_strcmp( property_name, "darkening-parameters" ) )
    592     {
    593       FT_Int*  darken_params = (FT_Int*)value;
    594 
    595       FT_Int  x1 = darken_params[0];
    596       FT_Int  y1 = darken_params[1];
    597       FT_Int  x2 = darken_params[2];
    598       FT_Int  y2 = darken_params[3];
    599       FT_Int  x3 = darken_params[4];
    600       FT_Int  y3 = darken_params[5];
    601       FT_Int  x4 = darken_params[6];
    602       FT_Int  y4 = darken_params[7];
    603 
    604 
    605       if ( x1 < 0   || x2 < 0   || x3 < 0   || x4 < 0   ||
    606            y1 < 0   || y2 < 0   || y3 < 0   || y4 < 0   ||
    607            x1 > x2  || x2 > x3  || x3 > x4              ||
    608            y1 > 500 || y2 > 500 || y3 > 500 || y4 > 500 )
    609         return FT_THROW( Invalid_Argument );
    610 
    611       driver->darken_params[0] = x1;
    612       driver->darken_params[1] = y1;
    613       driver->darken_params[2] = x2;
    614       driver->darken_params[3] = y2;
    615       driver->darken_params[4] = x3;
    616       driver->darken_params[5] = y3;
    617       driver->darken_params[6] = x4;
    618       driver->darken_params[7] = y4;
    619 
    620       return error;
    621     }
    622     else if ( !ft_strcmp( property_name, "hinting-engine" ) )
    623     {
    624       FT_UInt*  hinting_engine = (FT_UInt*)value;
    625 
    626 
    627 #ifndef CFF_CONFIG_OPTION_OLD_ENGINE
    628       if ( *hinting_engine != FT_CFF_HINTING_ADOBE )
    629         error = FT_ERR( Unimplemented_Feature );
    630       else
    631 #endif
    632         driver->hinting_engine = *hinting_engine;
    633 
    634       return error;
    635     }
    636     else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
    637     {
    638       FT_Bool*  no_stem_darkening = (FT_Bool*)value;
    639 
    640 
    641       driver->no_stem_darkening = *no_stem_darkening;
    642 
    643       return error;
    644     }
    645 
    646     FT_TRACE0(( "cff_property_set: missing property `%s'\n",
    647                 property_name ));
    648     return FT_THROW( Missing_Property );
    649   }
    650 
    651 
    652   static FT_Error
    653   cff_property_get( FT_Module    module,         /* CFF_Driver */
    654                     const char*  property_name,
    655                     const void*  value )
    656   {
    657     FT_Error    error  = FT_Err_Ok;
    658     CFF_Driver  driver = (CFF_Driver)module;
    659 
    660 
    661     if ( !ft_strcmp( property_name, "darkening-parameters" ) )
    662     {
    663       FT_Int*  darken_params = driver->darken_params;
    664       FT_Int*  val           = (FT_Int*)value;
    665 
    666 
    667       val[0] = darken_params[0];
    668       val[1] = darken_params[1];
    669       val[2] = darken_params[2];
    670       val[3] = darken_params[3];
    671       val[4] = darken_params[4];
    672       val[5] = darken_params[5];
    673       val[6] = darken_params[6];
    674       val[7] = darken_params[7];
    675 
    676       return error;
    677     }
    678     else if ( !ft_strcmp( property_name, "hinting-engine" ) )
    679     {
    680       FT_UInt   hinting_engine    = driver->hinting_engine;
    681       FT_UInt*  val               = (FT_UInt*)value;
    682 
    683 
    684       *val = hinting_engine;
    685 
    686       return error;
    687     }
    688     else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
    689     {
    690       FT_Bool   no_stem_darkening = driver->no_stem_darkening;
    691       FT_Bool*  val               = (FT_Bool*)value;
    692 
    693 
    694       *val = no_stem_darkening;
    695 
    696       return error;
    697     }
    698 
    699     FT_TRACE0(( "cff_property_get: missing property `%s'\n",
    700                 property_name ));
    701     return FT_THROW( Missing_Property );
    702   }
    703 
    704 
    705   FT_DEFINE_SERVICE_PROPERTIESREC(
    706     cff_service_properties,
    707     (FT_Properties_SetFunc)cff_property_set,
    708     (FT_Properties_GetFunc)cff_property_get )
    709 
    710 
    711   /*************************************************************************/
    712   /*************************************************************************/
    713   /*************************************************************************/
    714   /****                                                                 ****/
    715   /****                                                                 ****/
    716   /****                D R I V E R  I N T E R F A C E                   ****/
    717   /****                                                                 ****/
    718   /****                                                                 ****/
    719   /*************************************************************************/
    720   /*************************************************************************/
    721   /*************************************************************************/
    722 
    723 #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
    724   FT_DEFINE_SERVICEDESCREC7(
    725     cff_services,
    726     FT_SERVICE_ID_XF86_NAME,            FT_XF86_FORMAT_CFF,
    727     FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
    728     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
    729     FT_SERVICE_ID_GLYPH_DICT,           &CFF_SERVICE_GLYPH_DICT_GET,
    730     FT_SERVICE_ID_TT_CMAP,              &CFF_SERVICE_GET_CMAP_INFO_GET,
    731     FT_SERVICE_ID_CID,                  &CFF_SERVICE_CID_INFO_GET,
    732     FT_SERVICE_ID_PROPERTIES,           &CFF_SERVICE_PROPERTIES_GET
    733   )
    734 #else
    735   FT_DEFINE_SERVICEDESCREC6(
    736     cff_services,
    737     FT_SERVICE_ID_XF86_NAME,            FT_XF86_FORMAT_CFF,
    738     FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
    739     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
    740     FT_SERVICE_ID_TT_CMAP,              &CFF_SERVICE_GET_CMAP_INFO_GET,
    741     FT_SERVICE_ID_CID,                  &CFF_SERVICE_CID_INFO_GET,
    742     FT_SERVICE_ID_PROPERTIES,           &CFF_SERVICE_PROPERTIES_GET
    743   )
    744 #endif
    745 
    746 
    747   FT_CALLBACK_DEF( FT_Module_Interface )
    748   cff_get_interface( FT_Module    driver,       /* CFF_Driver */
    749                      const char*  module_interface )
    750   {
    751     FT_Library           library;
    752     FT_Module            sfnt;
    753     FT_Module_Interface  result;
    754 
    755 
    756     /* CFF_SERVICES_GET derefers `library' in PIC mode */
    757 #ifdef FT_CONFIG_OPTION_PIC
    758     if ( !driver )
    759       return NULL;
    760     library = driver->library;
    761     if ( !library )
    762       return NULL;
    763 #endif
    764 
    765     result = ft_service_list_lookup( CFF_SERVICES_GET, module_interface );
    766     if ( result != NULL )
    767       return result;
    768 
    769     /* `driver' is not yet evaluated in non-PIC mode */
    770 #ifndef FT_CONFIG_OPTION_PIC
    771     if ( !driver )
    772       return NULL;
    773     library = driver->library;
    774     if ( !library )
    775       return NULL;
    776 #endif
    777 
    778     /* we pass our request to the `sfnt' module */
    779     sfnt = FT_Get_Module( library, "sfnt" );
    780 
    781     return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0;
    782   }
    783 
    784 
    785   /* The FT_DriverInterface structure is defined in ftdriver.h. */
    786 
    787 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
    788 #define CFF_SIZE_SELECT cff_size_select
    789 #else
    790 #define CFF_SIZE_SELECT 0
    791 #endif
    792 
    793   FT_DEFINE_DRIVER(
    794     cff_driver_class,
    795 
    796       FT_MODULE_FONT_DRIVER       |
    797       FT_MODULE_DRIVER_SCALABLE   |
    798       FT_MODULE_DRIVER_HAS_HINTER,
    799 
    800       sizeof ( CFF_DriverRec ),
    801       "cff",
    802       0x10000L,
    803       0x20000L,
    804 
    805       0,   /* module-specific interface */
    806 
    807       cff_driver_init,
    808       cff_driver_done,
    809       cff_get_interface,
    810 
    811     /* now the specific driver fields */
    812     sizeof ( TT_FaceRec ),
    813     sizeof ( CFF_SizeRec ),
    814     sizeof ( CFF_GlyphSlotRec ),
    815 
    816     cff_face_init,
    817     cff_face_done,
    818     cff_size_init,
    819     cff_size_done,
    820     cff_slot_init,
    821     cff_slot_done,
    822 
    823     cff_glyph_load,
    824 
    825     cff_get_kerning,
    826     0,                       /* FT_Face_AttachFunc */
    827     cff_get_advances,
    828 
    829     cff_size_request,
    830 
    831     CFF_SIZE_SELECT
    832   )
    833 
    834 
    835 /* END */
    836