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