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