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