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    FT_TRACE1(( "cff_glyph_load: glyph index %d\n", glyph_index ));
168
169    /* check whether we want a scaled outline or bitmap */
170    if ( !size )
171      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
172
173    /* reset the size object if necessary */
174    if ( load_flags & FT_LOAD_NO_SCALE )
175      size = NULL;
176
177    if ( size )
178    {
179      /* these two objects must have the same parent */
180      if ( cffsize->face != cffslot->face )
181        return FT_THROW( Invalid_Face_Handle );
182    }
183
184    /* now load the glyph outline if necessary */
185    error = cff_slot_load( slot, size, glyph_index, load_flags );
186
187    /* force drop-out mode to 2 - irrelevant now */
188    /* slot->outline.dropout_mode = 2; */
189
190    return error;
191  }
192
193
194  FT_CALLBACK_DEF( FT_Error )
195  cff_get_advances( FT_Face    face,
196                    FT_UInt    start,
197                    FT_UInt    count,
198                    FT_Int32   flags,
199                    FT_Fixed*  advances )
200  {
201    FT_UInt       nn;
202    FT_Error      error = FT_Err_Ok;
203    FT_GlyphSlot  slot  = face->glyph;
204
205
206    flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
207
208    for ( nn = 0; nn < count; nn++ )
209    {
210      error = cff_glyph_load( slot, face->size, start + nn, flags );
211      if ( error )
212        break;
213
214      advances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
215                     ? slot->linearVertAdvance
216                     : slot->linearHoriAdvance;
217    }
218
219    return error;
220  }
221
222
223  /*
224   *  GLYPH DICT SERVICE
225   *
226   */
227
228  static FT_Error
229  cff_get_glyph_name( CFF_Face    face,
230                      FT_UInt     glyph_index,
231                      FT_Pointer  buffer,
232                      FT_UInt     buffer_max )
233  {
234    CFF_Font    font   = (CFF_Font)face->extra.data;
235    FT_String*  gname;
236    FT_UShort   sid;
237    FT_Error    error;
238
239
240    if ( !font->psnames )
241    {
242      FT_ERROR(( "cff_get_glyph_name:"
243                 " cannot get glyph name from CFF & CEF fonts\n"
244                 "                   "
245                 " without the `PSNames' module\n" ));
246      error = FT_THROW( Missing_Module );
247      goto Exit;
248    }
249
250    /* first, locate the sid in the charset table */
251    sid = font->charset.sids[glyph_index];
252
253    /* now, lookup the name itself */
254    gname = cff_index_get_sid_string( font, sid );
255
256    if ( gname )
257      FT_STRCPYN( buffer, gname, buffer_max );
258
259    error = FT_Err_Ok;
260
261  Exit:
262    return error;
263  }
264
265
266  static FT_UInt
267  cff_get_name_index( CFF_Face    face,
268                      FT_String*  glyph_name )
269  {
270    CFF_Font            cff;
271    CFF_Charset         charset;
272    FT_Service_PsCMaps  psnames;
273    FT_String*          name;
274    FT_UShort           sid;
275    FT_UInt             i;
276
277
278    cff     = (CFF_FontRec *)face->extra.data;
279    charset = &cff->charset;
280
281    FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
282    if ( !psnames )
283      return 0;
284
285    for ( i = 0; i < cff->num_glyphs; i++ )
286    {
287      sid = charset->sids[i];
288
289      if ( sid > 390 )
290        name = cff_index_get_string( cff, sid - 391 );
291      else
292        name = (FT_String *)psnames->adobe_std_strings( sid );
293
294      if ( !name )
295        continue;
296
297      if ( !ft_strcmp( glyph_name, name ) )
298        return i;
299    }
300
301    return 0;
302  }
303
304
305  FT_DEFINE_SERVICE_GLYPHDICTREC(
306    cff_service_glyph_dict,
307    (FT_GlyphDict_GetNameFunc)  cff_get_glyph_name,
308    (FT_GlyphDict_NameIndexFunc)cff_get_name_index
309  )
310
311
312  /*
313   *  POSTSCRIPT INFO SERVICE
314   *
315   */
316
317  static FT_Int
318  cff_ps_has_glyph_names( FT_Face  face )
319  {
320    return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0;
321  }
322
323
324  static FT_Error
325  cff_ps_get_font_info( CFF_Face         face,
326                        PS_FontInfoRec*  afont_info )
327  {
328    CFF_Font  cff   = (CFF_Font)face->extra.data;
329    FT_Error  error = FT_Err_Ok;
330
331
332    if ( cff && cff->font_info == NULL )
333    {
334      CFF_FontRecDict  dict   = &cff->top_font.font_dict;
335      PS_FontInfoRec  *font_info = NULL;
336      FT_Memory        memory = face->root.memory;
337
338
339      if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) )
340        goto Fail;
341
342      font_info->version     = cff_index_get_sid_string( cff,
343                                                         dict->version );
344      font_info->notice      = cff_index_get_sid_string( cff,
345                                                         dict->notice );
346      font_info->full_name   = cff_index_get_sid_string( cff,
347                                                         dict->full_name );
348      font_info->family_name = cff_index_get_sid_string( cff,
349                                                         dict->family_name );
350      font_info->weight      = cff_index_get_sid_string( cff,
351                                                         dict->weight );
352      font_info->italic_angle        = dict->italic_angle;
353      font_info->is_fixed_pitch      = dict->is_fixed_pitch;
354      font_info->underline_position  = (FT_Short)dict->underline_position;
355      font_info->underline_thickness = (FT_Short)dict->underline_thickness;
356
357      cff->font_info = font_info;
358    }
359
360    if ( cff )
361      *afont_info = *cff->font_info;
362
363  Fail:
364    return error;
365  }
366
367
368  FT_DEFINE_SERVICE_PSINFOREC(
369    cff_service_ps_info,
370    (PS_GetFontInfoFunc)   cff_ps_get_font_info,
371    (PS_GetFontExtraFunc)  NULL,
372    (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names,
373    (PS_GetFontPrivateFunc)NULL,        /* unsupported with CFF fonts */
374    (PS_GetFontValueFunc)  NULL         /* not implemented            */
375  )
376
377
378  /*
379   *  POSTSCRIPT NAME SERVICE
380   *
381   */
382
383  static const char*
384  cff_get_ps_name( CFF_Face  face )
385  {
386    CFF_Font  cff = (CFF_Font)face->extra.data;
387
388
389    return (const char*)cff->font_name;
390  }
391
392
393  FT_DEFINE_SERVICE_PSFONTNAMEREC(
394    cff_service_ps_name,
395    (FT_PsName_GetFunc)cff_get_ps_name
396  )
397
398
399  /*
400   * TT CMAP INFO
401   *
402   * If the charmap is a synthetic Unicode encoding cmap or
403   * a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO
404   * service defined in SFNT module.
405   *
406   * Otherwise call the service function in the sfnt module.
407   *
408   */
409  static FT_Error
410  cff_get_cmap_info( FT_CharMap    charmap,
411                     TT_CMapInfo  *cmap_info )
412  {
413    FT_CMap   cmap  = FT_CMAP( charmap );
414    FT_Error  error = FT_Err_Ok;
415
416    FT_Face     face    = FT_CMAP_FACE( cmap );
417    FT_Library  library = FT_FACE_LIBRARY( face );
418
419
420    cmap_info->language = 0;
421    cmap_info->format   = 0;
422
423    if ( cmap->clazz != &CFF_CMAP_ENCODING_CLASS_REC_GET &&
424         cmap->clazz != &CFF_CMAP_UNICODE_CLASS_REC_GET  )
425    {
426      FT_Module           sfnt    = FT_Get_Module( library, "sfnt" );
427      FT_Service_TTCMaps  service =
428        (FT_Service_TTCMaps)ft_module_get_service( sfnt,
429                                                   FT_SERVICE_ID_TT_CMAP );
430
431
432      if ( service && service->get_cmap_info )
433        error = service->get_cmap_info( charmap, cmap_info );
434    }
435
436    return error;
437  }
438
439
440  FT_DEFINE_SERVICE_TTCMAPSREC(
441    cff_service_get_cmap_info,
442    (TT_CMap_Info_GetFunc)cff_get_cmap_info
443  )
444
445
446  /*
447   *  CID INFO SERVICE
448   *
449   */
450  static FT_Error
451  cff_get_ros( CFF_Face      face,
452               const char*  *registry,
453               const char*  *ordering,
454               FT_Int       *supplement )
455  {
456    FT_Error  error = FT_Err_Ok;
457    CFF_Font  cff   = (CFF_Font)face->extra.data;
458
459
460    if ( cff )
461    {
462      CFF_FontRecDict  dict = &cff->top_font.font_dict;
463
464
465      if ( dict->cid_registry == 0xFFFFU )
466      {
467        error = FT_THROW( Invalid_Argument );
468        goto Fail;
469      }
470
471      if ( registry )
472      {
473        if ( cff->registry == NULL )
474          cff->registry = cff_index_get_sid_string( cff,
475                                                    dict->cid_registry );
476        *registry = cff->registry;
477      }
478
479      if ( ordering )
480      {
481        if ( cff->ordering == NULL )
482          cff->ordering = cff_index_get_sid_string( cff,
483                                                    dict->cid_ordering );
484        *ordering = cff->ordering;
485      }
486
487      /*
488       * XXX: According to Adobe TechNote #5176, the supplement in CFF
489       *      can be a real number. We truncate it to fit public API
490       *      since freetype-2.3.6.
491       */
492      if ( supplement )
493      {
494        if ( dict->cid_supplement < FT_INT_MIN ||
495             dict->cid_supplement > FT_INT_MAX )
496          FT_TRACE1(( "cff_get_ros: too large supplement %d is truncated\n",
497                      dict->cid_supplement ));
498        *supplement = (FT_Int)dict->cid_supplement;
499      }
500    }
501
502  Fail:
503    return error;
504  }
505
506
507  static FT_Error
508  cff_get_is_cid( CFF_Face  face,
509                  FT_Bool  *is_cid )
510  {
511    FT_Error  error = FT_Err_Ok;
512    CFF_Font  cff   = (CFF_Font)face->extra.data;
513
514
515    *is_cid = 0;
516
517    if ( cff )
518    {
519      CFF_FontRecDict  dict = &cff->top_font.font_dict;
520
521
522      if ( dict->cid_registry != 0xFFFFU )
523        *is_cid = 1;
524    }
525
526    return error;
527  }
528
529
530  static FT_Error
531  cff_get_cid_from_glyph_index( CFF_Face  face,
532                                FT_UInt   glyph_index,
533                                FT_UInt  *cid )
534  {
535    FT_Error  error = FT_Err_Ok;
536    CFF_Font  cff;
537
538
539    cff = (CFF_Font)face->extra.data;
540
541    if ( cff )
542    {
543      FT_UInt          c;
544      CFF_FontRecDict  dict = &cff->top_font.font_dict;
545
546
547      if ( dict->cid_registry == 0xFFFFU )
548      {
549        error = FT_THROW( Invalid_Argument );
550        goto Fail;
551      }
552
553      if ( glyph_index > cff->num_glyphs )
554      {
555        error = FT_THROW( Invalid_Argument );
556        goto Fail;
557      }
558
559      c = cff->charset.sids[glyph_index];
560
561      if ( cid )
562        *cid = c;
563    }
564
565  Fail:
566    return error;
567  }
568
569
570  FT_DEFINE_SERVICE_CIDREC(
571    cff_service_cid_info,
572    (FT_CID_GetRegistryOrderingSupplementFunc)cff_get_ros,
573    (FT_CID_GetIsInternallyCIDKeyedFunc)      cff_get_is_cid,
574    (FT_CID_GetCIDFromGlyphIndexFunc)         cff_get_cid_from_glyph_index
575  )
576
577
578  /*
579   *  PROPERTY SERVICE
580   *
581   */
582  static FT_Error
583  cff_property_set( FT_Module    module,         /* CFF_Driver */
584                    const char*  property_name,
585                    const void*  value )
586  {
587    FT_Error    error  = FT_Err_Ok;
588    CFF_Driver  driver = (CFF_Driver)module;
589
590
591    if ( !ft_strcmp( property_name, "darkening-parameters" ) )
592    {
593      FT_Int*  darken_params = (FT_Int*)value;
594
595      FT_Int  x1 = darken_params[0];
596      FT_Int  y1 = darken_params[1];
597      FT_Int  x2 = darken_params[2];
598      FT_Int  y2 = darken_params[3];
599      FT_Int  x3 = darken_params[4];
600      FT_Int  y3 = darken_params[5];
601      FT_Int  x4 = darken_params[6];
602      FT_Int  y4 = darken_params[7];
603
604
605      if ( x1 < 0   || x2 < 0   || x3 < 0   || x4 < 0   ||
606           y1 < 0   || y2 < 0   || y3 < 0   || y4 < 0   ||
607           x1 > x2  || x2 > x3  || x3 > x4              ||
608           y1 > 500 || y2 > 500 || y3 > 500 || y4 > 500 )
609        return FT_THROW( Invalid_Argument );
610
611      driver->darken_params[0] = x1;
612      driver->darken_params[1] = y1;
613      driver->darken_params[2] = x2;
614      driver->darken_params[3] = y2;
615      driver->darken_params[4] = x3;
616      driver->darken_params[5] = y3;
617      driver->darken_params[6] = x4;
618      driver->darken_params[7] = y4;
619
620      return error;
621    }
622    else if ( !ft_strcmp( property_name, "hinting-engine" ) )
623    {
624      FT_UInt*  hinting_engine = (FT_UInt*)value;
625
626
627#ifndef CFF_CONFIG_OPTION_OLD_ENGINE
628      if ( *hinting_engine != FT_CFF_HINTING_ADOBE )
629        error = FT_ERR( Unimplemented_Feature );
630      else
631#endif
632        driver->hinting_engine = *hinting_engine;
633
634      return error;
635    }
636    else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
637    {
638      FT_Bool*  no_stem_darkening = (FT_Bool*)value;
639
640
641      driver->no_stem_darkening = *no_stem_darkening;
642
643      return error;
644    }
645
646    FT_TRACE0(( "cff_property_set: missing property `%s'\n",
647                property_name ));
648    return FT_THROW( Missing_Property );
649  }
650
651
652  static FT_Error
653  cff_property_get( FT_Module    module,         /* CFF_Driver */
654                    const char*  property_name,
655                    const void*  value )
656  {
657    FT_Error    error  = FT_Err_Ok;
658    CFF_Driver  driver = (CFF_Driver)module;
659
660
661    if ( !ft_strcmp( property_name, "darkening-parameters" ) )
662    {
663      FT_Int*  darken_params = driver->darken_params;
664      FT_Int*  val           = (FT_Int*)value;
665
666
667      val[0] = darken_params[0];
668      val[1] = darken_params[1];
669      val[2] = darken_params[2];
670      val[3] = darken_params[3];
671      val[4] = darken_params[4];
672      val[5] = darken_params[5];
673      val[6] = darken_params[6];
674      val[7] = darken_params[7];
675
676      return error;
677    }
678    else if ( !ft_strcmp( property_name, "hinting-engine" ) )
679    {
680      FT_UInt   hinting_engine    = driver->hinting_engine;
681      FT_UInt*  val               = (FT_UInt*)value;
682
683
684      *val = hinting_engine;
685
686      return error;
687    }
688    else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
689    {
690      FT_Bool   no_stem_darkening = driver->no_stem_darkening;
691      FT_Bool*  val               = (FT_Bool*)value;
692
693
694      *val = no_stem_darkening;
695
696      return error;
697    }
698
699    FT_TRACE0(( "cff_property_get: missing property `%s'\n",
700                property_name ));
701    return FT_THROW( Missing_Property );
702  }
703
704
705  FT_DEFINE_SERVICE_PROPERTIESREC(
706    cff_service_properties,
707    (FT_Properties_SetFunc)cff_property_set,
708    (FT_Properties_GetFunc)cff_property_get )
709
710
711  /*************************************************************************/
712  /*************************************************************************/
713  /*************************************************************************/
714  /****                                                                 ****/
715  /****                                                                 ****/
716  /****                D R I V E R  I N T E R F A C E                   ****/
717  /****                                                                 ****/
718  /****                                                                 ****/
719  /*************************************************************************/
720  /*************************************************************************/
721  /*************************************************************************/
722
723#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
724  FT_DEFINE_SERVICEDESCREC7(
725    cff_services,
726    FT_SERVICE_ID_XF86_NAME,            FT_XF86_FORMAT_CFF,
727    FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
728    FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
729    FT_SERVICE_ID_GLYPH_DICT,           &CFF_SERVICE_GLYPH_DICT_GET,
730    FT_SERVICE_ID_TT_CMAP,              &CFF_SERVICE_GET_CMAP_INFO_GET,
731    FT_SERVICE_ID_CID,                  &CFF_SERVICE_CID_INFO_GET,
732    FT_SERVICE_ID_PROPERTIES,           &CFF_SERVICE_PROPERTIES_GET
733  )
734#else
735  FT_DEFINE_SERVICEDESCREC6(
736    cff_services,
737    FT_SERVICE_ID_XF86_NAME,            FT_XF86_FORMAT_CFF,
738    FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
739    FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
740    FT_SERVICE_ID_TT_CMAP,              &CFF_SERVICE_GET_CMAP_INFO_GET,
741    FT_SERVICE_ID_CID,                  &CFF_SERVICE_CID_INFO_GET,
742    FT_SERVICE_ID_PROPERTIES,           &CFF_SERVICE_PROPERTIES_GET
743  )
744#endif
745
746
747  FT_CALLBACK_DEF( FT_Module_Interface )
748  cff_get_interface( FT_Module    driver,       /* CFF_Driver */
749                     const char*  module_interface )
750  {
751    FT_Library           library;
752    FT_Module            sfnt;
753    FT_Module_Interface  result;
754
755
756    /* CFF_SERVICES_GET derefers `library' in PIC mode */
757#ifdef FT_CONFIG_OPTION_PIC
758    if ( !driver )
759      return NULL;
760    library = driver->library;
761    if ( !library )
762      return NULL;
763#endif
764
765    result = ft_service_list_lookup( CFF_SERVICES_GET, module_interface );
766    if ( result != NULL )
767      return result;
768
769    /* `driver' is not yet evaluated in non-PIC mode */
770#ifndef FT_CONFIG_OPTION_PIC
771    if ( !driver )
772      return NULL;
773    library = driver->library;
774    if ( !library )
775      return NULL;
776#endif
777
778    /* we pass our request to the `sfnt' module */
779    sfnt = FT_Get_Module( library, "sfnt" );
780
781    return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0;
782  }
783
784
785  /* The FT_DriverInterface structure is defined in ftdriver.h. */
786
787#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
788#define CFF_SIZE_SELECT cff_size_select
789#else
790#define CFF_SIZE_SELECT 0
791#endif
792
793  FT_DEFINE_DRIVER(
794    cff_driver_class,
795
796      FT_MODULE_FONT_DRIVER       |
797      FT_MODULE_DRIVER_SCALABLE   |
798      FT_MODULE_DRIVER_HAS_HINTER,
799
800      sizeof ( CFF_DriverRec ),
801      "cff",
802      0x10000L,
803      0x20000L,
804
805      0,   /* module-specific interface */
806
807      cff_driver_init,
808      cff_driver_done,
809      cff_get_interface,
810
811    /* now the specific driver fields */
812    sizeof ( TT_FaceRec ),
813    sizeof ( CFF_SizeRec ),
814    sizeof ( CFF_GlyphSlotRec ),
815
816    cff_face_init,
817    cff_face_done,
818    cff_size_init,
819    cff_size_done,
820    cff_slot_init,
821    cff_slot_done,
822
823    cff_glyph_load,
824
825    cff_get_kerning,
826    0,                       /* FT_Face_AttachFunc */
827    cff_get_advances,
828
829    cff_size_request,
830
831    CFF_SIZE_SELECT
832  )
833
834
835/* END */
836