1 /***************************************************************************/
   2 /*                                                                         */
   3 /*  t1driver.c                                                             */
   4 /*                                                                         */
   5 /*    Type 1 driver interface (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 "t1driver.h"
  21 #include "t1gload.h"
  22 #include "t1load.h"
  23 
  24 #include "t1errors.h"
  25 
  26 #ifndef T1_CONFIG_OPTION_NO_AFM
  27 #include "t1afm.h"
  28 #endif
  29 
  30 #include FT_INTERNAL_DEBUG_H
  31 #include FT_INTERNAL_STREAM_H
  32 #include FT_INTERNAL_HASH_H
  33 #include FT_INTERNAL_POSTSCRIPT_PROPS_H
  34 #include FT_DRIVER_H
  35 
  36 #include FT_SERVICE_MULTIPLE_MASTERS_H
  37 #include FT_SERVICE_GLYPH_DICT_H
  38 #include FT_SERVICE_FONT_FORMAT_H
  39 #include FT_SERVICE_POSTSCRIPT_NAME_H
  40 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
  41 #include FT_SERVICE_POSTSCRIPT_INFO_H
  42 #include FT_SERVICE_PROPERTIES_H
  43 #include FT_SERVICE_KERNING_H
  44 
  45 
  46   /*************************************************************************/
  47   /*                                                                       */
  48   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  49   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  50   /* messages during execution.                                            */
  51   /*                                                                       */
  52 #undef  FT_COMPONENT
  53 #define FT_COMPONENT  trace_t1driver
  54 
  55  /*
  56   *  GLYPH DICT SERVICE
  57   *
  58   */
  59 
  60   static FT_Error
  61   t1_get_glyph_name( T1_Face     face,
  62                      FT_UInt     glyph_index,
  63                      FT_Pointer  buffer,
  64                      FT_UInt     buffer_max )
  65   {
  66     FT_STRCPYN( buffer, face->type1.glyph_names[glyph_index], buffer_max );
  67 
  68     return FT_Err_Ok;
  69   }
  70 
  71 
  72   static FT_UInt
  73   t1_get_name_index( T1_Face     face,
  74                      FT_String*  glyph_name )
  75   {
  76     FT_Int  i;
  77 
  78 
  79     for ( i = 0; i < face->type1.num_glyphs; i++ )
  80     {
  81       FT_String*  gname = face->type1.glyph_names[i];
  82 
  83 
  84       if ( !ft_strcmp( glyph_name, gname ) )
  85         return (FT_UInt)i;
  86     }
  87 
  88     return 0;
  89   }
  90 
  91 
  92   static const FT_Service_GlyphDictRec  t1_service_glyph_dict =
  93   {
  94     (FT_GlyphDict_GetNameFunc)  t1_get_glyph_name,    /* get_name   */
  95     (FT_GlyphDict_NameIndexFunc)t1_get_name_index     /* name_index */
  96   };
  97 
  98 
  99   /*
 100    *  POSTSCRIPT NAME SERVICE
 101    *
 102    */
 103 
 104   static const char*
 105   t1_get_ps_name( T1_Face  face )
 106   {
 107     return (const char*) face->type1.font_name;
 108   }
 109 
 110 
 111   static const FT_Service_PsFontNameRec  t1_service_ps_name =
 112   {
 113     (FT_PsName_GetFunc)t1_get_ps_name     /* get_ps_font_name */
 114   };
 115 
 116 
 117   /*
 118    *  MULTIPLE MASTERS SERVICE
 119    *
 120    */
 121 
 122 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
 123   static const FT_Service_MultiMastersRec  t1_service_multi_masters =
 124   {
 125     (FT_Get_MM_Func)        T1_Get_Multi_Master,   /* get_mm         */
 126     (FT_Set_MM_Design_Func) T1_Set_MM_Design,      /* set_mm_design  */
 127     (FT_Set_MM_Blend_Func)  T1_Set_MM_Blend,       /* set_mm_blend   */
 128     (FT_Get_MM_Blend_Func)  T1_Get_MM_Blend,       /* get_mm_blend   */
 129     (FT_Get_MM_Var_Func)    T1_Get_MM_Var,         /* get_mm_var     */
 130     (FT_Set_Var_Design_Func)T1_Set_Var_Design,     /* set_var_design */
 131     (FT_Get_Var_Design_Func)T1_Get_Var_Design,     /* get_var_design */
 132     (FT_Set_Instance_Func)  T1_Reset_MM_Blend,     /* set_instance   */
 133 
 134     (FT_Get_Var_Blend_Func) NULL,                  /* get_var_blend  */
 135     (FT_Done_Blend_Func)    T1_Done_Blend          /* done_blend     */
 136   };
 137 #endif
 138 
 139 
 140   /*
 141    *  POSTSCRIPT INFO SERVICE
 142    *
 143    */
 144 
 145   static FT_Error
 146   t1_ps_get_font_info( FT_Face          face,
 147                        PS_FontInfoRec*  afont_info )
 148   {
 149     *afont_info = ((T1_Face)face)->type1.font_info;
 150 
 151     return FT_Err_Ok;
 152   }
 153 
 154 
 155   static FT_Error
 156   t1_ps_get_font_extra( FT_Face           face,
 157                         PS_FontExtraRec*  afont_extra )
 158   {
 159     *afont_extra = ((T1_Face)face)->type1.font_extra;
 160 
 161     return FT_Err_Ok;
 162   }
 163 
 164 
 165   static FT_Int
 166   t1_ps_has_glyph_names( FT_Face  face )
 167   {
 168     FT_UNUSED( face );
 169 
 170     return 1;
 171   }
 172 
 173 
 174   static FT_Error
 175   t1_ps_get_font_private( FT_Face         face,
 176                           PS_PrivateRec*  afont_private )
 177   {
 178     *afont_private = ((T1_Face)face)->type1.private_dict;
 179 
 180     return FT_Err_Ok;
 181   }
 182 
 183 
 184   static FT_Long
 185   t1_ps_get_font_value( FT_Face       face,
 186                         PS_Dict_Keys  key,
 187                         FT_UInt       idx,
 188                         void         *value,
 189                         FT_Long       value_len_ )
 190   {
 191     FT_ULong  retval    = 0; /* always >= 1 if valid */
 192     FT_ULong  value_len = value_len_ < 0 ? 0 : (FT_ULong)value_len_;
 193 
 194     T1_Face  t1face = (T1_Face)face;
 195     T1_Font  type1  = &t1face->type1;
 196 
 197 
 198     switch ( key )
 199     {
 200     case PS_DICT_FONT_TYPE:
 201       retval = sizeof ( type1->font_type );
 202       if ( value && value_len >= retval )
 203         *((FT_Byte *)value) = type1->font_type;
 204       break;
 205 
 206     case PS_DICT_FONT_MATRIX:
 207       if ( idx < sizeof ( type1->font_matrix ) /
 208                    sizeof ( type1->font_matrix.xx ) )
 209       {
 210         FT_Fixed  val = 0;
 211 
 212 
 213         retval = sizeof ( val );
 214         if ( value && value_len >= retval )
 215         {
 216           switch ( idx )
 217           {
 218           case 0:
 219             val = type1->font_matrix.xx;
 220             break;
 221           case 1:
 222             val = type1->font_matrix.xy;
 223             break;
 224           case 2:
 225             val = type1->font_matrix.yx;
 226             break;
 227           case 3:
 228             val = type1->font_matrix.yy;
 229             break;
 230           }
 231           *((FT_Fixed *)value) = val;
 232         }
 233       }
 234       break;
 235 
 236     case PS_DICT_FONT_BBOX:
 237       if ( idx < sizeof ( type1->font_bbox ) /
 238                    sizeof ( type1->font_bbox.xMin ) )
 239       {
 240         FT_Fixed  val = 0;
 241 
 242 
 243         retval = sizeof ( val );
 244         if ( value && value_len >= retval )
 245         {
 246           switch ( idx )
 247           {
 248           case 0:
 249             val = type1->font_bbox.xMin;
 250             break;
 251           case 1:
 252             val = type1->font_bbox.yMin;
 253             break;
 254           case 2:
 255             val = type1->font_bbox.xMax;
 256             break;
 257           case 3:
 258             val = type1->font_bbox.yMax;
 259             break;
 260           }
 261           *((FT_Fixed *)value) = val;
 262         }
 263       }
 264       break;
 265 
 266     case PS_DICT_PAINT_TYPE:
 267       retval = sizeof ( type1->paint_type );
 268       if ( value && value_len >= retval )
 269         *((FT_Byte *)value) = type1->paint_type;
 270       break;
 271 
 272     case PS_DICT_FONT_NAME:
 273       retval = ft_strlen( type1->font_name ) + 1;
 274       if ( value && value_len >= retval )
 275         ft_memcpy( value, (void *)( type1->font_name ), retval );
 276       break;
 277 
 278     case PS_DICT_UNIQUE_ID:
 279       retval = sizeof ( type1->private_dict.unique_id );
 280       if ( value && value_len >= retval )
 281         *((FT_Int *)value) = type1->private_dict.unique_id;
 282       break;
 283 
 284     case PS_DICT_NUM_CHAR_STRINGS:
 285       retval = sizeof ( type1->num_glyphs );
 286       if ( value && value_len >= retval )
 287         *((FT_Int *)value) = type1->num_glyphs;
 288       break;
 289 
 290     case PS_DICT_CHAR_STRING_KEY:
 291       if ( idx < (FT_UInt)type1->num_glyphs )
 292       {
 293         retval = ft_strlen( type1->glyph_names[idx] ) + 1;
 294         if ( value && value_len >= retval )
 295         {
 296           ft_memcpy( value, (void *)( type1->glyph_names[idx] ), retval );
 297           ((FT_Char *)value)[retval - 1] = (FT_Char)'\0';
 298         }
 299       }
 300       break;
 301 
 302     case PS_DICT_CHAR_STRING:
 303       if ( idx < (FT_UInt)type1->num_glyphs )
 304       {
 305         retval = type1->charstrings_len[idx] + 1;
 306         if ( value && value_len >= retval )
 307         {
 308           ft_memcpy( value, (void *)( type1->charstrings[idx] ),
 309                      retval - 1 );
 310           ((FT_Char *)value)[retval - 1] = (FT_Char)'\0';
 311         }
 312       }
 313       break;
 314 
 315     case PS_DICT_ENCODING_TYPE:
 316       retval = sizeof ( type1->encoding_type );
 317       if ( value && value_len >= retval )
 318         *((T1_EncodingType *)value) = type1->encoding_type;
 319       break;
 320 
 321     case PS_DICT_ENCODING_ENTRY:
 322       if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY &&
 323            idx < (FT_UInt)type1->encoding.num_chars       )
 324       {
 325         retval = ft_strlen( type1->encoding.char_name[idx] ) + 1;
 326         if ( value && value_len >= retval )
 327         {
 328           ft_memcpy( value, (void *)( type1->encoding.char_name[idx] ),
 329                      retval - 1 );
 330           ((FT_Char *)value)[retval - 1] = (FT_Char)'\0';
 331         }
 332       }
 333       break;
 334 
 335     case PS_DICT_NUM_SUBRS:
 336       retval = sizeof ( type1->num_subrs );
 337       if ( value && value_len >= retval )
 338         *((FT_Int *)value) = type1->num_subrs;
 339       break;
 340 
 341     case PS_DICT_SUBR:
 342       {
 343         FT_Bool  ok = 0;
 344 
 345 
 346         if ( type1->subrs_hash )
 347         {
 348           /* convert subr index to array index */
 349           size_t*  val = ft_hash_num_lookup( (FT_Int)idx,
 350                                              type1->subrs_hash );
 351 
 352 
 353           if ( val )
 354           {
 355             idx = *val;
 356             ok  = 1;
 357           }
 358         }
 359         else
 360         {
 361           if ( idx < (FT_UInt)type1->num_subrs )
 362             ok = 1;
 363         }
 364 
 365         if ( ok )
 366         {
 367           retval = type1->subrs_len[idx] + 1;
 368           if ( value && value_len >= retval )
 369           {
 370             ft_memcpy( value, (void *)( type1->subrs[idx] ), retval - 1 );
 371             ((FT_Char *)value)[retval - 1] = (FT_Char)'\0';
 372           }
 373         }
 374       }
 375       break;
 376 
 377     case PS_DICT_STD_HW:
 378       retval = sizeof ( type1->private_dict.standard_width[0] );
 379       if ( value && value_len >= retval )
 380         *((FT_UShort *)value) = type1->private_dict.standard_width[0];
 381       break;
 382 
 383     case PS_DICT_STD_VW:
 384       retval = sizeof ( type1->private_dict.standard_height[0] );
 385       if ( value && value_len >= retval )
 386         *((FT_UShort *)value) = type1->private_dict.standard_height[0];
 387       break;
 388 
 389     case PS_DICT_NUM_BLUE_VALUES:
 390       retval = sizeof ( type1->private_dict.num_blue_values );
 391       if ( value && value_len >= retval )
 392         *((FT_Byte *)value) = type1->private_dict.num_blue_values;
 393       break;
 394 
 395     case PS_DICT_BLUE_VALUE:
 396       if ( idx < type1->private_dict.num_blue_values )
 397       {
 398         retval = sizeof ( type1->private_dict.blue_values[idx] );
 399         if ( value && value_len >= retval )
 400           *((FT_Short *)value) = type1->private_dict.blue_values[idx];
 401       }
 402       break;
 403 
 404     case PS_DICT_BLUE_SCALE:
 405       retval = sizeof ( type1->private_dict.blue_scale );
 406       if ( value && value_len >= retval )
 407         *((FT_Fixed *)value) = type1->private_dict.blue_scale;
 408       break;
 409 
 410     case PS_DICT_BLUE_FUZZ:
 411       retval = sizeof ( type1->private_dict.blue_fuzz );
 412       if ( value && value_len >= retval )
 413         *((FT_Int *)value) = type1->private_dict.blue_fuzz;
 414       break;
 415 
 416     case PS_DICT_BLUE_SHIFT:
 417       retval = sizeof ( type1->private_dict.blue_shift );
 418       if ( value && value_len >= retval )
 419         *((FT_Int *)value) = type1->private_dict.blue_shift;
 420       break;
 421 
 422     case PS_DICT_NUM_OTHER_BLUES:
 423       retval = sizeof ( type1->private_dict.num_other_blues );
 424       if ( value && value_len >= retval )
 425         *((FT_Byte *)value) = type1->private_dict.num_other_blues;
 426       break;
 427 
 428     case PS_DICT_OTHER_BLUE:
 429       if ( idx < type1->private_dict.num_other_blues )
 430       {
 431         retval = sizeof ( type1->private_dict.other_blues[idx] );
 432         if ( value && value_len >= retval )
 433           *((FT_Short *)value) = type1->private_dict.other_blues[idx];
 434       }
 435       break;
 436 
 437     case PS_DICT_NUM_FAMILY_BLUES:
 438       retval = sizeof ( type1->private_dict.num_family_blues );
 439       if ( value && value_len >= retval )
 440         *((FT_Byte *)value) = type1->private_dict.num_family_blues;
 441       break;
 442 
 443     case PS_DICT_FAMILY_BLUE:
 444       if ( idx < type1->private_dict.num_family_blues )
 445       {
 446         retval = sizeof ( type1->private_dict.family_blues[idx] );
 447         if ( value && value_len >= retval )
 448           *((FT_Short *)value) = type1->private_dict.family_blues[idx];
 449       }
 450       break;
 451 
 452     case PS_DICT_NUM_FAMILY_OTHER_BLUES:
 453       retval = sizeof ( type1->private_dict.num_family_other_blues );
 454       if ( value && value_len >= retval )
 455         *((FT_Byte *)value) = type1->private_dict.num_family_other_blues;
 456       break;
 457 
 458     case PS_DICT_FAMILY_OTHER_BLUE:
 459       if ( idx < type1->private_dict.num_family_other_blues )
 460       {
 461         retval = sizeof ( type1->private_dict.family_other_blues[idx] );
 462         if ( value && value_len >= retval )
 463           *((FT_Short *)value) = type1->private_dict.family_other_blues[idx];
 464       }
 465       break;
 466 
 467     case PS_DICT_NUM_STEM_SNAP_H:
 468       retval = sizeof ( type1->private_dict.num_snap_widths );
 469       if ( value && value_len >= retval )
 470         *((FT_Byte *)value) = type1->private_dict.num_snap_widths;
 471       break;
 472 
 473     case PS_DICT_STEM_SNAP_H:
 474       if ( idx < type1->private_dict.num_snap_widths )
 475       {
 476         retval = sizeof ( type1->private_dict.snap_widths[idx] );
 477         if ( value && value_len >= retval )
 478           *((FT_Short *)value) = type1->private_dict.snap_widths[idx];
 479       }
 480       break;
 481 
 482     case PS_DICT_NUM_STEM_SNAP_V:
 483       retval = sizeof ( type1->private_dict.num_snap_heights );
 484       if ( value && value_len >= retval )
 485         *((FT_Byte *)value) = type1->private_dict.num_snap_heights;
 486       break;
 487 
 488     case PS_DICT_STEM_SNAP_V:
 489       if ( idx < type1->private_dict.num_snap_heights )
 490       {
 491         retval = sizeof ( type1->private_dict.snap_heights[idx] );
 492         if ( value && value_len >= retval )
 493           *((FT_Short *)value) = type1->private_dict.snap_heights[idx];
 494       }
 495       break;
 496 
 497     case PS_DICT_RND_STEM_UP:
 498       retval = sizeof ( type1->private_dict.round_stem_up );
 499       if ( value && value_len >= retval )
 500         *((FT_Bool *)value) = type1->private_dict.round_stem_up;
 501       break;
 502 
 503     case PS_DICT_FORCE_BOLD:
 504       retval = sizeof ( type1->private_dict.force_bold );
 505       if ( value && value_len >= retval )
 506         *((FT_Bool *)value) = type1->private_dict.force_bold;
 507       break;
 508 
 509     case PS_DICT_MIN_FEATURE:
 510       if ( idx < sizeof ( type1->private_dict.min_feature ) /
 511                    sizeof ( type1->private_dict.min_feature[0] ) )
 512       {
 513         retval = sizeof ( type1->private_dict.min_feature[idx] );
 514         if ( value && value_len >= retval )
 515           *((FT_Short *)value) = type1->private_dict.min_feature[idx];
 516       }
 517       break;
 518 
 519     case PS_DICT_LEN_IV:
 520       retval = sizeof ( type1->private_dict.lenIV );
 521       if ( value && value_len >= retval )
 522         *((FT_Int *)value) = type1->private_dict.lenIV;
 523       break;
 524 
 525     case PS_DICT_PASSWORD:
 526       retval = sizeof ( type1->private_dict.password );
 527       if ( value && value_len >= retval )
 528         *((FT_Long *)value) = type1->private_dict.password;
 529       break;
 530 
 531     case PS_DICT_LANGUAGE_GROUP:
 532       retval = sizeof ( type1->private_dict.language_group );
 533       if ( value && value_len >= retval )
 534         *((FT_Long *)value) = type1->private_dict.language_group;
 535       break;
 536 
 537     case PS_DICT_IS_FIXED_PITCH:
 538       retval = sizeof ( type1->font_info.is_fixed_pitch );
 539       if ( value && value_len >= retval )
 540         *((FT_Bool *)value) = type1->font_info.is_fixed_pitch;
 541       break;
 542 
 543     case PS_DICT_UNDERLINE_POSITION:
 544       retval = sizeof ( type1->font_info.underline_position );
 545       if ( value && value_len >= retval )
 546         *((FT_Short *)value) = type1->font_info.underline_position;
 547       break;
 548 
 549     case PS_DICT_UNDERLINE_THICKNESS:
 550       retval = sizeof ( type1->font_info.underline_thickness );
 551       if ( value && value_len >= retval )
 552         *((FT_UShort *)value) = type1->font_info.underline_thickness;
 553       break;
 554 
 555     case PS_DICT_FS_TYPE:
 556       retval = sizeof ( type1->font_extra.fs_type );
 557       if ( value && value_len >= retval )
 558         *((FT_UShort *)value) = type1->font_extra.fs_type;
 559       break;
 560 
 561     case PS_DICT_VERSION:
 562       retval = ft_strlen( type1->font_info.version ) + 1;
 563       if ( value && value_len >= retval )
 564         ft_memcpy( value, (void *)( type1->font_info.version ), retval );
 565       break;
 566 
 567     case PS_DICT_NOTICE:
 568       retval = ft_strlen( type1->font_info.notice ) + 1;
 569       if ( value && value_len >= retval )
 570         ft_memcpy( value, (void *)( type1->font_info.notice ), retval );
 571       break;
 572 
 573     case PS_DICT_FULL_NAME:
 574       retval = ft_strlen( type1->font_info.full_name ) + 1;
 575       if ( value && value_len >= retval )
 576         ft_memcpy( value, (void *)( type1->font_info.full_name ), retval );
 577       break;
 578 
 579     case PS_DICT_FAMILY_NAME:
 580       retval = ft_strlen( type1->font_info.family_name ) + 1;
 581       if ( value && value_len >= retval )
 582         ft_memcpy( value, (void *)( type1->font_info.family_name ), retval );
 583       break;
 584 
 585     case PS_DICT_WEIGHT:
 586       retval = ft_strlen( type1->font_info.weight ) + 1;
 587       if ( value && value_len >= retval )
 588         ft_memcpy( value, (void *)( type1->font_info.weight ), retval );
 589       break;
 590 
 591     case PS_DICT_ITALIC_ANGLE:
 592       retval = sizeof ( type1->font_info.italic_angle );
 593       if ( value && value_len >= retval )
 594         *((FT_Long *)value) = type1->font_info.italic_angle;
 595       break;
 596     }
 597 
 598     return retval == 0 ? -1 : (FT_Long)retval;
 599   }
 600 
 601 
 602   static const FT_Service_PsInfoRec  t1_service_ps_info =
 603   {
 604     (PS_GetFontInfoFunc)   t1_ps_get_font_info,    /* ps_get_font_info    */
 605     (PS_GetFontExtraFunc)  t1_ps_get_font_extra,   /* ps_get_font_extra   */
 606     (PS_HasGlyphNamesFunc) t1_ps_has_glyph_names,  /* ps_has_glyph_names  */
 607     (PS_GetFontPrivateFunc)t1_ps_get_font_private, /* ps_get_font_private */
 608     (PS_GetFontValueFunc)  t1_ps_get_font_value,   /* ps_get_font_value   */
 609   };
 610 
 611 
 612 #ifndef T1_CONFIG_OPTION_NO_AFM
 613   static const FT_Service_KerningRec  t1_service_kerning =
 614   {
 615     T1_Get_Track_Kerning,       /* get_track */
 616   };
 617 #endif
 618 
 619 
 620   /*
 621    *  PROPERTY SERVICE
 622    *
 623    */
 624 
 625   FT_DEFINE_SERVICE_PROPERTIESREC(
 626     t1_service_properties,
 627 
 628     (FT_Properties_SetFunc)ps_property_set,      /* set_property */
 629     (FT_Properties_GetFunc)ps_property_get )     /* get_property */
 630 
 631 
 632   /*
 633    *  SERVICE LIST
 634    *
 635    */
 636 
 637   static const FT_ServiceDescRec  t1_services[] =
 638   {
 639     { FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &t1_service_ps_name },
 640     { FT_SERVICE_ID_GLYPH_DICT,           &t1_service_glyph_dict },
 641     { FT_SERVICE_ID_FONT_FORMAT,          FT_FONT_FORMAT_TYPE_1 },
 642     { FT_SERVICE_ID_POSTSCRIPT_INFO,      &t1_service_ps_info },
 643     { FT_SERVICE_ID_PROPERTIES,           &t1_service_properties },
 644 
 645 #ifndef T1_CONFIG_OPTION_NO_AFM
 646     { FT_SERVICE_ID_KERNING,              &t1_service_kerning },
 647 #endif
 648 
 649 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
 650     { FT_SERVICE_ID_MULTI_MASTERS,        &t1_service_multi_masters },
 651 #endif
 652     { NULL, NULL }
 653   };
 654 
 655 
 656   FT_CALLBACK_DEF( FT_Module_Interface )
 657   Get_Interface( FT_Module         module,
 658                  const FT_String*  t1_interface )
 659   {
 660     FT_UNUSED( module );
 661 
 662     return ft_service_list_lookup( t1_services, t1_interface );
 663   }
 664 
 665 
 666 #ifndef T1_CONFIG_OPTION_NO_AFM
 667 
 668   /*************************************************************************/
 669   /*                                                                       */
 670   /* <Function>                                                            */
 671   /*    Get_Kerning                                                        */
 672   /*                                                                       */
 673   /* <Description>                                                         */
 674   /*    A driver method used to return the kerning vector between two      */
 675   /*    glyphs of the same face.                                           */
 676   /*                                                                       */
 677   /* <Input>                                                               */
 678   /*    face        :: A handle to the source face object.                 */
 679   /*                                                                       */
 680   /*    left_glyph  :: The index of the left glyph in the kern pair.       */
 681   /*                                                                       */
 682   /*    right_glyph :: The index of the right glyph in the kern pair.      */
 683   /*                                                                       */
 684   /* <Output>                                                              */
 685   /*    kerning     :: The kerning vector.  This is in font units for      */
 686   /*                   scalable formats, and in pixels for fixed-sizes     */
 687   /*                   formats.                                            */
 688   /*                                                                       */
 689   /* <Return>                                                              */
 690   /*    FreeType error code.  0 means success.                             */
 691   /*                                                                       */
 692   /* <Note>                                                                */
 693   /*    Only horizontal layouts (left-to-right & right-to-left) are        */
 694   /*    supported by this function.  Other layouts, or more sophisticated  */
 695   /*    kernings are out of scope of this method (the basic driver         */
 696   /*    interface is meant to be simple).                                  */
 697   /*                                                                       */
 698   /*    They can be implemented by format-specific interfaces.             */
 699   /*                                                                       */
 700   static FT_Error
 701   Get_Kerning( FT_Face     t1face,        /* T1_Face */
 702                FT_UInt     left_glyph,
 703                FT_UInt     right_glyph,
 704                FT_Vector*  kerning )
 705   {
 706     T1_Face  face = (T1_Face)t1face;
 707 
 708 
 709     kerning->x = 0;
 710     kerning->y = 0;
 711 
 712     if ( face->afm_data )
 713       T1_Get_Kerning( (AFM_FontInfo)face->afm_data,
 714                       left_glyph,
 715                       right_glyph,
 716                       kerning );
 717 
 718     return FT_Err_Ok;
 719   }
 720 
 721 
 722 #endif /* T1_CONFIG_OPTION_NO_AFM */
 723 
 724 
 725   FT_CALLBACK_TABLE_DEF
 726   const FT_Driver_ClassRec  t1_driver_class =
 727   {
 728     {
 729       FT_MODULE_FONT_DRIVER       |
 730       FT_MODULE_DRIVER_SCALABLE   |
 731       FT_MODULE_DRIVER_HAS_HINTER,
 732 
 733       sizeof ( PS_DriverRec ),
 734 
 735       "type1",
 736       0x10000L,
 737       0x20000L,
 738 
 739       NULL,    /* module-specific interface */
 740 
 741       T1_Driver_Init,           /* FT_Module_Constructor  module_init   */
 742       T1_Driver_Done,           /* FT_Module_Destructor   module_done   */
 743       Get_Interface,            /* FT_Module_Requester    get_interface */
 744     },
 745 
 746     sizeof ( T1_FaceRec ),
 747     sizeof ( T1_SizeRec ),
 748     sizeof ( T1_GlyphSlotRec ),
 749 
 750     T1_Face_Init,               /* FT_Face_InitFunc  init_face */
 751     T1_Face_Done,               /* FT_Face_DoneFunc  done_face */
 752     T1_Size_Init,               /* FT_Size_InitFunc  init_size */
 753     T1_Size_Done,               /* FT_Size_DoneFunc  done_size */
 754     T1_GlyphSlot_Init,          /* FT_Slot_InitFunc  init_slot */
 755     T1_GlyphSlot_Done,          /* FT_Slot_DoneFunc  done_slot */
 756 
 757     T1_Load_Glyph,              /* FT_Slot_LoadFunc  load_glyph */
 758 
 759 #ifdef T1_CONFIG_OPTION_NO_AFM
 760     NULL,                       /* FT_Face_GetKerningFunc   get_kerning  */
 761     NULL,                       /* FT_Face_AttachFunc       attach_file  */
 762 #else
 763     Get_Kerning,                /* FT_Face_GetKerningFunc   get_kerning  */
 764     T1_Read_Metrics,            /* FT_Face_AttachFunc       attach_file  */
 765 #endif
 766     T1_Get_Advances,            /* FT_Face_GetAdvancesFunc  get_advances */
 767 
 768     T1_Size_Request,            /* FT_Size_RequestFunc  request_size */
 769     NULL                        /* FT_Size_SelectFunc   select_size  */
 770   };
 771 
 772 
 773 /* END */