tizen 2.3.1 release
[framework/graphics/freetype.git] / src / cff / cffdrivr.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  cffdrivr.c                                                             */
4 /*                                                                         */
5 /*    OpenType font driver implementation (body).                          */
6 /*                                                                         */
7 /*  Copyright 1996-2014 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 dereferences `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 */