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