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