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