Home | History | Annotate | Download | only in cff
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  cffdrivr.c                                                             */
      4 /*                                                                         */
      5 /*    OpenType font driver implementation (body).                          */
      6 /*                                                                         */
      7 /*  Copyright 1996-2015 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_FONT_FORMAT_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   /*************************************************************************/
     68   /*                                                                       */
     69   /* <Function>                                                            */
     70   /*    cff_get_kerning                                                    */
     71   /*                                                                       */
     72   /* <Description>                                                         */
     73   /*    A driver method used to return the kerning vector between two      */
     74   /*    glyphs of the same face.                                           */
     75   /*                                                                       */
     76   /* <Input>                                                               */
     77   /*    face        :: A handle to the source face object.                 */
     78   /*                                                                       */
     79   /*    left_glyph  :: The index of the left glyph in the kern pair.       */
     80   /*                                                                       */
     81   /*    right_glyph :: The index of the right glyph in the kern pair.      */
     82   /*                                                                       */
     83   /* <Output>                                                              */
     84   /*    kerning     :: The kerning vector.  This is in font units for      */
     85   /*                   scalable formats, and in pixels for fixed-sizes     */
     86   /*                   formats.                                            */
     87   /*                                                                       */
     88   /* <Return>                                                              */
     89   /*    FreeType error code.  0 means success.                             */
     90   /*                                                                       */
     91   /* <Note>                                                                */
     92   /*    Only horizontal layouts (left-to-right & right-to-left) are        */
     93   /*    supported by this function.  Other layouts, or more sophisticated  */
     94   /*    kernings, are out of scope of this method (the basic driver        */
     95   /*    interface is meant to be simple).                                  */
     96   /*                                                                       */
     97   /*    They can be implemented by format-specific interfaces.             */
     98   /*                                                                       */
     99   FT_CALLBACK_DEF( FT_Error )
    100   cff_get_kerning( FT_Face     ttface,          /* TT_Face */
    101                    FT_UInt     left_glyph,
    102                    FT_UInt     right_glyph,
    103                    FT_Vector*  kerning )
    104   {
    105     TT_Face       face = (TT_Face)ttface;
    106     SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
    107 
    108 
    109     kerning->x = 0;
    110     kerning->y = 0;
    111 
    112     if ( sfnt )
    113       kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph );
    114 
    115     return FT_Err_Ok;
    116   }
    117 
    118 
    119   /*************************************************************************/
    120   /*                                                                       */
    121   /* <Function>                                                            */
    122   /*    cff_glyph_load                                                     */
    123   /*                                                                       */
    124   /* <Description>                                                         */
    125   /*    A driver method used to load a glyph within a given glyph slot.    */
    126   /*                                                                       */
    127   /* <Input>                                                               */
    128   /*    slot        :: A handle to the target slot object where the glyph  */
    129   /*                   will be loaded.                                     */
    130   /*                                                                       */
    131   /*    size        :: A handle to the source face size at which the glyph */
    132   /*                   must be scaled, loaded, etc.                        */
    133   /*                                                                       */
    134   /*    glyph_index :: The index of the glyph in the font file.            */
    135   /*                                                                       */
    136   /*    load_flags  :: A flag indicating what to load for this glyph.  The */
    137   /*                   FT_LOAD_??? constants can be used to control the    */
    138   /*                   glyph loading process (e.g., whether the outline    */
    139   /*                   should be scaled, whether to load bitmaps or not,   */
    140   /*                   whether to hint the outline, etc).                  */
    141   /*                                                                       */
    142   /* <Return>                                                              */
    143   /*    FreeType error code.  0 means success.                             */
    144   /*                                                                       */
    145   FT_CALLBACK_DEF( FT_Error )
    146   cff_glyph_load( FT_GlyphSlot  cffslot,      /* CFF_GlyphSlot */
    147                   FT_Size       cffsize,      /* CFF_Size      */
    148                   FT_UInt       glyph_index,
    149                   FT_Int32      load_flags )
    150   {
    151     FT_Error       error;
    152     CFF_GlyphSlot  slot = (CFF_GlyphSlot)cffslot;
    153     CFF_Size       size = (CFF_Size)cffsize;
    154 
    155 
    156     if ( !slot )
    157       return FT_THROW( Invalid_Slot_Handle );
    158 
    159     FT_TRACE1(( "cff_glyph_load: glyph index %d\n", glyph_index ));
    160 
    161     /* check whether we want a scaled outline or bitmap */
    162     if ( !size )
    163       load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
    164 
    165     /* reset the size object if necessary */
    166     if ( load_flags & FT_LOAD_NO_SCALE )
    167       size = NULL;
    168 
    169     if ( size )
    170     {
    171       /* these two objects must have the same parent */
    172       if ( cffsize->face != cffslot->face )
    173         return FT_THROW( Invalid_Face_Handle );
    174     }
    175 
    176     /* now load the glyph outline if necessary */
    177     error = cff_slot_load( slot, size, glyph_index, load_flags );
    178 
    179     /* force drop-out mode to 2 - irrelevant now */
    180     /* slot->outline.dropout_mode = 2; */
    181 
    182     return error;
    183   }
    184 
    185 
    186   FT_CALLBACK_DEF( FT_Error )
    187   cff_get_advances( FT_Face    face,
    188                     FT_UInt    start,
    189                     FT_UInt    count,
    190                     FT_Int32   flags,
    191                     FT_Fixed*  advances )
    192   {
    193     FT_UInt       nn;
    194     FT_Error      error = FT_Err_Ok;
    195     FT_GlyphSlot  slot  = face->glyph;
    196 
    197 
    198     if ( FT_IS_SFNT( face ) )
    199     {
    200       /* OpenType 1.7 mandates that the data from `hmtx' table be used; */
    201       /* it is no longer necessary that those values are identical to   */
    202       /* the values in the `CFF' table                                  */
    203 
    204       TT_Face   ttface = (TT_Face)face;
    205       FT_Short  dummy;
    206 
    207 
    208       if ( flags & FT_LOAD_VERTICAL_LAYOUT )
    209       {
    210         /* check whether we have data from the `vmtx' table at all; */
    211         /* otherwise we extract the info from the CFF glyphstrings  */
    212         /* (instead of synthesizing a global value using the `OS/2' */
    213         /* table)                                                   */
    214         if ( !ttface->vertical_info )
    215           goto Missing_Table;
    216 
    217         for ( nn = 0; nn < count; nn++ )
    218         {
    219           FT_UShort  ah;
    220 
    221 
    222           ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface,
    223                                                        1,
    224                                                        start + nn,
    225                                                        &dummy,
    226                                                        &ah );
    227 
    228           FT_TRACE5(( "  idx %d: advance height %d font units\n",
    229                       start + nn, ah ));
    230           advances[nn] = ah;
    231         }
    232       }
    233       else
    234       {
    235         /* check whether we have data from the `hmtx' table at all */
    236         if ( !ttface->horizontal.number_Of_HMetrics )
    237           goto Missing_Table;
    238 
    239         for ( nn = 0; nn < count; nn++ )
    240         {
    241           FT_UShort  aw;
    242 
    243 
    244           ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface,
    245                                                        0,
    246                                                        start + nn,
    247                                                        &dummy,
    248                                                        &aw );
    249 
    250           FT_TRACE5(( "  idx %d: advance width %d font units\n",
    251                       start + nn, aw ));
    252           advances[nn] = aw;
    253         }
    254       }
    255 
    256       return error;
    257     }
    258 
    259   Missing_Table:
    260     flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
    261 
    262     for ( nn = 0; nn < count; nn++ )
    263     {
    264       error = cff_glyph_load( slot, face->size, start + nn, flags );
    265       if ( error )
    266         break;
    267 
    268       advances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
    269                      ? slot->linearVertAdvance
    270                      : slot->linearHoriAdvance;
    271     }
    272 
    273     return error;
    274   }
    275 
    276 
    277   /*
    278    *  GLYPH DICT SERVICE
    279    *
    280    */
    281 
    282   static FT_Error
    283   cff_get_glyph_name( CFF_Face    face,
    284                       FT_UInt     glyph_index,
    285                       FT_Pointer  buffer,
    286                       FT_UInt     buffer_max )
    287   {
    288     CFF_Font    font   = (CFF_Font)face->extra.data;
    289     FT_String*  gname;
    290     FT_UShort   sid;
    291     FT_Error    error;
    292 
    293 
    294     if ( !font->psnames )
    295     {
    296       FT_ERROR(( "cff_get_glyph_name:"
    297                  " cannot get glyph name from CFF & CEF fonts\n"
    298                  "                   "
    299                  " without the `PSNames' module\n" ));
    300       error = FT_THROW( Missing_Module );
    301       goto Exit;
    302     }
    303 
    304     /* first, locate the sid in the charset table */
    305     sid = font->charset.sids[glyph_index];
    306 
    307     /* now, lookup the name itself */
    308     gname = cff_index_get_sid_string( font, sid );
    309 
    310     if ( gname )
    311       FT_STRCPYN( buffer, gname, buffer_max );
    312 
    313     error = FT_Err_Ok;
    314 
    315   Exit:
    316     return error;
    317   }
    318 
    319 
    320   static FT_UInt
    321   cff_get_name_index( CFF_Face    face,
    322                       FT_String*  glyph_name )
    323   {
    324     CFF_Font            cff;
    325     CFF_Charset         charset;
    326     FT_Service_PsCMaps  psnames;
    327     FT_String*          name;
    328     FT_UShort           sid;
    329     FT_UInt             i;
    330 
    331 
    332     cff     = (CFF_FontRec *)face->extra.data;
    333     charset = &cff->charset;
    334 
    335     FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
    336     if ( !psnames )
    337       return 0;
    338 
    339     for ( i = 0; i < cff->num_glyphs; i++ )
    340     {
    341       sid = charset->sids[i];
    342 
    343       if ( sid > 390 )
    344         name = cff_index_get_string( cff, sid - 391 );
    345       else
    346         name = (FT_String *)psnames->adobe_std_strings( sid );
    347 
    348       if ( !name )
    349         continue;
    350 
    351       if ( !ft_strcmp( glyph_name, name ) )
    352         return i;
    353     }
    354 
    355     return 0;
    356   }
    357 
    358 
    359   FT_DEFINE_SERVICE_GLYPHDICTREC(
    360     cff_service_glyph_dict,
    361     (FT_GlyphDict_GetNameFunc)  cff_get_glyph_name,      /* get_name   */
    362     (FT_GlyphDict_NameIndexFunc)cff_get_name_index       /* name_index */
    363   )
    364 
    365 
    366   /*
    367    *  POSTSCRIPT INFO SERVICE
    368    *
    369    */
    370 
    371   static FT_Int
    372   cff_ps_has_glyph_names( FT_Face  face )
    373   {
    374     return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0;
    375   }
    376 
    377 
    378   static FT_Error
    379   cff_ps_get_font_info( CFF_Face         face,
    380                         PS_FontInfoRec*  afont_info )
    381   {
    382     CFF_Font  cff   = (CFF_Font)face->extra.data;
    383     FT_Error  error = FT_Err_Ok;
    384 
    385 
    386     if ( cff && cff->font_info == NULL )
    387     {
    388       CFF_FontRecDict  dict   = &cff->top_font.font_dict;
    389       PS_FontInfoRec  *font_info = NULL;
    390       FT_Memory        memory = face->root.memory;
    391 
    392 
    393       if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) )
    394         goto Fail;
    395 
    396       font_info->version     = cff_index_get_sid_string( cff,
    397                                                          dict->version );
    398       font_info->notice      = cff_index_get_sid_string( cff,
    399                                                          dict->notice );
    400       font_info->full_name   = cff_index_get_sid_string( cff,
    401                                                          dict->full_name );
    402       font_info->family_name = cff_index_get_sid_string( cff,
    403                                                          dict->family_name );
    404       font_info->weight      = cff_index_get_sid_string( cff,
    405                                                          dict->weight );
    406       font_info->italic_angle        = dict->italic_angle;
    407       font_info->is_fixed_pitch      = dict->is_fixed_pitch;
    408       font_info->underline_position  = (FT_Short)dict->underline_position;
    409       font_info->underline_thickness = (FT_UShort)dict->underline_thickness;
    410 
    411       cff->font_info = font_info;
    412     }
    413 
    414     if ( cff )
    415       *afont_info = *cff->font_info;
    416 
    417   Fail:
    418     return error;
    419   }
    420 
    421 
    422   FT_DEFINE_SERVICE_PSINFOREC(
    423     cff_service_ps_info,
    424     (PS_GetFontInfoFunc)   cff_ps_get_font_info,    /* ps_get_font_info    */
    425     (PS_GetFontExtraFunc)  NULL,                    /* ps_get_font_extra   */
    426     (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names,  /* ps_has_glyph_names  */
    427     /* unsupported with CFF fonts */
    428     (PS_GetFontPrivateFunc)NULL,                    /* ps_get_font_private */
    429     /* not implemented            */
    430     (PS_GetFontValueFunc)  NULL                     /* ps_get_font_value   */
    431   )
    432 
    433 
    434   /*
    435    *  POSTSCRIPT NAME SERVICE
    436    *
    437    */
    438 
    439   static const char*
    440   cff_get_ps_name( CFF_Face  face )
    441   {
    442     CFF_Font      cff  = (CFF_Font)face->extra.data;
    443     SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
    444 
    445 
    446     /* following the OpenType specification 1.7, we return the name stored */
    447     /* in the `name' table for a CFF wrapped into an SFNT container        */
    448 
    449     if ( FT_IS_SFNT( FT_FACE( face ) ) && sfnt )
    450     {
    451       FT_Library             library     = FT_FACE_LIBRARY( face );
    452       FT_Module              sfnt_module = FT_Get_Module( library, "sfnt" );
    453       FT_Service_PsFontName  service     =
    454         (FT_Service_PsFontName)ft_module_get_service(
    455                                  sfnt_module,
    456                                  FT_SERVICE_ID_POSTSCRIPT_FONT_NAME );
    457 
    458 
    459       if ( service && service->get_ps_font_name )
    460         return service->get_ps_font_name( FT_FACE( face ) );
    461     }
    462 
    463     return (const char*)cff->font_name;
    464   }
    465 
    466 
    467   FT_DEFINE_SERVICE_PSFONTNAMEREC(
    468     cff_service_ps_name,
    469     (FT_PsName_GetFunc)cff_get_ps_name      /* get_ps_font_name */
    470   )
    471 
    472 
    473   /*
    474    * TT CMAP INFO
    475    *
    476    * If the charmap is a synthetic Unicode encoding cmap or
    477    * a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO
    478    * service defined in SFNT module.
    479    *
    480    * Otherwise call the service function in the sfnt module.
    481    *
    482    */
    483   static FT_Error
    484   cff_get_cmap_info( FT_CharMap    charmap,
    485                      TT_CMapInfo  *cmap_info )
    486   {
    487     FT_CMap   cmap  = FT_CMAP( charmap );
    488     FT_Error  error = FT_Err_Ok;
    489 
    490     FT_Face     face    = FT_CMAP_FACE( cmap );
    491     FT_Library  library = FT_FACE_LIBRARY( face );
    492 
    493 
    494     cmap_info->language = 0;
    495     cmap_info->format   = 0;
    496 
    497     if ( cmap->clazz != &CFF_CMAP_ENCODING_CLASS_REC_GET &&
    498          cmap->clazz != &CFF_CMAP_UNICODE_CLASS_REC_GET  )
    499     {
    500       FT_Module           sfnt    = FT_Get_Module( library, "sfnt" );
    501       FT_Service_TTCMaps  service =
    502         (FT_Service_TTCMaps)ft_module_get_service( sfnt,
    503                                                    FT_SERVICE_ID_TT_CMAP );
    504 
    505 
    506       if ( service && service->get_cmap_info )
    507         error = service->get_cmap_info( charmap, cmap_info );
    508     }
    509 
    510     return error;
    511   }
    512 
    513 
    514   FT_DEFINE_SERVICE_TTCMAPSREC(
    515     cff_service_get_cmap_info,
    516     (TT_CMap_Info_GetFunc)cff_get_cmap_info    /* get_cmap_info */
    517   )
    518 
    519 
    520   /*
    521    *  CID INFO SERVICE
    522    *
    523    */
    524   static FT_Error
    525   cff_get_ros( CFF_Face      face,
    526                const char*  *registry,
    527                const char*  *ordering,
    528                FT_Int       *supplement )
    529   {
    530     FT_Error  error = FT_Err_Ok;
    531     CFF_Font  cff   = (CFF_Font)face->extra.data;
    532 
    533 
    534     if ( cff )
    535     {
    536       CFF_FontRecDict  dict = &cff->top_font.font_dict;
    537 
    538 
    539       if ( dict->cid_registry == 0xFFFFU )
    540       {
    541         error = FT_THROW( Invalid_Argument );
    542         goto Fail;
    543       }
    544 
    545       if ( registry )
    546       {
    547         if ( cff->registry == NULL )
    548           cff->registry = cff_index_get_sid_string( cff,
    549                                                     dict->cid_registry );
    550         *registry = cff->registry;
    551       }
    552 
    553       if ( ordering )
    554       {
    555         if ( cff->ordering == NULL )
    556           cff->ordering = cff_index_get_sid_string( cff,
    557                                                     dict->cid_ordering );
    558         *ordering = cff->ordering;
    559       }
    560 
    561       /*
    562        * XXX: According to Adobe TechNote #5176, the supplement in CFF
    563        *      can be a real number. We truncate it to fit public API
    564        *      since freetype-2.3.6.
    565        */
    566       if ( supplement )
    567       {
    568         if ( dict->cid_supplement < FT_INT_MIN ||
    569              dict->cid_supplement > FT_INT_MAX )
    570           FT_TRACE1(( "cff_get_ros: too large supplement %d is truncated\n",
    571                       dict->cid_supplement ));
    572         *supplement = (FT_Int)dict->cid_supplement;
    573       }
    574     }
    575 
    576   Fail:
    577     return error;
    578   }
    579 
    580 
    581   static FT_Error
    582   cff_get_is_cid( CFF_Face  face,
    583                   FT_Bool  *is_cid )
    584   {
    585     FT_Error  error = FT_Err_Ok;
    586     CFF_Font  cff   = (CFF_Font)face->extra.data;
    587 
    588 
    589     *is_cid = 0;
    590 
    591     if ( cff )
    592     {
    593       CFF_FontRecDict  dict = &cff->top_font.font_dict;
    594 
    595 
    596       if ( dict->cid_registry != 0xFFFFU )
    597         *is_cid = 1;
    598     }
    599 
    600     return error;
    601   }
    602 
    603 
    604   static FT_Error
    605   cff_get_cid_from_glyph_index( CFF_Face  face,
    606                                 FT_UInt   glyph_index,
    607                                 FT_UInt  *cid )
    608   {
    609     FT_Error  error = FT_Err_Ok;
    610     CFF_Font  cff;
    611 
    612 
    613     cff = (CFF_Font)face->extra.data;
    614 
    615     if ( cff )
    616     {
    617       FT_UInt          c;
    618       CFF_FontRecDict  dict = &cff->top_font.font_dict;
    619 
    620 
    621       if ( dict->cid_registry == 0xFFFFU )
    622       {
    623         error = FT_THROW( Invalid_Argument );
    624         goto Fail;
    625       }
    626 
    627       if ( glyph_index > cff->num_glyphs )
    628       {
    629         error = FT_THROW( Invalid_Argument );
    630         goto Fail;
    631       }
    632 
    633       c = cff->charset.sids[glyph_index];
    634 
    635       if ( cid )
    636         *cid = c;
    637     }
    638 
    639   Fail:
    640     return error;
    641   }
    642 
    643 
    644   FT_DEFINE_SERVICE_CIDREC(
    645     cff_service_cid_info,
    646     (FT_CID_GetRegistryOrderingSupplementFunc)
    647       cff_get_ros,                             /* get_ros                  */
    648     (FT_CID_GetIsInternallyCIDKeyedFunc)
    649       cff_get_is_cid,                          /* get_is_cid               */
    650     (FT_CID_GetCIDFromGlyphIndexFunc)
    651       cff_get_cid_from_glyph_index             /* get_cid_from_glyph_index */
    652   )
    653 
    654 
    655   /*
    656    *  PROPERTY SERVICE
    657    *
    658    */
    659   static FT_Error
    660   cff_property_set( FT_Module    module,         /* CFF_Driver */
    661                     const char*  property_name,
    662                     const void*  value )
    663   {
    664     FT_Error    error  = FT_Err_Ok;
    665     CFF_Driver  driver = (CFF_Driver)module;
    666 
    667 
    668     if ( !ft_strcmp( property_name, "darkening-parameters" ) )
    669     {
    670       FT_Int*  darken_params = (FT_Int*)value;
    671 
    672       FT_Int  x1 = darken_params[0];
    673       FT_Int  y1 = darken_params[1];
    674       FT_Int  x2 = darken_params[2];
    675       FT_Int  y2 = darken_params[3];
    676       FT_Int  x3 = darken_params[4];
    677       FT_Int  y3 = darken_params[5];
    678       FT_Int  x4 = darken_params[6];
    679       FT_Int  y4 = darken_params[7];
    680 
    681 
    682       if ( x1 < 0   || x2 < 0   || x3 < 0   || x4 < 0   ||
    683            y1 < 0   || y2 < 0   || y3 < 0   || y4 < 0   ||
    684            x1 > x2  || x2 > x3  || x3 > x4              ||
    685            y1 > 500 || y2 > 500 || y3 > 500 || y4 > 500 )
    686         return FT_THROW( Invalid_Argument );
    687 
    688       driver->darken_params[0] = x1;
    689       driver->darken_params[1] = y1;
    690       driver->darken_params[2] = x2;
    691       driver->darken_params[3] = y2;
    692       driver->darken_params[4] = x3;
    693       driver->darken_params[5] = y3;
    694       driver->darken_params[6] = x4;
    695       driver->darken_params[7] = y4;
    696 
    697       return error;
    698     }
    699     else if ( !ft_strcmp( property_name, "hinting-engine" ) )
    700     {
    701       FT_UInt*  hinting_engine = (FT_UInt*)value;
    702 
    703 
    704 #ifndef CFF_CONFIG_OPTION_OLD_ENGINE
    705       if ( *hinting_engine != FT_CFF_HINTING_ADOBE )
    706         error = FT_ERR( Unimplemented_Feature );
    707       else
    708 #endif
    709         driver->hinting_engine = *hinting_engine;
    710 
    711       return error;
    712     }
    713     else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
    714     {
    715       FT_Bool*  no_stem_darkening = (FT_Bool*)value;
    716 
    717 
    718       driver->no_stem_darkening = *no_stem_darkening;
    719 
    720       return error;
    721     }
    722 
    723     FT_TRACE0(( "cff_property_set: missing property `%s'\n",
    724                 property_name ));
    725     return FT_THROW( Missing_Property );
    726   }
    727 
    728 
    729   static FT_Error
    730   cff_property_get( FT_Module    module,         /* CFF_Driver */
    731                     const char*  property_name,
    732                     const void*  value )
    733   {
    734     FT_Error    error  = FT_Err_Ok;
    735     CFF_Driver  driver = (CFF_Driver)module;
    736 
    737 
    738     if ( !ft_strcmp( property_name, "darkening-parameters" ) )
    739     {
    740       FT_Int*  darken_params = driver->darken_params;
    741       FT_Int*  val           = (FT_Int*)value;
    742 
    743 
    744       val[0] = darken_params[0];
    745       val[1] = darken_params[1];
    746       val[2] = darken_params[2];
    747       val[3] = darken_params[3];
    748       val[4] = darken_params[4];
    749       val[5] = darken_params[5];
    750       val[6] = darken_params[6];
    751       val[7] = darken_params[7];
    752 
    753       return error;
    754     }
    755     else if ( !ft_strcmp( property_name, "hinting-engine" ) )
    756     {
    757       FT_UInt   hinting_engine    = driver->hinting_engine;
    758       FT_UInt*  val               = (FT_UInt*)value;
    759 
    760 
    761       *val = hinting_engine;
    762 
    763       return error;
    764     }
    765     else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
    766     {
    767       FT_Bool   no_stem_darkening = driver->no_stem_darkening;
    768       FT_Bool*  val               = (FT_Bool*)value;
    769 
    770 
    771       *val = no_stem_darkening;
    772 
    773       return error;
    774     }
    775 
    776     FT_TRACE0(( "cff_property_get: missing property `%s'\n",
    777                 property_name ));
    778     return FT_THROW( Missing_Property );
    779   }
    780 
    781 
    782   FT_DEFINE_SERVICE_PROPERTIESREC(
    783     cff_service_properties,
    784     (FT_Properties_SetFunc)cff_property_set,      /* set_property */
    785     (FT_Properties_GetFunc)cff_property_get )     /* get_property */
    786 
    787 
    788   /*************************************************************************/
    789   /*************************************************************************/
    790   /*************************************************************************/
    791   /****                                                                 ****/
    792   /****                                                                 ****/
    793   /****                D R I V E R  I N T E R F A C E                   ****/
    794   /****                                                                 ****/
    795   /****                                                                 ****/
    796   /*************************************************************************/
    797   /*************************************************************************/
    798   /*************************************************************************/
    799 
    800 #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
    801   FT_DEFINE_SERVICEDESCREC7(
    802     cff_services,
    803     FT_SERVICE_ID_FONT_FORMAT,          FT_FONT_FORMAT_CFF,
    804     FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
    805     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
    806     FT_SERVICE_ID_GLYPH_DICT,           &CFF_SERVICE_GLYPH_DICT_GET,
    807     FT_SERVICE_ID_TT_CMAP,              &CFF_SERVICE_GET_CMAP_INFO_GET,
    808     FT_SERVICE_ID_CID,                  &CFF_SERVICE_CID_INFO_GET,
    809     FT_SERVICE_ID_PROPERTIES,           &CFF_SERVICE_PROPERTIES_GET
    810   )
    811 #else
    812   FT_DEFINE_SERVICEDESCREC6(
    813     cff_services,
    814     FT_SERVICE_ID_FONT_FORMAT,          FT_FONT_FORMAT_CFF,
    815     FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
    816     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
    817     FT_SERVICE_ID_TT_CMAP,              &CFF_SERVICE_GET_CMAP_INFO_GET,
    818     FT_SERVICE_ID_CID,                  &CFF_SERVICE_CID_INFO_GET,
    819     FT_SERVICE_ID_PROPERTIES,           &CFF_SERVICE_PROPERTIES_GET
    820   )
    821 #endif
    822 
    823 
    824   FT_CALLBACK_DEF( FT_Module_Interface )
    825   cff_get_interface( FT_Module    driver,       /* CFF_Driver */
    826                      const char*  module_interface )
    827   {
    828     FT_Library           library;
    829     FT_Module            sfnt;
    830     FT_Module_Interface  result;
    831 
    832 
    833     /* CFF_SERVICES_GET dereferences `library' in PIC mode */
    834 #ifdef FT_CONFIG_OPTION_PIC
    835     if ( !driver )
    836       return NULL;
    837     library = driver->library;
    838     if ( !library )
    839       return NULL;
    840 #endif
    841 
    842     result = ft_service_list_lookup( CFF_SERVICES_GET, module_interface );
    843     if ( result != NULL )
    844       return result;
    845 
    846     /* `driver' is not yet evaluated in non-PIC mode */
    847 #ifndef FT_CONFIG_OPTION_PIC
    848     if ( !driver )
    849       return NULL;
    850     library = driver->library;
    851     if ( !library )
    852       return NULL;
    853 #endif
    854 
    855     /* we pass our request to the `sfnt' module */
    856     sfnt = FT_Get_Module( library, "sfnt" );
    857 
    858     return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0;
    859   }
    860 
    861 
    862   /* The FT_DriverInterface structure is defined in ftdriver.h. */
    863 
    864 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
    865 #define CFF_SIZE_SELECT cff_size_select
    866 #else
    867 #define CFF_SIZE_SELECT 0
    868 #endif
    869 
    870   FT_DEFINE_DRIVER(
    871     cff_driver_class,
    872 
    873       FT_MODULE_FONT_DRIVER          |
    874       FT_MODULE_DRIVER_SCALABLE      |
    875       FT_MODULE_DRIVER_HAS_HINTER    |
    876       FT_MODULE_DRIVER_HINTS_LIGHTLY,
    877 
    878       sizeof ( CFF_DriverRec ),
    879       "cff",
    880       0x10000L,
    881       0x20000L,
    882 
    883       0,   /* module-specific interface */
    884 
    885       cff_driver_init,          /* FT_Module_Constructor  module_init   */
    886       cff_driver_done,          /* FT_Module_Destructor   module_done   */
    887       cff_get_interface,        /* FT_Module_Requester    get_interface */
    888 
    889     sizeof ( TT_FaceRec ),
    890     sizeof ( CFF_SizeRec ),
    891     sizeof ( CFF_GlyphSlotRec ),
    892 
    893     cff_face_init,              /* FT_Face_InitFunc  init_face */
    894     cff_face_done,              /* FT_Face_DoneFunc  done_face */
    895     cff_size_init,              /* FT_Size_InitFunc  init_size */
    896     cff_size_done,              /* FT_Size_DoneFunc  done_size */
    897     cff_slot_init,              /* FT_Slot_InitFunc  init_slot */
    898     cff_slot_done,              /* FT_Slot_DoneFunc  done_slot */
    899 
    900     cff_glyph_load,             /* FT_Slot_LoadFunc  load_glyph */
    901 
    902     cff_get_kerning,            /* FT_Face_GetKerningFunc   get_kerning  */
    903     0,                          /* FT_Face_AttachFunc       attach_file  */
    904     cff_get_advances,           /* FT_Face_GetAdvancesFunc  get_advances */
    905 
    906     cff_size_request,           /* FT_Size_RequestFunc  request_size */
    907     CFF_SIZE_SELECT             /* FT_Size_SelectFunc   select_size  */
    908   )
    909 
    910 
    911 /* END */
    912