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