cffdrivr.c revision 727dee178a392d20eb050d0c446f2fcc29058fa1
1/***************************************************************************/
2/*                                                                         */
3/*  cffdrivr.c                                                             */
4/*                                                                         */
5/*    OpenType font driver implementation (body).                          */
6/*                                                                         */
7/*  Copyright 1996-2013 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 FT_FREETYPE_H
21#include FT_INTERNAL_DEBUG_H
22#include FT_INTERNAL_STREAM_H
23#include FT_INTERNAL_SFNT_H
24#include FT_SERVICE_CID_H
25#include FT_SERVICE_POSTSCRIPT_INFO_H
26#include FT_SERVICE_POSTSCRIPT_NAME_H
27#include FT_SERVICE_TT_CMAP_H
28
29#include "cffdrivr.h"
30#include "cffgload.h"
31#include "cffload.h"
32#include "cffcmap.h"
33#include "cffparse.h"
34
35#include "cfferrs.h"
36#include "cffpic.h"
37
38#include FT_SERVICE_XFREE86_NAME_H
39#include FT_SERVICE_GLYPH_DICT_H
40#include FT_SERVICE_PROPERTIES_H
41#include FT_CFF_DRIVER_H
42
43
44  /*************************************************************************/
45  /*                                                                       */
46  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
47  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
48  /* messages during execution.                                            */
49  /*                                                                       */
50#undef  FT_COMPONENT
51#define FT_COMPONENT  trace_cffdriver
52
53
54  /*************************************************************************/
55  /*************************************************************************/
56  /*************************************************************************/
57  /****                                                                 ****/
58  /****                                                                 ****/
59  /****                          F A C E S                              ****/
60  /****                                                                 ****/
61  /****                                                                 ****/
62  /*************************************************************************/
63  /*************************************************************************/
64  /*************************************************************************/
65
66
67#undef  PAIR_TAG
68#define PAIR_TAG( left, right )  ( ( (FT_ULong)left << 16 ) | \
69                                     (FT_ULong)right        )
70
71
72  /*************************************************************************/
73  /*                                                                       */
74  /* <Function>                                                            */
75  /*    cff_get_kerning                                                    */
76  /*                                                                       */
77  /* <Description>                                                         */
78  /*    A driver method used to return the kerning vector between two      */
79  /*    glyphs of the same face.                                           */
80  /*                                                                       */
81  /* <Input>                                                               */
82  /*    face        :: A handle to the source face object.                 */
83  /*                                                                       */
84  /*    left_glyph  :: The index of the left glyph in the kern pair.       */
85  /*                                                                       */
86  /*    right_glyph :: The index of the right glyph in the kern pair.      */
87  /*                                                                       */
88  /* <Output>                                                              */
89  /*    kerning     :: The kerning vector.  This is in font units for      */
90  /*                   scalable formats, and in pixels for fixed-sizes     */
91  /*                   formats.                                            */
92  /*                                                                       */
93  /* <Return>                                                              */
94  /*    FreeType error code.  0 means success.                             */
95  /*                                                                       */
96  /* <Note>                                                                */
97  /*    Only horizontal layouts (left-to-right & right-to-left) are        */
98  /*    supported by this function.  Other layouts, or more sophisticated  */
99  /*    kernings, are out of scope of this method (the basic driver        */
100  /*    interface is meant to be simple).                                  */
101  /*                                                                       */
102  /*    They can be implemented by format-specific interfaces.             */
103  /*                                                                       */
104  FT_CALLBACK_DEF( FT_Error )
105  cff_get_kerning( FT_Face     ttface,          /* TT_Face */
106                   FT_UInt     left_glyph,
107                   FT_UInt     right_glyph,
108                   FT_Vector*  kerning )
109  {
110    TT_Face       face = (TT_Face)ttface;
111    SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
112
113
114    kerning->x = 0;
115    kerning->y = 0;
116
117    if ( sfnt )
118      kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph );
119
120    return FT_Err_Ok;
121  }
122
123
124#undef PAIR_TAG
125
126
127  /*************************************************************************/
128  /*                                                                       */
129  /* <Function>                                                            */
130  /*    cff_glyph_load                                                     */
131  /*                                                                       */
132  /* <Description>                                                         */
133  /*    A driver method used to load a glyph within a given glyph slot.    */
134  /*                                                                       */
135  /* <Input>                                                               */
136  /*    slot        :: A handle to the target slot object where the glyph  */
137  /*                   will be loaded.                                     */
138  /*                                                                       */
139  /*    size        :: A handle to the source face size at which the glyph */
140  /*                   must be scaled, loaded, etc.                        */
141  /*                                                                       */
142  /*    glyph_index :: The index of the glyph in the font file.            */
143  /*                                                                       */
144  /*    load_flags  :: A flag indicating what to load for this glyph.  The */
145  /*                   FT_LOAD_??? constants can be used to control the    */
146  /*                   glyph loading process (e.g., whether the outline    */
147  /*                   should be scaled, whether to load bitmaps or not,   */
148  /*                   whether to hint the outline, etc).                  */
149  /*                                                                       */
150  /* <Return>                                                              */
151  /*    FreeType error code.  0 means success.                             */
152  /*                                                                       */
153  FT_CALLBACK_DEF( FT_Error )
154  cff_glyph_load( FT_GlyphSlot  cffslot,      /* CFF_GlyphSlot */
155                  FT_Size       cffsize,      /* CFF_Size      */
156                  FT_UInt       glyph_index,
157                  FT_Int32      load_flags )
158  {
159    FT_Error       error;
160    CFF_GlyphSlot  slot = (CFF_GlyphSlot)cffslot;
161    CFF_Size       size = (CFF_Size)cffsize;
162
163
164    if ( !slot )
165      return FT_THROW( Invalid_Slot_Handle );
166
167    /* check whether we want a scaled outline or bitmap */
168    if ( !size )
169      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
170
171    /* reset the size object if necessary */
172    if ( load_flags & FT_LOAD_NO_SCALE )
173      size = NULL;
174
175    if ( size )
176    {
177      /* these two objects must have the same parent */
178      if ( cffsize->face != cffslot->face )
179        return FT_THROW( Invalid_Face_Handle );
180    }
181
182    /* now load the glyph outline if necessary */
183    error = cff_slot_load( slot, size, glyph_index, load_flags );
184
185    /* force drop-out mode to 2 - irrelevant now */
186    /* slot->outline.dropout_mode = 2; */
187
188    return error;
189  }
190
191
192  FT_CALLBACK_DEF( FT_Error )
193  cff_get_advances( FT_Face    face,
194                    FT_UInt    start,
195                    FT_UInt    count,
196                    FT_Int32   flags,
197                    FT_Fixed*  advances )
198  {
199    FT_UInt       nn;
200    FT_Error      error = FT_Err_Ok;
201    FT_GlyphSlot  slot  = face->glyph;
202
203
204    flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
205
206    for ( nn = 0; nn < count; nn++ )
207    {
208      error = cff_glyph_load( slot, face->size, start + nn, flags );
209      if ( error )
210        break;
211
212      advances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
213                     ? slot->linearVertAdvance
214                     : slot->linearHoriAdvance;
215    }
216
217    return error;
218  }
219
220
221  /*
222   *  GLYPH DICT SERVICE
223   *
224   */
225
226  static FT_Error
227  cff_get_glyph_name( CFF_Face    face,
228                      FT_UInt     glyph_index,
229                      FT_Pointer  buffer,
230                      FT_UInt     buffer_max )
231  {
232    CFF_Font    font   = (CFF_Font)face->extra.data;
233    FT_String*  gname;
234    FT_UShort   sid;
235    FT_Error    error;
236
237
238    if ( !font->psnames )
239    {
240      FT_ERROR(( "cff_get_glyph_name:"
241                 " cannot get glyph name from CFF & CEF fonts\n"
242                 "                   "
243                 " without the `PSNames' module\n" ));
244      error = FT_THROW( Missing_Module );
245      goto Exit;
246    }
247
248    /* first, locate the sid in the charset table */
249    sid = font->charset.sids[glyph_index];
250
251    /* now, lookup the name itself */
252    gname = cff_index_get_sid_string( font, sid );
253
254    if ( gname )
255      FT_STRCPYN( buffer, gname, buffer_max );
256
257    error = FT_Err_Ok;
258
259  Exit:
260    return error;
261  }
262
263
264  static FT_UInt
265  cff_get_name_index( CFF_Face    face,
266                      FT_String*  glyph_name )
267  {
268    CFF_Font            cff;
269    CFF_Charset         charset;
270    FT_Service_PsCMaps  psnames;
271    FT_String*          name;
272    FT_UShort           sid;
273    FT_UInt             i;
274
275
276    cff     = (CFF_FontRec *)face->extra.data;
277    charset = &cff->charset;
278
279    FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
280    if ( !psnames )
281      return 0;
282
283    for ( i = 0; i < cff->num_glyphs; i++ )
284    {
285      sid = charset->sids[i];
286
287      if ( sid > 390 )
288        name = cff_index_get_string( cff, sid - 391 );
289      else
290        name = (FT_String *)psnames->adobe_std_strings( sid );
291
292      if ( !name )
293        continue;
294
295      if ( !ft_strcmp( glyph_name, name ) )
296        return i;
297    }
298
299    return 0;
300  }
301
302
303  FT_DEFINE_SERVICE_GLYPHDICTREC(
304    cff_service_glyph_dict,
305    (FT_GlyphDict_GetNameFunc)  cff_get_glyph_name,
306    (FT_GlyphDict_NameIndexFunc)cff_get_name_index
307  )
308
309
310  /*
311   *  POSTSCRIPT INFO SERVICE
312   *
313   */
314
315  static FT_Int
316  cff_ps_has_glyph_names( FT_Face  face )
317  {
318    return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0;
319  }
320
321
322  static FT_Error
323  cff_ps_get_font_info( CFF_Face         face,
324                        PS_FontInfoRec*  afont_info )
325  {
326    CFF_Font  cff   = (CFF_Font)face->extra.data;
327    FT_Error  error = FT_Err_Ok;
328
329
330    if ( cff && cff->font_info == NULL )
331    {
332      CFF_FontRecDict  dict   = &cff->top_font.font_dict;
333      PS_FontInfoRec  *font_info = NULL;
334      FT_Memory        memory = face->root.memory;
335
336
337      if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) )
338        goto Fail;
339
340      font_info->version     = cff_index_get_sid_string( cff,
341                                                         dict->version );
342      font_info->notice      = cff_index_get_sid_string( cff,
343                                                         dict->notice );
344      font_info->full_name   = cff_index_get_sid_string( cff,
345                                                         dict->full_name );
346      font_info->family_name = cff_index_get_sid_string( cff,
347                                                         dict->family_name );
348      font_info->weight      = cff_index_get_sid_string( cff,
349                                                         dict->weight );
350      font_info->italic_angle        = dict->italic_angle;
351      font_info->is_fixed_pitch      = dict->is_fixed_pitch;
352      font_info->underline_position  = (FT_Short)dict->underline_position;
353      font_info->underline_thickness = (FT_Short)dict->underline_thickness;
354
355      cff->font_info = font_info;
356    }
357
358    if ( cff )
359      *afont_info = *cff->font_info;
360
361  Fail:
362    return error;
363  }
364
365
366  FT_DEFINE_SERVICE_PSINFOREC(
367    cff_service_ps_info,
368    (PS_GetFontInfoFunc)   cff_ps_get_font_info,
369    (PS_GetFontExtraFunc)  NULL,
370    (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names,
371    (PS_GetFontPrivateFunc)NULL,        /* unsupported with CFF fonts */
372    (PS_GetFontValueFunc)  NULL         /* not implemented            */
373  )
374
375
376  /*
377   *  POSTSCRIPT NAME SERVICE
378   *
379   */
380
381  static const char*
382  cff_get_ps_name( CFF_Face  face )
383  {
384    CFF_Font  cff = (CFF_Font)face->extra.data;
385
386
387    return (const char*)cff->font_name;
388  }
389
390
391  FT_DEFINE_SERVICE_PSFONTNAMEREC(
392    cff_service_ps_name,
393    (FT_PsName_GetFunc)cff_get_ps_name
394  )
395
396
397  /*
398   * TT CMAP INFO
399   *
400   * If the charmap is a synthetic Unicode encoding cmap or
401   * a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO
402   * service defined in SFNT module.
403   *
404   * Otherwise call the service function in the sfnt module.
405   *
406   */
407  static FT_Error
408  cff_get_cmap_info( FT_CharMap    charmap,
409                     TT_CMapInfo  *cmap_info )
410  {
411    FT_CMap   cmap  = FT_CMAP( charmap );
412    FT_Error  error = FT_Err_Ok;
413
414    FT_Face     face    = FT_CMAP_FACE( cmap );
415    FT_Library  library = FT_FACE_LIBRARY( face );
416
417
418    cmap_info->language = 0;
419    cmap_info->format   = 0;
420
421    if ( cmap->clazz != &CFF_CMAP_ENCODING_CLASS_REC_GET &&
422         cmap->clazz != &CFF_CMAP_UNICODE_CLASS_REC_GET  )
423    {
424      FT_Module           sfnt    = FT_Get_Module( library, "sfnt" );
425      FT_Service_TTCMaps  service =
426        (FT_Service_TTCMaps)ft_module_get_service( sfnt,
427                                                   FT_SERVICE_ID_TT_CMAP );
428
429
430      if ( service && service->get_cmap_info )
431        error = service->get_cmap_info( charmap, cmap_info );
432    }
433
434    return error;
435  }
436
437
438  FT_DEFINE_SERVICE_TTCMAPSREC(
439    cff_service_get_cmap_info,
440    (TT_CMap_Info_GetFunc)cff_get_cmap_info
441  )
442
443
444  /*
445   *  CID INFO SERVICE
446   *
447   */
448  static FT_Error
449  cff_get_ros( CFF_Face      face,
450               const char*  *registry,
451               const char*  *ordering,
452               FT_Int       *supplement )
453  {
454    FT_Error  error = FT_Err_Ok;
455    CFF_Font  cff   = (CFF_Font)face->extra.data;
456
457
458    if ( cff )
459    {
460      CFF_FontRecDict  dict = &cff->top_font.font_dict;
461
462
463      if ( dict->cid_registry == 0xFFFFU )
464      {
465        error = FT_THROW( Invalid_Argument );
466        goto Fail;
467      }
468
469      if ( registry )
470      {
471        if ( cff->registry == NULL )
472          cff->registry = cff_index_get_sid_string( cff,
473                                                    dict->cid_registry );
474        *registry = cff->registry;
475      }
476
477      if ( ordering )
478      {
479        if ( cff->ordering == NULL )
480          cff->ordering = cff_index_get_sid_string( cff,
481                                                    dict->cid_ordering );
482        *ordering = cff->ordering;
483      }
484
485      /*
486       * XXX: According to Adobe TechNote #5176, the supplement in CFF
487       *      can be a real number. We truncate it to fit public API
488       *      since freetype-2.3.6.
489       */
490      if ( supplement )
491      {
492        if ( dict->cid_supplement < FT_INT_MIN ||
493             dict->cid_supplement > FT_INT_MAX )
494          FT_TRACE1(( "cff_get_ros: too large supplement %d is truncated\n",
495                      dict->cid_supplement ));
496        *supplement = (FT_Int)dict->cid_supplement;
497      }
498    }
499
500  Fail:
501    return error;
502  }
503
504
505  static FT_Error
506  cff_get_is_cid( CFF_Face  face,
507                  FT_Bool  *is_cid )
508  {
509    FT_Error  error = FT_Err_Ok;
510    CFF_Font  cff   = (CFF_Font)face->extra.data;
511
512
513    *is_cid = 0;
514
515    if ( cff )
516    {
517      CFF_FontRecDict  dict = &cff->top_font.font_dict;
518
519
520      if ( dict->cid_registry != 0xFFFFU )
521        *is_cid = 1;
522    }
523
524    return error;
525  }
526
527
528  static FT_Error
529  cff_get_cid_from_glyph_index( CFF_Face  face,
530                                FT_UInt   glyph_index,
531                                FT_UInt  *cid )
532  {
533    FT_Error  error = FT_Err_Ok;
534    CFF_Font  cff;
535
536
537    cff = (CFF_Font)face->extra.data;
538
539    if ( cff )
540    {
541      FT_UInt          c;
542      CFF_FontRecDict  dict = &cff->top_font.font_dict;
543
544
545      if ( dict->cid_registry == 0xFFFFU )
546      {
547        error = FT_THROW( Invalid_Argument );
548        goto Fail;
549      }
550
551      if ( glyph_index > cff->num_glyphs )
552      {
553        error = FT_THROW( Invalid_Argument );
554        goto Fail;
555      }
556
557      c = cff->charset.sids[glyph_index];
558
559      if ( cid )
560        *cid = c;
561    }
562
563  Fail:
564    return error;
565  }
566
567
568  FT_DEFINE_SERVICE_CIDREC(
569    cff_service_cid_info,
570    (FT_CID_GetRegistryOrderingSupplementFunc)cff_get_ros,
571    (FT_CID_GetIsInternallyCIDKeyedFunc)      cff_get_is_cid,
572    (FT_CID_GetCIDFromGlyphIndexFunc)         cff_get_cid_from_glyph_index
573  )
574
575
576  /*
577   *  PROPERTY SERVICE
578   *
579   */
580  static FT_Error
581  cff_property_set( FT_Module    module,         /* CFF_Driver */
582                    const char*  property_name,
583                    const void*  value )
584  {
585    FT_Error    error  = FT_Err_Ok;
586    CFF_Driver  driver = (CFF_Driver)module;
587
588
589    if ( !ft_strcmp( property_name, "hinting-engine" ) )
590    {
591      FT_UInt*  hinting_engine = (FT_UInt*)value;
592
593
594#ifndef CFF_CONFIG_OPTION_OLD_ENGINE
595      if ( *hinting_engine != FT_CFF_HINTING_ADOBE )
596        error = FT_ERR( Unimplemented_Feature );
597      else
598#endif
599        driver->hinting_engine = *hinting_engine;
600
601      return error;
602    }
603    else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
604    {
605      FT_Bool*  no_stem_darkening = (FT_Bool*)value;
606
607
608      driver->no_stem_darkening = *no_stem_darkening;
609
610      return error;
611    }
612
613    FT_TRACE0(( "cff_property_set: missing property `%s'\n",
614                property_name ));
615    return FT_THROW( Missing_Property );
616  }
617
618
619  static FT_Error
620  cff_property_get( FT_Module    module,         /* CFF_Driver */
621                    const char*  property_name,
622                    const void*  value )
623  {
624    FT_Error    error  = FT_Err_Ok;
625    CFF_Driver  driver = (CFF_Driver)module;
626
627    FT_UInt  hinting_engine    = driver->hinting_engine;
628    FT_Bool  no_stem_darkening = driver->no_stem_darkening;
629
630
631    if ( !ft_strcmp( property_name, "hinting-engine" ) )
632    {
633      FT_UInt*  val = (FT_UInt*)value;
634
635
636      *val = hinting_engine;
637
638      return error;
639    }
640    else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
641    {
642      FT_Bool*  val = (FT_Bool*)value;
643
644
645      *val = no_stem_darkening;
646
647      return error;
648    }
649
650    FT_TRACE0(( "cff_property_get: missing property `%s'\n",
651                property_name ));
652    return FT_THROW( Missing_Property );
653  }
654
655
656  FT_DEFINE_SERVICE_PROPERTIESREC(
657    cff_service_properties,
658    (FT_Properties_SetFunc)cff_property_set,
659    (FT_Properties_GetFunc)cff_property_get )
660
661
662  /*************************************************************************/
663  /*************************************************************************/
664  /*************************************************************************/
665  /****                                                                 ****/
666  /****                                                                 ****/
667  /****                D R I V E R  I N T E R F A C E                   ****/
668  /****                                                                 ****/
669  /****                                                                 ****/
670  /*************************************************************************/
671  /*************************************************************************/
672  /*************************************************************************/
673
674#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
675  FT_DEFINE_SERVICEDESCREC7(
676    cff_services,
677    FT_SERVICE_ID_XF86_NAME,            FT_XF86_FORMAT_CFF,
678    FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
679    FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
680    FT_SERVICE_ID_GLYPH_DICT,           &CFF_SERVICE_GLYPH_DICT_GET,
681    FT_SERVICE_ID_TT_CMAP,              &CFF_SERVICE_GET_CMAP_INFO_GET,
682    FT_SERVICE_ID_CID,                  &CFF_SERVICE_CID_INFO_GET,
683    FT_SERVICE_ID_PROPERTIES,           &CFF_SERVICE_PROPERTIES_GET
684  )
685#else
686  FT_DEFINE_SERVICEDESCREC6(
687    cff_services,
688    FT_SERVICE_ID_XF86_NAME,            FT_XF86_FORMAT_CFF,
689    FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
690    FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
691    FT_SERVICE_ID_TT_CMAP,              &CFF_SERVICE_GET_CMAP_INFO_GET,
692    FT_SERVICE_ID_CID,                  &CFF_SERVICE_CID_INFO_GET,
693    FT_SERVICE_ID_PROPERTIES,           &CFF_SERVICE_PROPERTIES_GET
694  )
695#endif
696
697
698  FT_CALLBACK_DEF( FT_Module_Interface )
699  cff_get_interface( FT_Module    driver,       /* CFF_Driver */
700                     const char*  module_interface )
701  {
702    FT_Library           library;
703    FT_Module            sfnt;
704    FT_Module_Interface  result;
705
706
707    /* CFF_SERVICES_GET derefers `library' in PIC mode */
708#ifdef FT_CONFIG_OPTION_PIC
709    if ( !driver )
710      return NULL;
711    library = driver->library;
712    if ( !library )
713      return NULL;
714#endif
715
716    result = ft_service_list_lookup( CFF_SERVICES_GET, module_interface );
717    if ( result != NULL )
718      return result;
719
720    /* `driver' is not yet evaluated in non-PIC mode */
721#ifndef FT_CONFIG_OPTION_PIC
722    if ( !driver )
723      return NULL;
724    library = driver->library;
725    if ( !library )
726      return NULL;
727#endif
728
729    /* we pass our request to the `sfnt' module */
730    sfnt = FT_Get_Module( library, "sfnt" );
731
732    return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0;
733  }
734
735
736  /* The FT_DriverInterface structure is defined in ftdriver.h. */
737
738#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
739#define CFF_SIZE_SELECT cff_size_select
740#else
741#define CFF_SIZE_SELECT 0
742#endif
743
744  FT_DEFINE_DRIVER(
745    cff_driver_class,
746
747      FT_MODULE_FONT_DRIVER       |
748      FT_MODULE_DRIVER_SCALABLE   |
749      FT_MODULE_DRIVER_HAS_HINTER,
750
751      sizeof ( CFF_DriverRec ),
752      "cff",
753      0x10000L,
754      0x20000L,
755
756      0,   /* module-specific interface */
757
758      cff_driver_init,
759      cff_driver_done,
760      cff_get_interface,
761
762    /* now the specific driver fields */
763    sizeof ( TT_FaceRec ),
764    sizeof ( CFF_SizeRec ),
765    sizeof ( CFF_GlyphSlotRec ),
766
767    cff_face_init,
768    cff_face_done,
769    cff_size_init,
770    cff_size_done,
771    cff_slot_init,
772    cff_slot_done,
773
774    cff_glyph_load,
775
776    cff_get_kerning,
777    0,                       /* FT_Face_AttachFunc */
778    cff_get_advances,
779
780    cff_size_request,
781
782    CFF_SIZE_SELECT
783  )
784
785
786/* END */
787