• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************/
2 /*                                                                         */
3 /*  cffdrivr.c                                                             */
4 /*                                                                         */
5 /*    OpenType font driver implementation (body).                          */
6 /*                                                                         */
7 /*  Copyright 1996-2017 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 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
36 #include FT_SERVICE_MULTIPLE_MASTERS_H
37 #include FT_SERVICE_METRICS_VARIATIONS_H
38 #endif
39 
40 #include "cfferrs.h"
41 #include "cffpic.h"
42 
43 #include FT_SERVICE_FONT_FORMAT_H
44 #include FT_SERVICE_GLYPH_DICT_H
45 #include FT_SERVICE_PROPERTIES_H
46 #include FT_CFF_DRIVER_H
47 
48 
49   /*************************************************************************/
50   /*                                                                       */
51   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
52   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
53   /* messages during execution.                                            */
54   /*                                                                       */
55 #undef  FT_COMPONENT
56 #define FT_COMPONENT  trace_cffdriver
57 
58 
59   /*************************************************************************/
60   /*************************************************************************/
61   /*************************************************************************/
62   /****                                                                 ****/
63   /****                                                                 ****/
64   /****                          F A C E S                              ****/
65   /****                                                                 ****/
66   /****                                                                 ****/
67   /*************************************************************************/
68   /*************************************************************************/
69   /*************************************************************************/
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 )
cff_get_kerning(FT_Face ttface,FT_UInt left_glyph,FT_UInt right_glyph,FT_Vector * kerning)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   /*************************************************************************/
125   /*                                                                       */
126   /* <Function>                                                            */
127   /*    cff_glyph_load                                                     */
128   /*                                                                       */
129   /* <Description>                                                         */
130   /*    A driver method used to load a glyph within a given glyph slot.    */
131   /*                                                                       */
132   /* <Input>                                                               */
133   /*    slot        :: A handle to the target slot object where the glyph  */
134   /*                   will be loaded.                                     */
135   /*                                                                       */
136   /*    size        :: A handle to the source face size at which the glyph */
137   /*                   must be scaled, loaded, etc.                        */
138   /*                                                                       */
139   /*    glyph_index :: The index of the glyph in the font file.            */
140   /*                                                                       */
141   /*    load_flags  :: A flag indicating what to load for this glyph.  The */
142   /*                   FT_LOAD_??? constants can be used to control the    */
143   /*                   glyph loading process (e.g., whether the outline    */
144   /*                   should be scaled, whether to load bitmaps or not,   */
145   /*                   whether to hint the outline, etc).                  */
146   /*                                                                       */
147   /* <Return>                                                              */
148   /*    FreeType error code.  0 means success.                             */
149   /*                                                                       */
150   FT_CALLBACK_DEF( FT_Error )
cff_glyph_load(FT_GlyphSlot cffslot,FT_Size cffsize,FT_UInt glyph_index,FT_Int32 load_flags)151   cff_glyph_load( FT_GlyphSlot  cffslot,      /* CFF_GlyphSlot */
152                   FT_Size       cffsize,      /* CFF_Size      */
153                   FT_UInt       glyph_index,
154                   FT_Int32      load_flags )
155   {
156     FT_Error       error;
157     CFF_GlyphSlot  slot = (CFF_GlyphSlot)cffslot;
158     CFF_Size       size = (CFF_Size)cffsize;
159 
160 
161     if ( !slot )
162       return FT_THROW( Invalid_Slot_Handle );
163 
164     FT_TRACE1(( "cff_glyph_load: glyph index %d\n", glyph_index ));
165 
166     /* check whether we want a scaled outline or bitmap */
167     if ( !size )
168       load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
169 
170     /* reset the size object if necessary */
171     if ( load_flags & FT_LOAD_NO_SCALE )
172       size = NULL;
173 
174     if ( size )
175     {
176       /* these two objects must have the same parent */
177       if ( cffsize->face != cffslot->face )
178         return FT_THROW( Invalid_Face_Handle );
179     }
180 
181     /* now load the glyph outline if necessary */
182     error = cff_slot_load( slot, size, glyph_index, load_flags );
183 
184     /* force drop-out mode to 2 - irrelevant now */
185     /* slot->outline.dropout_mode = 2; */
186 
187     return error;
188   }
189 
190 
191   FT_CALLBACK_DEF( FT_Error )
cff_get_advances(FT_Face face,FT_UInt start,FT_UInt count,FT_Int32 flags,FT_Fixed * advances)192   cff_get_advances( FT_Face    face,
193                     FT_UInt    start,
194                     FT_UInt    count,
195                     FT_Int32   flags,
196                     FT_Fixed*  advances )
197   {
198     FT_UInt       nn;
199     FT_Error      error = FT_Err_Ok;
200     FT_GlyphSlot  slot  = face->glyph;
201 
202 
203     if ( FT_IS_SFNT( face ) )
204     {
205       /* OpenType 1.7 mandates that the data from `hmtx' table be used; */
206       /* it is no longer necessary that those values are identical to   */
207       /* the values in the `CFF' table                                  */
208 
209       TT_Face   ttface = (TT_Face)face;
210       FT_Short  dummy;
211 
212 
213       if ( flags & FT_LOAD_VERTICAL_LAYOUT )
214       {
215 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
216         /* no fast retrieval for blended MM fonts without VVAR table */
217         if ( !ttface->is_default_instance                               &&
218              !( ttface->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
219           return FT_THROW( Unimplemented_Feature );
220 #endif
221 
222         /* check whether we have data from the `vmtx' table at all; */
223         /* otherwise we extract the info from the CFF glyphstrings  */
224         /* (instead of synthesizing a global value using the `OS/2' */
225         /* table)                                                   */
226         if ( !ttface->vertical_info )
227           goto Missing_Table;
228 
229         for ( nn = 0; nn < count; nn++ )
230         {
231           FT_UShort  ah;
232 
233 
234           ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface,
235                                                        1,
236                                                        start + nn,
237                                                        &dummy,
238                                                        &ah );
239 
240           FT_TRACE5(( "  idx %d: advance height %d font units\n",
241                       start + nn, ah ));
242           advances[nn] = ah;
243         }
244       }
245       else
246       {
247 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
248         /* no fast retrieval for blended MM fonts without HVAR table */
249         if ( !ttface->is_default_instance                               &&
250              !( ttface->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
251           return FT_THROW( Unimplemented_Feature );
252 #endif
253 
254         /* check whether we have data from the `hmtx' table at all */
255         if ( !ttface->horizontal.number_Of_HMetrics )
256           goto Missing_Table;
257 
258         for ( nn = 0; nn < count; nn++ )
259         {
260           FT_UShort  aw;
261 
262 
263           ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface,
264                                                        0,
265                                                        start + nn,
266                                                        &dummy,
267                                                        &aw );
268 
269           FT_TRACE5(( "  idx %d: advance width %d font units\n",
270                       start + nn, aw ));
271           advances[nn] = aw;
272         }
273       }
274 
275       return error;
276     }
277 
278   Missing_Table:
279     flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
280 
281     for ( nn = 0; nn < count; nn++ )
282     {
283       error = cff_glyph_load( slot, face->size, start + nn, flags );
284       if ( error )
285         break;
286 
287       advances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
288                      ? slot->linearVertAdvance
289                      : slot->linearHoriAdvance;
290     }
291 
292     return error;
293   }
294 
295 
296   /*
297    *  GLYPH DICT SERVICE
298    *
299    */
300 
301   static FT_Error
cff_get_glyph_name(CFF_Face face,FT_UInt glyph_index,FT_Pointer buffer,FT_UInt buffer_max)302   cff_get_glyph_name( CFF_Face    face,
303                       FT_UInt     glyph_index,
304                       FT_Pointer  buffer,
305                       FT_UInt     buffer_max )
306   {
307     CFF_Font    font   = (CFF_Font)face->extra.data;
308     FT_String*  gname;
309     FT_UShort   sid;
310     FT_Error    error;
311 
312 
313     /* CFF2 table does not have glyph names; */
314     /* we need to use `post' table method    */
315     if ( font->version_major == 2 )
316     {
317       FT_Library            library     = FT_FACE_LIBRARY( face );
318       FT_Module             sfnt_module = FT_Get_Module( library, "sfnt" );
319       FT_Service_GlyphDict  service     =
320         (FT_Service_GlyphDict)ft_module_get_service(
321                                  sfnt_module,
322                                  FT_SERVICE_ID_GLYPH_DICT,
323                                  0 );
324 
325 
326       if ( service && service->get_name )
327         return service->get_name( FT_FACE( face ),
328                                   glyph_index,
329                                   buffer,
330                                   buffer_max );
331       else
332       {
333         FT_ERROR(( "cff_get_glyph_name:"
334                    " cannot get glyph name from a CFF2 font\n"
335                    "                   "
336                    " without the `PSNames' module\n" ));
337         error = FT_THROW( Missing_Module );
338         goto Exit;
339       }
340     }
341 
342     if ( !font->psnames )
343     {
344       FT_ERROR(( "cff_get_glyph_name:"
345                  " cannot get glyph name from CFF & CEF fonts\n"
346                  "                   "
347                  " without the `PSNames' module\n" ));
348       error = FT_THROW( Missing_Module );
349       goto Exit;
350     }
351 
352     /* first, locate the sid in the charset table */
353     sid = font->charset.sids[glyph_index];
354 
355     /* now, lookup the name itself */
356     gname = cff_index_get_sid_string( font, sid );
357 
358     if ( gname )
359       FT_STRCPYN( buffer, gname, buffer_max );
360 
361     error = FT_Err_Ok;
362 
363   Exit:
364     return error;
365   }
366 
367 
368   static FT_UInt
cff_get_name_index(CFF_Face face,FT_String * glyph_name)369   cff_get_name_index( CFF_Face    face,
370                       FT_String*  glyph_name )
371   {
372     CFF_Font            cff;
373     CFF_Charset         charset;
374     FT_Service_PsCMaps  psnames;
375     FT_String*          name;
376     FT_UShort           sid;
377     FT_UInt             i;
378 
379 
380     cff     = (CFF_FontRec *)face->extra.data;
381     charset = &cff->charset;
382 
383     /* CFF2 table does not have glyph names; */
384     /* we need to use `post' table method    */
385     if ( cff->version_major == 2 )
386     {
387       FT_Library            library     = FT_FACE_LIBRARY( face );
388       FT_Module             sfnt_module = FT_Get_Module( library, "sfnt" );
389       FT_Service_GlyphDict  service     =
390         (FT_Service_GlyphDict)ft_module_get_service(
391                                  sfnt_module,
392                                  FT_SERVICE_ID_GLYPH_DICT,
393                                  0 );
394 
395 
396       if ( service && service->name_index )
397         return service->name_index( FT_FACE( face ), glyph_name );
398       else
399       {
400         FT_ERROR(( "cff_get_name_index:"
401                    " cannot get glyph index from a CFF2 font\n"
402                    "                   "
403                    " without the `PSNames' module\n" ));
404         return 0;
405       }
406     }
407 
408     FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
409     if ( !psnames )
410       return 0;
411 
412     for ( i = 0; i < cff->num_glyphs; i++ )
413     {
414       sid = charset->sids[i];
415 
416       if ( sid > 390 )
417         name = cff_index_get_string( cff, sid - 391 );
418       else
419         name = (FT_String *)psnames->adobe_std_strings( sid );
420 
421       if ( !name )
422         continue;
423 
424       if ( !ft_strcmp( glyph_name, name ) )
425         return i;
426     }
427 
428     return 0;
429   }
430 
431 
432   FT_DEFINE_SERVICE_GLYPHDICTREC(
433     cff_service_glyph_dict,
434 
435     (FT_GlyphDict_GetNameFunc)  cff_get_glyph_name,      /* get_name   */
436     (FT_GlyphDict_NameIndexFunc)cff_get_name_index       /* name_index */
437   )
438 
439 
440   /*
441    *  POSTSCRIPT INFO SERVICE
442    *
443    */
444 
445   static FT_Int
cff_ps_has_glyph_names(FT_Face face)446   cff_ps_has_glyph_names( FT_Face  face )
447   {
448     return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0;
449   }
450 
451 
452   static FT_Error
cff_ps_get_font_info(CFF_Face face,PS_FontInfoRec * afont_info)453   cff_ps_get_font_info( CFF_Face         face,
454                         PS_FontInfoRec*  afont_info )
455   {
456     CFF_Font  cff   = (CFF_Font)face->extra.data;
457     FT_Error  error = FT_Err_Ok;
458 
459 
460     if ( cff && !cff->font_info )
461     {
462       CFF_FontRecDict  dict      = &cff->top_font.font_dict;
463       PS_FontInfoRec  *font_info = NULL;
464       FT_Memory        memory    = face->root.memory;
465 
466 
467       if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) )
468         goto Fail;
469 
470       font_info->version     = cff_index_get_sid_string( cff,
471                                                          dict->version );
472       font_info->notice      = cff_index_get_sid_string( cff,
473                                                          dict->notice );
474       font_info->full_name   = cff_index_get_sid_string( cff,
475                                                          dict->full_name );
476       font_info->family_name = cff_index_get_sid_string( cff,
477                                                          dict->family_name );
478       font_info->weight      = cff_index_get_sid_string( cff,
479                                                          dict->weight );
480       font_info->italic_angle        = dict->italic_angle;
481       font_info->is_fixed_pitch      = dict->is_fixed_pitch;
482       font_info->underline_position  = (FT_Short)dict->underline_position;
483       font_info->underline_thickness = (FT_UShort)dict->underline_thickness;
484 
485       cff->font_info = font_info;
486     }
487 
488     if ( cff )
489       *afont_info = *cff->font_info;
490 
491   Fail:
492     return error;
493   }
494 
495 
496   FT_DEFINE_SERVICE_PSINFOREC(
497     cff_service_ps_info,
498 
499     (PS_GetFontInfoFunc)   cff_ps_get_font_info,    /* ps_get_font_info    */
500     (PS_GetFontExtraFunc)  NULL,                    /* ps_get_font_extra   */
501     (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names,  /* ps_has_glyph_names  */
502     /* unsupported with CFF fonts */
503     (PS_GetFontPrivateFunc)NULL,                    /* ps_get_font_private */
504     /* not implemented            */
505     (PS_GetFontValueFunc)  NULL                     /* ps_get_font_value   */
506   )
507 
508 
509   /*
510    *  POSTSCRIPT NAME SERVICE
511    *
512    */
513 
514   static const char*
cff_get_ps_name(CFF_Face face)515   cff_get_ps_name( CFF_Face  face )
516   {
517     CFF_Font      cff  = (CFF_Font)face->extra.data;
518     SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
519 
520 
521     /* following the OpenType specification 1.7, we return the name stored */
522     /* in the `name' table for a CFF wrapped into an SFNT container        */
523 
524     if ( FT_IS_SFNT( FT_FACE( face ) ) && sfnt )
525     {
526       FT_Library             library     = FT_FACE_LIBRARY( face );
527       FT_Module              sfnt_module = FT_Get_Module( library, "sfnt" );
528       FT_Service_PsFontName  service     =
529         (FT_Service_PsFontName)ft_module_get_service(
530                                  sfnt_module,
531                                  FT_SERVICE_ID_POSTSCRIPT_FONT_NAME,
532                                  0 );
533 
534 
535       if ( service && service->get_ps_font_name )
536         return service->get_ps_font_name( FT_FACE( face ) );
537     }
538 
539     return (const char*)cff->font_name;
540   }
541 
542 
543   FT_DEFINE_SERVICE_PSFONTNAMEREC(
544     cff_service_ps_name,
545 
546     (FT_PsName_GetFunc)cff_get_ps_name      /* get_ps_font_name */
547   )
548 
549 
550   /*
551    * TT CMAP INFO
552    *
553    * If the charmap is a synthetic Unicode encoding cmap or
554    * a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO
555    * service defined in SFNT module.
556    *
557    * Otherwise call the service function in the sfnt module.
558    *
559    */
560   static FT_Error
cff_get_cmap_info(FT_CharMap charmap,TT_CMapInfo * cmap_info)561   cff_get_cmap_info( FT_CharMap    charmap,
562                      TT_CMapInfo  *cmap_info )
563   {
564     FT_CMap   cmap  = FT_CMAP( charmap );
565     FT_Error  error = FT_Err_Ok;
566 
567     FT_Face     face    = FT_CMAP_FACE( cmap );
568     FT_Library  library = FT_FACE_LIBRARY( face );
569 
570 
571     if ( cmap->clazz != &CFF_CMAP_ENCODING_CLASS_REC_GET &&
572          cmap->clazz != &CFF_CMAP_UNICODE_CLASS_REC_GET  )
573     {
574       FT_Module           sfnt    = FT_Get_Module( library, "sfnt" );
575       FT_Service_TTCMaps  service =
576         (FT_Service_TTCMaps)ft_module_get_service( sfnt,
577                                                    FT_SERVICE_ID_TT_CMAP,
578                                                    0 );
579 
580 
581       if ( service && service->get_cmap_info )
582         error = service->get_cmap_info( charmap, cmap_info );
583     }
584     else
585       error = FT_THROW( Invalid_CharMap_Format );
586 
587     return error;
588   }
589 
590 
591   FT_DEFINE_SERVICE_TTCMAPSREC(
592     cff_service_get_cmap_info,
593 
594     (TT_CMap_Info_GetFunc)cff_get_cmap_info    /* get_cmap_info */
595   )
596 
597 
598   /*
599    *  CID INFO SERVICE
600    *
601    */
602   static FT_Error
cff_get_ros(CFF_Face face,const char ** registry,const char ** ordering,FT_Int * supplement)603   cff_get_ros( CFF_Face      face,
604                const char*  *registry,
605                const char*  *ordering,
606                FT_Int       *supplement )
607   {
608     FT_Error  error = FT_Err_Ok;
609     CFF_Font  cff   = (CFF_Font)face->extra.data;
610 
611 
612     if ( cff )
613     {
614       CFF_FontRecDict  dict = &cff->top_font.font_dict;
615 
616 
617       if ( dict->cid_registry == 0xFFFFU )
618       {
619         error = FT_THROW( Invalid_Argument );
620         goto Fail;
621       }
622 
623       if ( registry )
624       {
625         if ( !cff->registry )
626           cff->registry = cff_index_get_sid_string( cff,
627                                                     dict->cid_registry );
628         *registry = cff->registry;
629       }
630 
631       if ( ordering )
632       {
633         if ( !cff->ordering )
634           cff->ordering = cff_index_get_sid_string( cff,
635                                                     dict->cid_ordering );
636         *ordering = cff->ordering;
637       }
638 
639       /*
640        * XXX: According to Adobe TechNote #5176, the supplement in CFF
641        *      can be a real number. We truncate it to fit public API
642        *      since freetype-2.3.6.
643        */
644       if ( supplement )
645       {
646         if ( dict->cid_supplement < FT_INT_MIN ||
647              dict->cid_supplement > FT_INT_MAX )
648           FT_TRACE1(( "cff_get_ros: too large supplement %d is truncated\n",
649                       dict->cid_supplement ));
650         *supplement = (FT_Int)dict->cid_supplement;
651       }
652     }
653 
654   Fail:
655     return error;
656   }
657 
658 
659   static FT_Error
cff_get_is_cid(CFF_Face face,FT_Bool * is_cid)660   cff_get_is_cid( CFF_Face  face,
661                   FT_Bool  *is_cid )
662   {
663     FT_Error  error = FT_Err_Ok;
664     CFF_Font  cff   = (CFF_Font)face->extra.data;
665 
666 
667     *is_cid = 0;
668 
669     if ( cff )
670     {
671       CFF_FontRecDict  dict = &cff->top_font.font_dict;
672 
673 
674       if ( dict->cid_registry != 0xFFFFU )
675         *is_cid = 1;
676     }
677 
678     return error;
679   }
680 
681 
682   static FT_Error
cff_get_cid_from_glyph_index(CFF_Face face,FT_UInt glyph_index,FT_UInt * cid)683   cff_get_cid_from_glyph_index( CFF_Face  face,
684                                 FT_UInt   glyph_index,
685                                 FT_UInt  *cid )
686   {
687     FT_Error  error = FT_Err_Ok;
688     CFF_Font  cff;
689 
690 
691     cff = (CFF_Font)face->extra.data;
692 
693     if ( cff )
694     {
695       FT_UInt          c;
696       CFF_FontRecDict  dict = &cff->top_font.font_dict;
697 
698 
699       if ( dict->cid_registry == 0xFFFFU )
700       {
701         error = FT_THROW( Invalid_Argument );
702         goto Fail;
703       }
704 
705       if ( glyph_index > cff->num_glyphs )
706       {
707         error = FT_THROW( Invalid_Argument );
708         goto Fail;
709       }
710 
711       c = cff->charset.sids[glyph_index];
712 
713       if ( cid )
714         *cid = c;
715     }
716 
717   Fail:
718     return error;
719   }
720 
721 
722   FT_DEFINE_SERVICE_CIDREC(
723     cff_service_cid_info,
724 
725     (FT_CID_GetRegistryOrderingSupplementFunc)
726       cff_get_ros,                             /* get_ros                  */
727     (FT_CID_GetIsInternallyCIDKeyedFunc)
728       cff_get_is_cid,                          /* get_is_cid               */
729     (FT_CID_GetCIDFromGlyphIndexFunc)
730       cff_get_cid_from_glyph_index             /* get_cid_from_glyph_index */
731   )
732 
733 
734   /*
735    *  PROPERTY SERVICE
736    *
737    */
738   static FT_Error
cff_property_set(FT_Module module,const char * property_name,const void * value,FT_Bool value_is_string)739   cff_property_set( FT_Module    module,         /* CFF_Driver */
740                     const char*  property_name,
741                     const void*  value,
742                     FT_Bool      value_is_string )
743   {
744     FT_Error    error  = FT_Err_Ok;
745     CFF_Driver  driver = (CFF_Driver)module;
746 
747 #ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
748     FT_UNUSED( value_is_string );
749 #endif
750 
751 
752     if ( !ft_strcmp( property_name, "darkening-parameters" ) )
753     {
754       FT_Int*  darken_params;
755       FT_Int   x1, y1, x2, y2, x3, y3, x4, y4;
756 
757 #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
758       FT_Int   dp[8];
759 
760 
761       if ( value_is_string )
762       {
763         const char*  s = (const char*)value;
764         char*        ep;
765         int          i;
766 
767 
768         /* eight comma-separated numbers */
769         for ( i = 0; i < 7; i++ )
770         {
771           dp[i] = (FT_Int)ft_strtol( s, &ep, 10 );
772           if ( *ep != ',' || s == ep )
773             return FT_THROW( Invalid_Argument );
774 
775           s = ep + 1;
776         }
777 
778         dp[7] = (FT_Int)ft_strtol( s, &ep, 10 );
779         if ( !( *ep == '\0' || *ep == ' ' ) || s == ep )
780           return FT_THROW( Invalid_Argument );
781 
782         darken_params = dp;
783       }
784       else
785 #endif
786         darken_params = (FT_Int*)value;
787 
788       x1 = darken_params[0];
789       y1 = darken_params[1];
790       x2 = darken_params[2];
791       y2 = darken_params[3];
792       x3 = darken_params[4];
793       y3 = darken_params[5];
794       x4 = darken_params[6];
795       y4 = darken_params[7];
796 
797       if ( x1 < 0   || x2 < 0   || x3 < 0   || x4 < 0   ||
798            y1 < 0   || y2 < 0   || y3 < 0   || y4 < 0   ||
799            x1 > x2  || x2 > x3  || x3 > x4              ||
800            y1 > 500 || y2 > 500 || y3 > 500 || y4 > 500 )
801         return FT_THROW( Invalid_Argument );
802 
803       driver->darken_params[0] = x1;
804       driver->darken_params[1] = y1;
805       driver->darken_params[2] = x2;
806       driver->darken_params[3] = y2;
807       driver->darken_params[4] = x3;
808       driver->darken_params[5] = y3;
809       driver->darken_params[6] = x4;
810       driver->darken_params[7] = y4;
811 
812       return error;
813     }
814     else if ( !ft_strcmp( property_name, "hinting-engine" ) )
815     {
816 #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
817       if ( value_is_string )
818       {
819         const char*  s = (const char*)value;
820 
821 
822         if ( !ft_strcmp( s, "adobe" ) )
823           driver->hinting_engine = FT_CFF_HINTING_ADOBE;
824 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
825         else if ( !ft_strcmp( s, "freetype" ) )
826           driver->hinting_engine = FT_CFF_HINTING_FREETYPE;
827 #endif
828         else
829           return FT_THROW( Invalid_Argument );
830       }
831       else
832 #endif
833       {
834         FT_UInt*  hinting_engine = (FT_UInt*)value;
835 
836         if ( *hinting_engine == FT_CFF_HINTING_ADOBE
837 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
838              || *hinting_engine == FT_CFF_HINTING_FREETYPE
839 #endif
840            )
841           driver->hinting_engine = *hinting_engine;
842         else
843           error = FT_ERR( Unimplemented_Feature );
844 
845         return error;
846       }
847     }
848     else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
849     {
850 #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
851       if ( value_is_string )
852       {
853         const char*  s   = (const char*)value;
854         long         nsd = ft_strtol( s, NULL, 10 );
855 
856 
857         if ( nsd == 0 )
858           driver->no_stem_darkening = 0;
859         else if ( nsd == 1 )
860           driver->no_stem_darkening = 1;
861         else
862           return FT_THROW( Invalid_Argument );
863       }
864       else
865 #endif
866       {
867         FT_Bool*  no_stem_darkening = (FT_Bool*)value;
868 
869 
870         driver->no_stem_darkening = *no_stem_darkening;
871       }
872 
873       return error;
874     }
875 
876     FT_TRACE0(( "cff_property_set: missing property `%s'\n",
877                 property_name ));
878     return FT_THROW( Missing_Property );
879   }
880 
881 
882   static FT_Error
cff_property_get(FT_Module module,const char * property_name,const void * value)883   cff_property_get( FT_Module    module,         /* CFF_Driver */
884                     const char*  property_name,
885                     const void*  value )
886   {
887     FT_Error    error  = FT_Err_Ok;
888     CFF_Driver  driver = (CFF_Driver)module;
889 
890 
891     if ( !ft_strcmp( property_name, "darkening-parameters" ) )
892     {
893       FT_Int*  darken_params = driver->darken_params;
894       FT_Int*  val           = (FT_Int*)value;
895 
896 
897       val[0] = darken_params[0];
898       val[1] = darken_params[1];
899       val[2] = darken_params[2];
900       val[3] = darken_params[3];
901       val[4] = darken_params[4];
902       val[5] = darken_params[5];
903       val[6] = darken_params[6];
904       val[7] = darken_params[7];
905 
906       return error;
907     }
908     else if ( !ft_strcmp( property_name, "hinting-engine" ) )
909     {
910       FT_UInt   hinting_engine    = driver->hinting_engine;
911       FT_UInt*  val               = (FT_UInt*)value;
912 
913 
914       *val = hinting_engine;
915 
916       return error;
917     }
918     else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
919     {
920       FT_Bool   no_stem_darkening = driver->no_stem_darkening;
921       FT_Bool*  val               = (FT_Bool*)value;
922 
923 
924       *val = no_stem_darkening;
925 
926       return error;
927     }
928 
929     FT_TRACE0(( "cff_property_get: missing property `%s'\n",
930                 property_name ));
931     return FT_THROW( Missing_Property );
932   }
933 
934 
935   FT_DEFINE_SERVICE_PROPERTIESREC(
936     cff_service_properties,
937 
938     (FT_Properties_SetFunc)cff_property_set,      /* set_property */
939     (FT_Properties_GetFunc)cff_property_get )     /* get_property */
940 
941 
942 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
943 
944   /*
945    *  MULTIPLE MASTER SERVICE
946    *
947    */
948 
949   static FT_Error
cff_set_mm_blend(CFF_Face face,FT_UInt num_coords,FT_Fixed * coords)950   cff_set_mm_blend( CFF_Face   face,
951                     FT_UInt    num_coords,
952                     FT_Fixed*  coords )
953   {
954     FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
955 
956 
957     return mm->set_mm_blend( FT_FACE( face ), num_coords, coords );
958   }
959 
960 
961   static FT_Error
cff_get_mm_blend(CFF_Face face,FT_UInt num_coords,FT_Fixed * coords)962   cff_get_mm_blend( CFF_Face   face,
963                     FT_UInt    num_coords,
964                     FT_Fixed*  coords )
965   {
966     FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
967 
968 
969     return mm->get_mm_blend( FT_FACE( face ), num_coords, coords );
970   }
971 
972 
973   static FT_Error
cff_get_mm_var(CFF_Face face,FT_MM_Var ** master)974   cff_get_mm_var( CFF_Face     face,
975                   FT_MM_Var*  *master )
976   {
977     FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
978 
979 
980     return mm->get_mm_var( FT_FACE( face ), master );
981   }
982 
983 
984   static FT_Error
cff_set_var_design(CFF_Face face,FT_UInt num_coords,FT_Fixed * coords)985   cff_set_var_design( CFF_Face   face,
986                       FT_UInt    num_coords,
987                       FT_Fixed*  coords )
988   {
989     FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
990 
991 
992     return mm->set_var_design( FT_FACE( face ), num_coords, coords );
993   }
994 
995 
996   static FT_Error
cff_get_var_design(CFF_Face face,FT_UInt num_coords,FT_Fixed * coords)997   cff_get_var_design( CFF_Face   face,
998                       FT_UInt    num_coords,
999                       FT_Fixed*  coords )
1000   {
1001     FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
1002 
1003 
1004     return mm->get_var_design( FT_FACE( face ), num_coords, coords );
1005   }
1006 
1007 
1008   FT_DEFINE_SERVICE_MULTIMASTERSREC(
1009     cff_service_multi_masters,
1010 
1011     (FT_Get_MM_Func)        NULL,                   /* get_mm         */
1012     (FT_Set_MM_Design_Func) NULL,                   /* set_mm_design  */
1013     (FT_Set_MM_Blend_Func)  cff_set_mm_blend,       /* set_mm_blend   */
1014     (FT_Get_MM_Blend_Func)  cff_get_mm_blend,       /* get_mm_blend   */
1015     (FT_Get_MM_Var_Func)    cff_get_mm_var,         /* get_mm_var     */
1016     (FT_Set_Var_Design_Func)cff_set_var_design,     /* set_var_design */
1017     (FT_Get_Var_Design_Func)cff_get_var_design,     /* get_var_design */
1018 
1019     (FT_Get_Var_Blend_Func) cff_get_var_blend,      /* get_var_blend  */
1020     (FT_Done_Blend_Func)    cff_done_blend          /* done_blend     */
1021   )
1022 
1023 
1024   /*
1025    *  METRICS VARIATIONS SERVICE
1026    *
1027    */
1028 
1029   static FT_Error
cff_hadvance_adjust(CFF_Face face,FT_UInt gindex,FT_Int * avalue)1030   cff_hadvance_adjust( CFF_Face  face,
1031                        FT_UInt   gindex,
1032                        FT_Int   *avalue )
1033   {
1034     FT_Service_MetricsVariations  var = (FT_Service_MetricsVariations)face->var;
1035 
1036 
1037     return var->hadvance_adjust( FT_FACE( face ), gindex, avalue );
1038   }
1039 
1040 
1041   static void
cff_metrics_adjust(CFF_Face face)1042   cff_metrics_adjust( CFF_Face  face )
1043   {
1044     FT_Service_MetricsVariations  var = (FT_Service_MetricsVariations)face->var;
1045 
1046 
1047     var->metrics_adjust( FT_FACE( face ) );
1048   }
1049 
1050 
1051   FT_DEFINE_SERVICE_METRICSVARIATIONSREC(
1052     cff_service_metrics_variations,
1053 
1054     (FT_HAdvance_Adjust_Func)cff_hadvance_adjust,    /* hadvance_adjust */
1055     (FT_LSB_Adjust_Func)     NULL,                   /* lsb_adjust      */
1056     (FT_RSB_Adjust_Func)     NULL,                   /* rsb_adjust      */
1057 
1058     (FT_VAdvance_Adjust_Func)NULL,                   /* vadvance_adjust */
1059     (FT_TSB_Adjust_Func)     NULL,                   /* tsb_adjust      */
1060     (FT_BSB_Adjust_Func)     NULL,                   /* bsb_adjust      */
1061     (FT_VOrg_Adjust_Func)    NULL,                   /* vorg_adjust     */
1062 
1063     (FT_Metrics_Adjust_Func) cff_metrics_adjust      /* metrics_adjust  */
1064   )
1065 #endif
1066 
1067 
1068   /*************************************************************************/
1069   /*************************************************************************/
1070   /*************************************************************************/
1071   /****                                                                 ****/
1072   /****                                                                 ****/
1073   /****                D R I V E R  I N T E R F A C E                   ****/
1074   /****                                                                 ****/
1075   /****                                                                 ****/
1076   /*************************************************************************/
1077   /*************************************************************************/
1078   /*************************************************************************/
1079 
1080 #if !defined FT_CONFIG_OPTION_NO_GLYPH_NAMES && \
1081      defined TT_CONFIG_OPTION_GX_VAR_SUPPORT
1082   FT_DEFINE_SERVICEDESCREC9(
1083     cff_services,
1084 
1085     FT_SERVICE_ID_FONT_FORMAT,          FT_FONT_FORMAT_CFF,
1086     FT_SERVICE_ID_MULTI_MASTERS,        &CFF_SERVICE_MULTI_MASTERS_GET,
1087     FT_SERVICE_ID_METRICS_VARIATIONS,   &CFF_SERVICE_METRICS_VAR_GET,
1088     FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
1089     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
1090     FT_SERVICE_ID_GLYPH_DICT,           &CFF_SERVICE_GLYPH_DICT_GET,
1091     FT_SERVICE_ID_TT_CMAP,              &CFF_SERVICE_GET_CMAP_INFO_GET,
1092     FT_SERVICE_ID_CID,                  &CFF_SERVICE_CID_INFO_GET,
1093     FT_SERVICE_ID_PROPERTIES,           &CFF_SERVICE_PROPERTIES_GET
1094   )
1095 #elif !defined FT_CONFIG_OPTION_NO_GLYPH_NAMES
1096   FT_DEFINE_SERVICEDESCREC7(
1097     cff_services,
1098 
1099     FT_SERVICE_ID_FONT_FORMAT,          FT_FONT_FORMAT_CFF,
1100     FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
1101     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
1102     FT_SERVICE_ID_GLYPH_DICT,           &CFF_SERVICE_GLYPH_DICT_GET,
1103     FT_SERVICE_ID_TT_CMAP,              &CFF_SERVICE_GET_CMAP_INFO_GET,
1104     FT_SERVICE_ID_CID,                  &CFF_SERVICE_CID_INFO_GET,
1105     FT_SERVICE_ID_PROPERTIES,           &CFF_SERVICE_PROPERTIES_GET
1106   )
1107 #elif defined TT_CONFIG_OPTION_GX_VAR_SUPPORT
1108   FT_DEFINE_SERVICEDESCREC8(
1109     cff_services,
1110 
1111     FT_SERVICE_ID_FONT_FORMAT,          FT_FONT_FORMAT_CFF,
1112     FT_SERVICE_ID_MULTI_MASTERS,        &CFF_SERVICE_MULTI_MASTERS_GET,
1113     FT_SERVICE_ID_METRICS_VARIATIONS,   &CFF_SERVICE_METRICS_VAR_GET,
1114     FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
1115     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
1116     FT_SERVICE_ID_TT_CMAP,              &CFF_SERVICE_GET_CMAP_INFO_GET,
1117     FT_SERVICE_ID_CID,                  &CFF_SERVICE_CID_INFO_GET,
1118     FT_SERVICE_ID_PROPERTIES,           &CFF_SERVICE_PROPERTIES_GET
1119   )
1120 #else
1121   FT_DEFINE_SERVICEDESCREC6(
1122     cff_services,
1123 
1124     FT_SERVICE_ID_FONT_FORMAT,          FT_FONT_FORMAT_CFF,
1125     FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
1126     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
1127     FT_SERVICE_ID_TT_CMAP,              &CFF_SERVICE_GET_CMAP_INFO_GET,
1128     FT_SERVICE_ID_CID,                  &CFF_SERVICE_CID_INFO_GET,
1129     FT_SERVICE_ID_PROPERTIES,           &CFF_SERVICE_PROPERTIES_GET
1130   )
1131 #endif
1132 
1133 
FT_CALLBACK_DEF(FT_Module_Interface)1134   FT_CALLBACK_DEF( FT_Module_Interface )
1135   cff_get_interface( FT_Module    driver,       /* CFF_Driver */
1136                      const char*  module_interface )
1137   {
1138     FT_Library           library;
1139     FT_Module            sfnt;
1140     FT_Module_Interface  result;
1141 
1142 
1143     /* CFF_SERVICES_GET dereferences `library' in PIC mode */
1144 #ifdef FT_CONFIG_OPTION_PIC
1145     if ( !driver )
1146       return NULL;
1147     library = driver->library;
1148     if ( !library )
1149       return NULL;
1150 #endif
1151 
1152     result = ft_service_list_lookup( CFF_SERVICES_GET, module_interface );
1153     if ( result )
1154       return result;
1155 
1156     /* `driver' is not yet evaluated in non-PIC mode */
1157 #ifndef FT_CONFIG_OPTION_PIC
1158     if ( !driver )
1159       return NULL;
1160     library = driver->library;
1161     if ( !library )
1162       return NULL;
1163 #endif
1164 
1165     /* we pass our request to the `sfnt' module */
1166     sfnt = FT_Get_Module( library, "sfnt" );
1167 
1168     return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0;
1169   }
1170 
1171 
1172   /* The FT_DriverInterface structure is defined in ftdriver.h. */
1173 
1174 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
1175 #define CFF_SIZE_SELECT cff_size_select
1176 #else
1177 #define CFF_SIZE_SELECT 0
1178 #endif
1179 
1180   FT_DEFINE_DRIVER(
1181     cff_driver_class,
1182 
1183       FT_MODULE_FONT_DRIVER          |
1184       FT_MODULE_DRIVER_SCALABLE      |
1185       FT_MODULE_DRIVER_HAS_HINTER    |
1186       FT_MODULE_DRIVER_HINTS_LIGHTLY,
1187 
1188       sizeof ( CFF_DriverRec ),
1189       "cff",
1190       0x10000L,
1191       0x20000L,
1192 
1193       NULL,   /* module-specific interface */
1194 
1195       cff_driver_init,          /* FT_Module_Constructor  module_init   */
1196       cff_driver_done,          /* FT_Module_Destructor   module_done   */
1197       cff_get_interface,        /* FT_Module_Requester    get_interface */
1198 
1199     sizeof ( TT_FaceRec ),
1200     sizeof ( CFF_SizeRec ),
1201     sizeof ( CFF_GlyphSlotRec ),
1202 
1203     cff_face_init,              /* FT_Face_InitFunc  init_face */
1204     cff_face_done,              /* FT_Face_DoneFunc  done_face */
1205     cff_size_init,              /* FT_Size_InitFunc  init_size */
1206     cff_size_done,              /* FT_Size_DoneFunc  done_size */
1207     cff_slot_init,              /* FT_Slot_InitFunc  init_slot */
1208     cff_slot_done,              /* FT_Slot_DoneFunc  done_slot */
1209 
1210     cff_glyph_load,             /* FT_Slot_LoadFunc  load_glyph */
1211 
1212     cff_get_kerning,            /* FT_Face_GetKerningFunc   get_kerning  */
1213     NULL,                       /* FT_Face_AttachFunc       attach_file  */
1214     cff_get_advances,           /* FT_Face_GetAdvancesFunc  get_advances */
1215 
1216     cff_size_request,           /* FT_Size_RequestFunc  request_size */
1217     CFF_SIZE_SELECT             /* FT_Size_SelectFunc   select_size  */
1218   )
1219 
1220 
1221 /* END */
1222