Home | History | Annotate | Download | only in type1
      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 */
    774