1 /***************************************************************************/
2 /*                                                                         */
3 /*  cffdrivr.c                                                             */
4 /*                                                                         */
5 /*    OpenType font driver implementation (body).                          */
6 /*                                                                         */
7 /*  Copyright 1996-2016 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,      /* get_name   */
362     (FT_GlyphDict_NameIndexFunc)cff_get_name_index       /* 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,    /* ps_get_font_info    */
425     (PS_GetFontExtraFunc)  NULL,                    /* ps_get_font_extra   */
426     (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names,  /* ps_has_glyph_names  */
427     /* unsupported with CFF fonts */
428     (PS_GetFontPrivateFunc)NULL,                    /* ps_get_font_private */
429     /* not implemented            */
430     (PS_GetFontValueFunc)  NULL                     /* ps_get_font_value   */
431   )
432 
433 
434   /*
435    *  POSTSCRIPT NAME SERVICE
436    *
437    */
438 
439   static const char*
cff_get_ps_name(CFF_Face face)440   cff_get_ps_name( CFF_Face  face )
441   {
442     CFF_Font      cff  = (CFF_Font)face->extra.data;
443     SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
444 
445 
446     /* following the OpenType specification 1.7, we return the name stored */
447     /* in the `name' table for a CFF wrapped into an SFNT container        */
448 
449     if ( FT_IS_SFNT( FT_FACE( face ) ) && sfnt )
450     {
451       FT_Library             library     = FT_FACE_LIBRARY( face );
452       FT_Module              sfnt_module = FT_Get_Module( library, "sfnt" );
453       FT_Service_PsFontName  service     =
454         (FT_Service_PsFontName)ft_module_get_service(
455                                  sfnt_module,
456                                  FT_SERVICE_ID_POSTSCRIPT_FONT_NAME );
457 
458 
459       if ( service && service->get_ps_font_name )
460         return service->get_ps_font_name( FT_FACE( face ) );
461     }
462 
463     return (const char*)cff->font_name;
464   }
465 
466 
467   FT_DEFINE_SERVICE_PSFONTNAMEREC(
468     cff_service_ps_name,
469     (FT_PsName_GetFunc)cff_get_ps_name      /* get_ps_font_name */
470   )
471 
472 
473   /*
474    * TT CMAP INFO
475    *
476    * If the charmap is a synthetic Unicode encoding cmap or
477    * a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO
478    * service defined in SFNT module.
479    *
480    * Otherwise call the service function in the sfnt module.
481    *
482    */
483   static FT_Error
cff_get_cmap_info(FT_CharMap charmap,TT_CMapInfo * cmap_info)484   cff_get_cmap_info( FT_CharMap    charmap,
485                      TT_CMapInfo  *cmap_info )
486   {
487     FT_CMap   cmap  = FT_CMAP( charmap );
488     FT_Error  error = FT_Err_Ok;
489 
490     FT_Face     face    = FT_CMAP_FACE( cmap );
491     FT_Library  library = FT_FACE_LIBRARY( face );
492 
493 
494     cmap_info->language = 0;
495     cmap_info->format   = 0;
496 
497     if ( cmap->clazz != &CFF_CMAP_ENCODING_CLASS_REC_GET &&
498          cmap->clazz != &CFF_CMAP_UNICODE_CLASS_REC_GET  )
499     {
500       FT_Module           sfnt    = FT_Get_Module( library, "sfnt" );
501       FT_Service_TTCMaps  service =
502         (FT_Service_TTCMaps)ft_module_get_service( sfnt,
503                                                    FT_SERVICE_ID_TT_CMAP );
504 
505 
506       if ( service && service->get_cmap_info )
507         error = service->get_cmap_info( charmap, cmap_info );
508     }
509 
510     return error;
511   }
512 
513 
514   FT_DEFINE_SERVICE_TTCMAPSREC(
515     cff_service_get_cmap_info,
516     (TT_CMap_Info_GetFunc)cff_get_cmap_info    /* get_cmap_info */
517   )
518 
519 
520   /*
521    *  CID INFO SERVICE
522    *
523    */
524   static FT_Error
cff_get_ros(CFF_Face face,const char ** registry,const char ** ordering,FT_Int * supplement)525   cff_get_ros( CFF_Face      face,
526                const char*  *registry,
527                const char*  *ordering,
528                FT_Int       *supplement )
529   {
530     FT_Error  error = FT_Err_Ok;
531     CFF_Font  cff   = (CFF_Font)face->extra.data;
532 
533 
534     if ( cff )
535     {
536       CFF_FontRecDict  dict = &cff->top_font.font_dict;
537 
538 
539       if ( dict->cid_registry == 0xFFFFU )
540       {
541         error = FT_THROW( Invalid_Argument );
542         goto Fail;
543       }
544 
545       if ( registry )
546       {
547         if ( cff->registry == NULL )
548           cff->registry = cff_index_get_sid_string( cff,
549                                                     dict->cid_registry );
550         *registry = cff->registry;
551       }
552 
553       if ( ordering )
554       {
555         if ( cff->ordering == NULL )
556           cff->ordering = cff_index_get_sid_string( cff,
557                                                     dict->cid_ordering );
558         *ordering = cff->ordering;
559       }
560 
561       /*
562        * XXX: According to Adobe TechNote #5176, the supplement in CFF
563        *      can be a real number. We truncate it to fit public API
564        *      since freetype-2.3.6.
565        */
566       if ( supplement )
567       {
568         if ( dict->cid_supplement < FT_INT_MIN ||
569              dict->cid_supplement > FT_INT_MAX )
570           FT_TRACE1(( "cff_get_ros: too large supplement %d is truncated\n",
571                       dict->cid_supplement ));
572         *supplement = (FT_Int)dict->cid_supplement;
573       }
574     }
575 
576   Fail:
577     return error;
578   }
579 
580 
581   static FT_Error
cff_get_is_cid(CFF_Face face,FT_Bool * is_cid)582   cff_get_is_cid( CFF_Face  face,
583                   FT_Bool  *is_cid )
584   {
585     FT_Error  error = FT_Err_Ok;
586     CFF_Font  cff   = (CFF_Font)face->extra.data;
587 
588 
589     *is_cid = 0;
590 
591     if ( cff )
592     {
593       CFF_FontRecDict  dict = &cff->top_font.font_dict;
594 
595 
596       if ( dict->cid_registry != 0xFFFFU )
597         *is_cid = 1;
598     }
599 
600     return error;
601   }
602 
603 
604   static FT_Error
cff_get_cid_from_glyph_index(CFF_Face face,FT_UInt glyph_index,FT_UInt * cid)605   cff_get_cid_from_glyph_index( CFF_Face  face,
606                                 FT_UInt   glyph_index,
607                                 FT_UInt  *cid )
608   {
609     FT_Error  error = FT_Err_Ok;
610     CFF_Font  cff;
611 
612 
613     cff = (CFF_Font)face->extra.data;
614 
615     if ( cff )
616     {
617       FT_UInt          c;
618       CFF_FontRecDict  dict = &cff->top_font.font_dict;
619 
620 
621       if ( dict->cid_registry == 0xFFFFU )
622       {
623         error = FT_THROW( Invalid_Argument );
624         goto Fail;
625       }
626 
627       if ( glyph_index > cff->num_glyphs )
628       {
629         error = FT_THROW( Invalid_Argument );
630         goto Fail;
631       }
632 
633       c = cff->charset.sids[glyph_index];
634 
635       if ( cid )
636         *cid = c;
637     }
638 
639   Fail:
640     return error;
641   }
642 
643 
644   FT_DEFINE_SERVICE_CIDREC(
645     cff_service_cid_info,
646     (FT_CID_GetRegistryOrderingSupplementFunc)
647       cff_get_ros,                             /* get_ros                  */
648     (FT_CID_GetIsInternallyCIDKeyedFunc)
649       cff_get_is_cid,                          /* get_is_cid               */
650     (FT_CID_GetCIDFromGlyphIndexFunc)
651       cff_get_cid_from_glyph_index             /* get_cid_from_glyph_index */
652   )
653 
654 
655   /*
656    *  PROPERTY SERVICE
657    *
658    */
659   static FT_Error
cff_property_set(FT_Module module,const char * property_name,const void * value)660   cff_property_set( FT_Module    module,         /* CFF_Driver */
661                     const char*  property_name,
662                     const void*  value )
663   {
664     FT_Error    error  = FT_Err_Ok;
665     CFF_Driver  driver = (CFF_Driver)module;
666 
667 
668     if ( !ft_strcmp( property_name, "darkening-parameters" ) )
669     {
670       FT_Int*  darken_params = (FT_Int*)value;
671 
672       FT_Int  x1 = darken_params[0];
673       FT_Int  y1 = darken_params[1];
674       FT_Int  x2 = darken_params[2];
675       FT_Int  y2 = darken_params[3];
676       FT_Int  x3 = darken_params[4];
677       FT_Int  y3 = darken_params[5];
678       FT_Int  x4 = darken_params[6];
679       FT_Int  y4 = darken_params[7];
680 
681 
682       if ( x1 < 0   || x2 < 0   || x3 < 0   || x4 < 0   ||
683            y1 < 0   || y2 < 0   || y3 < 0   || y4 < 0   ||
684            x1 > x2  || x2 > x3  || x3 > x4              ||
685            y1 > 500 || y2 > 500 || y3 > 500 || y4 > 500 )
686         return FT_THROW( Invalid_Argument );
687 
688       driver->darken_params[0] = x1;
689       driver->darken_params[1] = y1;
690       driver->darken_params[2] = x2;
691       driver->darken_params[3] = y2;
692       driver->darken_params[4] = x3;
693       driver->darken_params[5] = y3;
694       driver->darken_params[6] = x4;
695       driver->darken_params[7] = y4;
696 
697       return error;
698     }
699     else if ( !ft_strcmp( property_name, "hinting-engine" ) )
700     {
701       FT_UInt*  hinting_engine = (FT_UInt*)value;
702 
703 
704       if ( *hinting_engine == FT_CFF_HINTING_ADOBE
705 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
706            || *hinting_engine == FT_CFF_HINTING_FREETYPE
707 #endif
708          )
709         driver->hinting_engine = *hinting_engine;
710       else
711         error = FT_ERR( Unimplemented_Feature );
712 
713       return error;
714     }
715     else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
716     {
717       FT_Bool*  no_stem_darkening = (FT_Bool*)value;
718 
719 
720       driver->no_stem_darkening = *no_stem_darkening;
721 
722       return error;
723     }
724 
725     FT_TRACE0(( "cff_property_set: missing property `%s'\n",
726                 property_name ));
727     return FT_THROW( Missing_Property );
728   }
729 
730 
731   static FT_Error
cff_property_get(FT_Module module,const char * property_name,const void * value)732   cff_property_get( FT_Module    module,         /* CFF_Driver */
733                     const char*  property_name,
734                     const void*  value )
735   {
736     FT_Error    error  = FT_Err_Ok;
737     CFF_Driver  driver = (CFF_Driver)module;
738 
739 
740     if ( !ft_strcmp( property_name, "darkening-parameters" ) )
741     {
742       FT_Int*  darken_params = driver->darken_params;
743       FT_Int*  val           = (FT_Int*)value;
744 
745 
746       val[0] = darken_params[0];
747       val[1] = darken_params[1];
748       val[2] = darken_params[2];
749       val[3] = darken_params[3];
750       val[4] = darken_params[4];
751       val[5] = darken_params[5];
752       val[6] = darken_params[6];
753       val[7] = darken_params[7];
754 
755       return error;
756     }
757     else if ( !ft_strcmp( property_name, "hinting-engine" ) )
758     {
759       FT_UInt   hinting_engine    = driver->hinting_engine;
760       FT_UInt*  val               = (FT_UInt*)value;
761 
762 
763       *val = hinting_engine;
764 
765       return error;
766     }
767     else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
768     {
769       FT_Bool   no_stem_darkening = driver->no_stem_darkening;
770       FT_Bool*  val               = (FT_Bool*)value;
771 
772 
773       *val = no_stem_darkening;
774 
775       return error;
776     }
777 
778     FT_TRACE0(( "cff_property_get: missing property `%s'\n",
779                 property_name ));
780     return FT_THROW( Missing_Property );
781   }
782 
783 
784   FT_DEFINE_SERVICE_PROPERTIESREC(
785     cff_service_properties,
786     (FT_Properties_SetFunc)cff_property_set,      /* set_property */
787     (FT_Properties_GetFunc)cff_property_get )     /* get_property */
788 
789 
790   /*************************************************************************/
791   /*************************************************************************/
792   /*************************************************************************/
793   /****                                                                 ****/
794   /****                                                                 ****/
795   /****                D R I V E R  I N T E R F A C E                   ****/
796   /****                                                                 ****/
797   /****                                                                 ****/
798   /*************************************************************************/
799   /*************************************************************************/
800   /*************************************************************************/
801 
802 #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
803   FT_DEFINE_SERVICEDESCREC7(
804     cff_services,
805     FT_SERVICE_ID_FONT_FORMAT,          FT_FONT_FORMAT_CFF,
806     FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
807     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
808     FT_SERVICE_ID_GLYPH_DICT,           &CFF_SERVICE_GLYPH_DICT_GET,
809     FT_SERVICE_ID_TT_CMAP,              &CFF_SERVICE_GET_CMAP_INFO_GET,
810     FT_SERVICE_ID_CID,                  &CFF_SERVICE_CID_INFO_GET,
811     FT_SERVICE_ID_PROPERTIES,           &CFF_SERVICE_PROPERTIES_GET
812   )
813 #else
814   FT_DEFINE_SERVICEDESCREC6(
815     cff_services,
816     FT_SERVICE_ID_FONT_FORMAT,          FT_FONT_FORMAT_CFF,
817     FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
818     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
819     FT_SERVICE_ID_TT_CMAP,              &CFF_SERVICE_GET_CMAP_INFO_GET,
820     FT_SERVICE_ID_CID,                  &CFF_SERVICE_CID_INFO_GET,
821     FT_SERVICE_ID_PROPERTIES,           &CFF_SERVICE_PROPERTIES_GET
822   )
823 #endif
824 
825 
FT_CALLBACK_DEF(FT_Module_Interface)826   FT_CALLBACK_DEF( FT_Module_Interface )
827   cff_get_interface( FT_Module    driver,       /* CFF_Driver */
828                      const char*  module_interface )
829   {
830     FT_Library           library;
831     FT_Module            sfnt;
832     FT_Module_Interface  result;
833 
834 
835     /* CFF_SERVICES_GET dereferences `library' in PIC mode */
836 #ifdef FT_CONFIG_OPTION_PIC
837     if ( !driver )
838       return NULL;
839     library = driver->library;
840     if ( !library )
841       return NULL;
842 #endif
843 
844     result = ft_service_list_lookup( CFF_SERVICES_GET, module_interface );
845     if ( result != NULL )
846       return result;
847 
848     /* `driver' is not yet evaluated in non-PIC mode */
849 #ifndef FT_CONFIG_OPTION_PIC
850     if ( !driver )
851       return NULL;
852     library = driver->library;
853     if ( !library )
854       return NULL;
855 #endif
856 
857     /* we pass our request to the `sfnt' module */
858     sfnt = FT_Get_Module( library, "sfnt" );
859 
860     return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0;
861   }
862 
863 
864   /* The FT_DriverInterface structure is defined in ftdriver.h. */
865 
866 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
867 #define CFF_SIZE_SELECT cff_size_select
868 #else
869 #define CFF_SIZE_SELECT 0
870 #endif
871 
872   FT_DEFINE_DRIVER(
873     cff_driver_class,
874 
875       FT_MODULE_FONT_DRIVER          |
876       FT_MODULE_DRIVER_SCALABLE      |
877       FT_MODULE_DRIVER_HAS_HINTER    |
878       FT_MODULE_DRIVER_HINTS_LIGHTLY,
879 
880       sizeof ( CFF_DriverRec ),
881       "cff",
882       0x10000L,
883       0x20000L,
884 
885       0,   /* module-specific interface */
886 
887       cff_driver_init,          /* FT_Module_Constructor  module_init   */
888       cff_driver_done,          /* FT_Module_Destructor   module_done   */
889       cff_get_interface,        /* FT_Module_Requester    get_interface */
890 
891     sizeof ( TT_FaceRec ),
892     sizeof ( CFF_SizeRec ),
893     sizeof ( CFF_GlyphSlotRec ),
894 
895     cff_face_init,              /* FT_Face_InitFunc  init_face */
896     cff_face_done,              /* FT_Face_DoneFunc  done_face */
897     cff_size_init,              /* FT_Size_InitFunc  init_size */
898     cff_size_done,              /* FT_Size_DoneFunc  done_size */
899     cff_slot_init,              /* FT_Slot_InitFunc  init_slot */
900     cff_slot_done,              /* FT_Slot_DoneFunc  done_slot */
901 
902     cff_glyph_load,             /* FT_Slot_LoadFunc  load_glyph */
903 
904     cff_get_kerning,            /* FT_Face_GetKerningFunc   get_kerning  */
905     0,                          /* FT_Face_AttachFunc       attach_file  */
906     cff_get_advances,           /* FT_Face_GetAdvancesFunc  get_advances */
907 
908     cff_size_request,           /* FT_Size_RequestFunc  request_size */
909     CFF_SIZE_SELECT             /* FT_Size_SelectFunc   select_size  */
910   )
911 
912 
913 /* END */
914