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