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 */