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
t1_get_glyph_name(T1_Face face,FT_UInt glyph_index,FT_Pointer buffer,FT_UInt buffer_max)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
t1_get_name_index(T1_Face face,FT_String * glyph_name)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*
t1_get_ps_name(T1_Face face)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
t1_ps_get_font_info(FT_Face face,PS_FontInfoRec * afont_info)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
t1_ps_get_font_extra(FT_Face face,PS_FontExtraRec * afont_extra)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
t1_ps_has_glyph_names(FT_Face face)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
t1_ps_get_font_private(FT_Face face,PS_PrivateRec * afont_private)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
t1_ps_get_font_value(FT_Face face,PS_Dict_Keys key,FT_UInt idx,void * value,FT_Long value_len_)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 )
Get_Interface(FT_Module module,const FT_String * t1_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
Get_Kerning(FT_Face t1face,FT_UInt left_glyph,FT_UInt right_glyph,FT_Vector * kerning)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