xref: /aosp_15_r20/external/freetype/src/cff/cffobjs.c (revision 63949dbd25bcc50c4e1178497ff9e9574d44fc5a)
1 /****************************************************************************
2  *
3  * cffobjs.c
4  *
5  *   OpenType objects manager (body).
6  *
7  * Copyright (C) 1996-2023 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 
20 #include <freetype/internal/ftdebug.h>
21 #include <freetype/internal/ftcalc.h>
22 #include <freetype/internal/ftstream.h>
23 #include <freetype/fterrors.h>
24 #include <freetype/ttnameid.h>
25 #include <freetype/tttags.h>
26 #include <freetype/internal/sfnt.h>
27 #include <freetype/ftdriver.h>
28 
29 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
30 #include <freetype/ftmm.h>
31 #include <freetype/internal/services/svmm.h>
32 #include <freetype/internal/services/svmetric.h>
33 #endif
34 
35 #include <freetype/internal/cffotypes.h>
36 #include "cffobjs.h"
37 #include "cffload.h"
38 #include "cffcmap.h"
39 
40 #include "cfferrs.h"
41 
42 #include <freetype/internal/psaux.h>
43 #include <freetype/internal/services/svcfftl.h>
44 
45 
46   /**************************************************************************
47    *
48    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
49    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
50    * messages during execution.
51    */
52 #undef  FT_COMPONENT
53 #define FT_COMPONENT  cffobjs
54 
55 
56   /**************************************************************************
57    *
58    *                           SIZE FUNCTIONS
59    *
60    */
61 
62 
63   static PSH_Globals_Funcs
cff_size_get_globals_funcs(CFF_Size size)64   cff_size_get_globals_funcs( CFF_Size  size )
65   {
66     CFF_Face          face     = (CFF_Face)size->root.face;
67     CFF_Font          font     = (CFF_Font)face->extra.data;
68     PSHinter_Service  pshinter = font->pshinter;
69     FT_Module         module;
70 
71 
72     module = FT_Get_Module( font->library, "pshinter" );
73 
74     return ( module && pshinter && pshinter->get_globals_funcs )
75            ? pshinter->get_globals_funcs( module )
76            : 0;
77   }
78 
79 
80   FT_LOCAL_DEF( void )
cff_size_done(FT_Size cffsize)81   cff_size_done( FT_Size  cffsize )        /* CFF_Size */
82   {
83     FT_Memory     memory   = cffsize->face->memory;
84     CFF_Size      size     = (CFF_Size)cffsize;
85     CFF_Face      face     = (CFF_Face)size->root.face;
86     CFF_Font      font     = (CFF_Font)face->extra.data;
87     CFF_Internal  internal = (CFF_Internal)cffsize->internal->module_data;
88 
89 
90     if ( internal )
91     {
92       PSH_Globals_Funcs  funcs;
93 
94 
95       funcs = cff_size_get_globals_funcs( size );
96       if ( funcs )
97       {
98         FT_UInt  i;
99 
100 
101         funcs->destroy( internal->topfont );
102 
103         for ( i = font->num_subfonts; i > 0; i-- )
104           funcs->destroy( internal->subfonts[i - 1] );
105       }
106 
107       FT_FREE( internal );
108     }
109   }
110 
111 
112   /* CFF and Type 1 private dictionaries have slightly different      */
113   /* structures; we need to synthesize a Type 1 dictionary on the fly */
114 
115   static void
cff_make_private_dict(CFF_SubFont subfont,PS_Private priv)116   cff_make_private_dict( CFF_SubFont  subfont,
117                          PS_Private   priv )
118   {
119     CFF_Private  cpriv = &subfont->private_dict;
120     FT_UInt      n, count;
121 
122 
123     FT_ZERO( priv );
124 
125     count = priv->num_blue_values = cpriv->num_blue_values;
126     for ( n = 0; n < count; n++ )
127       priv->blue_values[n] = (FT_Short)cpriv->blue_values[n];
128 
129     count = priv->num_other_blues = cpriv->num_other_blues;
130     for ( n = 0; n < count; n++ )
131       priv->other_blues[n] = (FT_Short)cpriv->other_blues[n];
132 
133     count = priv->num_family_blues = cpriv->num_family_blues;
134     for ( n = 0; n < count; n++ )
135       priv->family_blues[n] = (FT_Short)cpriv->family_blues[n];
136 
137     count = priv->num_family_other_blues = cpriv->num_family_other_blues;
138     for ( n = 0; n < count; n++ )
139       priv->family_other_blues[n] = (FT_Short)cpriv->family_other_blues[n];
140 
141     priv->blue_scale = cpriv->blue_scale;
142     priv->blue_shift = (FT_Int)cpriv->blue_shift;
143     priv->blue_fuzz  = (FT_Int)cpriv->blue_fuzz;
144 
145     priv->standard_width[0]  = (FT_UShort)cpriv->standard_width;
146     priv->standard_height[0] = (FT_UShort)cpriv->standard_height;
147 
148     count = priv->num_snap_widths = cpriv->num_snap_widths;
149     for ( n = 0; n < count; n++ )
150       priv->snap_widths[n] = (FT_Short)cpriv->snap_widths[n];
151 
152     count = priv->num_snap_heights = cpriv->num_snap_heights;
153     for ( n = 0; n < count; n++ )
154       priv->snap_heights[n] = (FT_Short)cpriv->snap_heights[n];
155 
156     priv->force_bold     = cpriv->force_bold;
157     priv->language_group = cpriv->language_group;
158     priv->lenIV          = cpriv->lenIV;
159   }
160 
161 
162   FT_LOCAL_DEF( FT_Error )
cff_size_init(FT_Size cffsize)163   cff_size_init( FT_Size  cffsize )         /* CFF_Size */
164   {
165     CFF_Size           size  = (CFF_Size)cffsize;
166     FT_Error           error = FT_Err_Ok;
167     PSH_Globals_Funcs  funcs = cff_size_get_globals_funcs( size );
168 
169     FT_Memory     memory   = cffsize->face->memory;
170     CFF_Internal  internal = NULL;
171     CFF_Face      face     = (CFF_Face)cffsize->face;
172     CFF_Font      font     = (CFF_Font)face->extra.data;
173 
174     PS_PrivateRec priv;
175 
176     FT_UInt       i;
177 
178     if ( !funcs )
179       goto Exit;
180 
181     if ( FT_NEW( internal ) )
182       goto Exit;
183 
184     cff_make_private_dict( &font->top_font, &priv );
185     error = funcs->create( memory, &priv, &internal->topfont );
186     if ( error )
187       goto Exit;
188 
189     for ( i = font->num_subfonts; i > 0; i-- )
190     {
191       CFF_SubFont  sub = font->subfonts[i - 1];
192 
193 
194       cff_make_private_dict( sub, &priv );
195       error = funcs->create( memory, &priv, &internal->subfonts[i - 1] );
196       if ( error )
197         goto Exit;
198     }
199 
200     cffsize->internal->module_data = internal;
201 
202     size->strike_index = 0xFFFFFFFFUL;
203 
204   Exit:
205     if ( error )
206     {
207       if ( internal )
208       {
209         for ( i = font->num_subfonts; i > 0; i-- )
210           FT_FREE( internal->subfonts[i - 1] );
211         FT_FREE( internal->topfont );
212       }
213 
214       FT_FREE( internal );
215     }
216 
217     return error;
218   }
219 
220 
221 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
222 
223   FT_LOCAL_DEF( FT_Error )
cff_size_select(FT_Size size,FT_ULong strike_index)224   cff_size_select( FT_Size   size,
225                    FT_ULong  strike_index )
226   {
227     CFF_Size           cffsize = (CFF_Size)size;
228     PSH_Globals_Funcs  funcs;
229 
230 
231     cffsize->strike_index = strike_index;
232 
233     FT_Select_Metrics( size->face, strike_index );
234 
235     funcs = cff_size_get_globals_funcs( cffsize );
236 
237     if ( funcs )
238     {
239       CFF_Face      face     = (CFF_Face)size->face;
240       CFF_Font      font     = (CFF_Font)face->extra.data;
241       CFF_Internal  internal = (CFF_Internal)size->internal->module_data;
242 
243       FT_Long  top_upm  = (FT_Long)font->top_font.font_dict.units_per_em;
244       FT_UInt  i;
245 
246 
247       funcs->set_scale( internal->topfont,
248                         size->metrics.x_scale, size->metrics.y_scale,
249                         0, 0 );
250 
251       for ( i = font->num_subfonts; i > 0; i-- )
252       {
253         CFF_SubFont  sub     = font->subfonts[i - 1];
254         FT_Long      sub_upm = (FT_Long)sub->font_dict.units_per_em;
255         FT_Pos       x_scale, y_scale;
256 
257 
258         if ( top_upm != sub_upm )
259         {
260           x_scale = FT_MulDiv( size->metrics.x_scale, top_upm, sub_upm );
261           y_scale = FT_MulDiv( size->metrics.y_scale, top_upm, sub_upm );
262         }
263         else
264         {
265           x_scale = size->metrics.x_scale;
266           y_scale = size->metrics.y_scale;
267         }
268 
269         funcs->set_scale( internal->subfonts[i - 1],
270                           x_scale, y_scale, 0, 0 );
271       }
272     }
273 
274     return FT_Err_Ok;
275   }
276 
277 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
278 
279 
280   FT_LOCAL_DEF( FT_Error )
cff_size_request(FT_Size size,FT_Size_Request req)281   cff_size_request( FT_Size          size,
282                     FT_Size_Request  req )
283   {
284     FT_Error  error;
285 
286     CFF_Size           cffsize = (CFF_Size)size;
287     PSH_Globals_Funcs  funcs;
288 
289 
290 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
291 
292     if ( FT_HAS_FIXED_SIZES( size->face ) )
293     {
294       CFF_Face      cffface = (CFF_Face)size->face;
295       SFNT_Service  sfnt    = (SFNT_Service)cffface->sfnt;
296       FT_ULong      strike_index;
297 
298 
299       if ( sfnt->set_sbit_strike( cffface, req, &strike_index ) )
300         cffsize->strike_index = 0xFFFFFFFFUL;
301       else
302         return cff_size_select( size, strike_index );
303     }
304 
305 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
306 
307     error = FT_Request_Metrics( size->face, req );
308     if ( error )
309       goto Exit;
310 
311     funcs = cff_size_get_globals_funcs( cffsize );
312 
313     if ( funcs )
314     {
315       CFF_Face      cffface  = (CFF_Face)size->face;
316       CFF_Font      font     = (CFF_Font)cffface->extra.data;
317       CFF_Internal  internal = (CFF_Internal)size->internal->module_data;
318 
319       FT_Long  top_upm  = (FT_Long)font->top_font.font_dict.units_per_em;
320       FT_UInt  i;
321 
322 
323       funcs->set_scale( internal->topfont,
324                         size->metrics.x_scale, size->metrics.y_scale,
325                         0, 0 );
326 
327       for ( i = font->num_subfonts; i > 0; i-- )
328       {
329         CFF_SubFont  sub     = font->subfonts[i - 1];
330         FT_Long      sub_upm = (FT_Long)sub->font_dict.units_per_em;
331         FT_Pos       x_scale, y_scale;
332 
333 
334         if ( top_upm != sub_upm )
335         {
336           x_scale = FT_MulDiv( size->metrics.x_scale, top_upm, sub_upm );
337           y_scale = FT_MulDiv( size->metrics.y_scale, top_upm, sub_upm );
338         }
339         else
340         {
341           x_scale = size->metrics.x_scale;
342           y_scale = size->metrics.y_scale;
343         }
344 
345         funcs->set_scale( internal->subfonts[i - 1],
346                           x_scale, y_scale, 0, 0 );
347       }
348     }
349 
350   Exit:
351     return error;
352   }
353 
354 
355   /**************************************************************************
356    *
357    *                           SLOT  FUNCTIONS
358    *
359    */
360 
361   FT_LOCAL_DEF( void )
cff_slot_done(FT_GlyphSlot slot)362   cff_slot_done( FT_GlyphSlot  slot )
363   {
364     if ( slot->internal )
365       slot->internal->glyph_hints = NULL;
366   }
367 
368 
369   FT_LOCAL_DEF( FT_Error )
cff_slot_init(FT_GlyphSlot slot)370   cff_slot_init( FT_GlyphSlot  slot )
371   {
372     CFF_Face          face     = (CFF_Face)slot->face;
373     CFF_Font          font     = (CFF_Font)face->extra.data;
374     PSHinter_Service  pshinter = font->pshinter;
375 
376 
377     if ( pshinter )
378     {
379       FT_Module  module;
380 
381 
382       module = FT_Get_Module( slot->library, "pshinter" );
383       if ( module )
384       {
385         T2_Hints_Funcs  funcs;
386 
387 
388         funcs = pshinter->get_t2_funcs( module );
389         slot->internal->glyph_hints = (void*)funcs;
390       }
391     }
392 
393     return FT_Err_Ok;
394   }
395 
396 
397   /**************************************************************************
398    *
399    *                          FACE  FUNCTIONS
400    *
401    */
402 
403   static FT_String*
cff_strcpy(FT_Memory memory,const FT_String * source)404   cff_strcpy( FT_Memory         memory,
405               const FT_String*  source )
406   {
407     FT_Error    error;
408     FT_String*  result;
409 
410 
411     FT_MEM_STRDUP( result, source );
412 
413     return result;
414   }
415 
416 
417   /* Strip all subset prefixes of the form `ABCDEF+'.  Usually, there */
418   /* is only one, but font names like `APCOOG+JFABTD+FuturaBQ-Bold'   */
419   /* have been seen in the wild.                                      */
420 
421   static void
remove_subset_prefix(FT_String * name)422   remove_subset_prefix( FT_String*  name )
423   {
424     FT_Int32  idx             = 0;
425     FT_Int32  length          = (FT_Int32)ft_strlen( name ) + 1;
426     FT_Bool   continue_search = 1;
427 
428 
429     while ( continue_search )
430     {
431       if ( length >= 7 && name[6] == '+' )
432       {
433         for ( idx = 0; idx < 6; idx++ )
434         {
435           /* ASCII uppercase letters */
436           if ( !( 'A' <= name[idx] && name[idx] <= 'Z' ) )
437             continue_search = 0;
438         }
439 
440         if ( continue_search )
441         {
442           for ( idx = 7; idx < length; idx++ )
443             name[idx - 7] = name[idx];
444           length -= 7;
445         }
446       }
447       else
448         continue_search = 0;
449     }
450   }
451 
452 
453   /* Remove the style part from the family name (if present). */
454 
455   static void
remove_style(FT_String * family_name,const FT_String * style_name)456   remove_style( FT_String*        family_name,
457                 const FT_String*  style_name )
458   {
459     FT_Int32  family_name_length, style_name_length;
460 
461 
462     family_name_length = (FT_Int32)ft_strlen( family_name );
463     style_name_length  = (FT_Int32)ft_strlen( style_name );
464 
465     if ( family_name_length > style_name_length )
466     {
467       FT_Int  idx;
468 
469 
470       for ( idx = 1; idx <= style_name_length; idx++ )
471       {
472         if ( family_name[family_name_length - idx] !=
473              style_name[style_name_length - idx] )
474           break;
475       }
476 
477       if ( idx > style_name_length )
478       {
479         /* family_name ends with style_name; remove it */
480         idx = family_name_length - style_name_length - 1;
481 
482         /* also remove special characters     */
483         /* between real family name and style */
484         while ( idx > 0                     &&
485                 ( family_name[idx] == '-' ||
486                   family_name[idx] == ' ' ||
487                   family_name[idx] == '_' ||
488                   family_name[idx] == '+' ) )
489           idx--;
490 
491         if ( idx > 0 )
492           family_name[idx + 1] = '\0';
493       }
494     }
495   }
496 
497 
498   FT_LOCAL_DEF( FT_Error )
cff_face_init(FT_Stream stream,FT_Face cffface,FT_Int face_index,FT_Int num_params,FT_Parameter * params)499   cff_face_init( FT_Stream      stream,
500                  FT_Face        cffface,        /* CFF_Face */
501                  FT_Int         face_index,
502                  FT_Int         num_params,
503                  FT_Parameter*  params )
504   {
505     CFF_Face            face        = (CFF_Face)cffface;
506     FT_Error            error;
507     SFNT_Service        sfnt;
508     FT_Service_PsCMaps  psnames;
509     PSHinter_Service    pshinter;
510     PSAux_Service       psaux;
511     FT_Service_CFFLoad  cffload;
512     FT_Bool             pure_cff    = 1;
513     FT_Bool             cff2        = 0;
514     FT_Bool             sfnt_format = 0;
515     FT_Library          library     = cffface->driver->root.library;
516 
517 
518     sfnt = (SFNT_Service)FT_Get_Module_Interface( library,
519                                                   "sfnt" );
520     if ( !sfnt )
521     {
522       FT_ERROR(( "cff_face_init: cannot access `sfnt' module\n" ));
523       error = FT_THROW( Missing_Module );
524       goto Exit;
525     }
526 
527     FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
528 
529     pshinter = (PSHinter_Service)FT_Get_Module_Interface( library,
530                                                           "pshinter" );
531 
532     psaux = (PSAux_Service)FT_Get_Module_Interface( library,
533                                                     "psaux" );
534     if ( !psaux )
535     {
536       FT_ERROR(( "cff_face_init: cannot access `psaux' module\n" ));
537       error = FT_THROW( Missing_Module );
538       goto Exit;
539     }
540     face->psaux = psaux;
541 
542     FT_FACE_FIND_GLOBAL_SERVICE( face, cffload, CFF_LOAD );
543 
544     FT_TRACE2(( "CFF driver\n" ));
545 
546     /* create input stream from resource */
547     if ( FT_STREAM_SEEK( 0 ) )
548       goto Exit;
549 
550     /* check whether we have a valid OpenType file */
551     FT_TRACE2(( "  " ));
552     error = sfnt->init_face( stream, face, face_index, num_params, params );
553     if ( !error )
554     {
555       if ( face->format_tag != TTAG_OTTO )  /* `OTTO'; OpenType/CFF font */
556       {
557         FT_TRACE2(( "  not an OpenType/CFF font\n" ));
558         error = FT_THROW( Unknown_File_Format );
559         goto Exit;
560       }
561 
562       /* if we are performing a simple font format check, exit immediately */
563       if ( face_index < 0 )
564         return FT_Err_Ok;
565 
566       sfnt_format = 1;
567 
568       /* now, the font can be either an OpenType/CFF font, or an SVG CEF */
569       /* font; in the latter case it doesn't have a `head' table         */
570       error = face->goto_table( face, TTAG_head, stream, 0 );
571       if ( !error )
572       {
573         pure_cff = 0;
574 
575         /* load font directory */
576         error = sfnt->load_face( stream, face, face_index,
577                                  num_params, params );
578         if ( error )
579           goto Exit;
580       }
581       else
582       {
583         /* load the `cmap' table explicitly */
584         error = sfnt->load_cmap( face, stream );
585         if ( error )
586           goto Exit;
587       }
588 
589       /* now load the CFF part of the file; */
590       /* give priority to CFF2              */
591       error = face->goto_table( face, TTAG_CFF2, stream, 0 );
592       if ( !error )
593       {
594         cff2          = 1;
595         face->is_cff2 = cff2;
596       }
597 
598       if ( FT_ERR_EQ( error, Table_Missing ) )
599         error = face->goto_table( face, TTAG_CFF, stream, 0 );
600 
601       if ( error )
602         goto Exit;
603     }
604     else
605     {
606       /* rewind to start of file; we are going to load a pure-CFF font */
607       if ( FT_STREAM_SEEK( 0 ) )
608         goto Exit;
609       error = FT_Err_Ok;
610     }
611 
612     /* now load and parse the CFF table in the file */
613     {
614       CFF_Font         cff = NULL;
615       CFF_FontRecDict  dict;
616       FT_Memory        memory = cffface->memory;
617       FT_Int32         flags;
618       FT_UInt          i;
619 
620 
621       if ( FT_NEW( cff ) )
622         goto Exit;
623 
624       face->extra.data = cff;
625       error = cff_font_load( library,
626                              stream,
627                              face_index,
628                              cff,
629                              face,
630                              pure_cff,
631                              cff2 );
632       if ( error )
633         goto Exit;
634 
635       /* if we are performing a simple font format check, exit immediately */
636       /* (this is here for pure CFF)                                       */
637       if ( face_index < 0 )
638       {
639         cffface->num_faces = (FT_Long)cff->num_faces;
640         return FT_Err_Ok;
641       }
642 
643       cff->pshinter = pshinter;
644       cff->psnames  = psnames;
645       cff->cffload  = cffload;
646 
647       cffface->face_index = face_index & 0xFFFF;
648 
649       /* Complement the root flags with some interesting information. */
650       /* Note that this is only necessary for pure CFF and CEF fonts; */
651       /* SFNT based fonts use the `name' table instead.               */
652 
653       cffface->num_glyphs = (FT_Long)cff->num_glyphs;
654 
655       dict = &cff->top_font.font_dict;
656 
657       /* we need the `psnames' module for CFF and CEF formats */
658       /* which aren't CID-keyed                               */
659       if ( dict->cid_registry == 0xFFFFU && !psnames )
660       {
661         FT_ERROR(( "cff_face_init:"
662                    " cannot open CFF & CEF fonts\n" ));
663         FT_ERROR(( "              "
664                    " without the `psnames' module\n" ));
665         error = FT_THROW( Missing_Module );
666         goto Exit;
667       }
668 
669 #ifdef FT_DEBUG_LEVEL_TRACE
670       {
671         FT_UInt     idx;
672         FT_String*  s;
673 
674 
675         FT_TRACE4(( "SIDs\n" ));
676 
677         /* dump string index, including default strings for convenience */
678         for ( idx = 0; idx <= 390; idx++ )
679         {
680           s = cff_index_get_sid_string( cff, idx );
681           if ( s )
682             FT_TRACE4(( "  %5d %s\n", idx, s ));
683         }
684 
685         /* In Multiple Master CFFs, two SIDs hold the Normalize Design  */
686         /* Vector (NDV) and Convert Design Vector (CDV) charstrings,    */
687         /* which may contain null bytes in the middle of the data, too. */
688         /* We thus access `cff->strings' directly.                      */
689         for ( idx = 1; idx < cff->num_strings; idx++ )
690         {
691           FT_Byte*    s1    = cff->strings[idx - 1];
692           FT_Byte*    s2    = cff->strings[idx];
693           FT_PtrDist  s1len = s2 - s1 - 1; /* without the final null byte */
694           FT_PtrDist  l;
695 
696 
697           FT_TRACE4(( "  %5d ", idx + 390 ));
698           for ( l = 0; l < s1len; l++ )
699             FT_TRACE4(( "%c", s1[l] ));
700           FT_TRACE4(( "\n" ));
701         }
702 
703         /* print last element */
704         if ( cff->num_strings )
705         {
706           FT_Byte*    s1    = cff->strings[cff->num_strings - 1];
707           FT_Byte*    s2    = cff->string_pool + cff->string_pool_size;
708           FT_PtrDist  s1len = s2 - s1 - 1;
709           FT_PtrDist  l;
710 
711 
712           FT_TRACE4(( "  %5d ", cff->num_strings + 390 ));
713           for ( l = 0; l < s1len; l++ )
714             FT_TRACE4(( "%c", s1[l] ));
715           FT_TRACE4(( "\n" ));
716         }
717       }
718 #endif /* FT_DEBUG_LEVEL_TRACE */
719 
720 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
721       {
722         FT_UInt  instance_index = (FT_UInt)face_index >> 16;
723 
724 
725         if ( FT_HAS_MULTIPLE_MASTERS( cffface ) &&
726              instance_index > 0                 )
727         {
728           error = FT_Set_Named_Instance( cffface, instance_index );
729           if ( error )
730             goto Exit;
731         }
732       }
733 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
734 
735       if ( !dict->has_font_matrix )
736         dict->units_per_em = pure_cff ? 1000 : face->root.units_per_EM;
737 
738       /* Normalize the font matrix so that `matrix->yy' is 1; if  */
739       /* it is zero, we use `matrix->yx' instead.  The scaling is */
740       /* done with `units_per_em' then (at this point, it already */
741       /* contains the scaling factor, but without normalization   */
742       /* of the matrix).                                          */
743       /*                                                          */
744       /* Note that the offsets must be expressed in integer font  */
745       /* units.                                                   */
746 
747       {
748         FT_Matrix*  matrix = &dict->font_matrix;
749         FT_Vector*  offset = &dict->font_offset;
750         FT_ULong*   upm    = &dict->units_per_em;
751         FT_Fixed    temp;
752 
753 
754         temp = matrix->yy ? FT_ABS( matrix->yy )
755                           : FT_ABS( matrix->yx );
756 
757         if ( temp != 0x10000L )
758         {
759           *upm = (FT_ULong)FT_DivFix( (FT_Long)*upm, temp );
760 
761           matrix->xx = FT_DivFix( matrix->xx, temp );
762           matrix->yx = FT_DivFix( matrix->yx, temp );
763           matrix->xy = FT_DivFix( matrix->xy, temp );
764           matrix->yy = FT_DivFix( matrix->yy, temp );
765           offset->x  = FT_DivFix( offset->x,  temp );
766           offset->y  = FT_DivFix( offset->y,  temp );
767         }
768 
769         offset->x >>= 16;
770         offset->y >>= 16;
771       }
772 
773       for ( i = cff->num_subfonts; i > 0; i-- )
774       {
775         CFF_FontRecDict  sub = &cff->subfonts[i - 1]->font_dict;
776         CFF_FontRecDict  top = &cff->top_font.font_dict;
777 
778         FT_Matrix*  matrix;
779         FT_Vector*  offset;
780         FT_ULong*   upm;
781         FT_Fixed    temp;
782 
783 
784         if ( sub->has_font_matrix )
785         {
786           FT_Long  scaling;
787 
788 
789           /* if we have a top-level matrix, */
790           /* concatenate the subfont matrix */
791 
792           if ( top->has_font_matrix )
793           {
794             if ( top->units_per_em > 1 && sub->units_per_em > 1 )
795               scaling = (FT_Long)FT_MIN( top->units_per_em,
796                                          sub->units_per_em );
797             else
798               scaling = 1;
799 
800             FT_Matrix_Multiply_Scaled( &top->font_matrix,
801                                        &sub->font_matrix,
802                                        scaling );
803             FT_Vector_Transform_Scaled( &sub->font_offset,
804                                         &top->font_matrix,
805                                         scaling );
806 
807             sub->units_per_em = (FT_ULong)
808                                   FT_MulDiv( (FT_Long)sub->units_per_em,
809                                              (FT_Long)top->units_per_em,
810                                              scaling );
811           }
812         }
813         else
814         {
815           sub->font_matrix = top->font_matrix;
816           sub->font_offset = top->font_offset;
817 
818           sub->units_per_em = top->units_per_em;
819         }
820 
821         matrix = &sub->font_matrix;
822         offset = &sub->font_offset;
823         upm    = &sub->units_per_em;
824 
825         temp = matrix->yy ? FT_ABS( matrix->yy )
826                           : FT_ABS( matrix->yx );
827 
828 
829         if ( temp != 0x10000L )
830         {
831           *upm = (FT_ULong)FT_DivFix( (FT_Long)*upm, temp );
832 
833           matrix->xx = FT_DivFix( matrix->xx, temp );
834           matrix->yx = FT_DivFix( matrix->yx, temp );
835           matrix->xy = FT_DivFix( matrix->xy, temp );
836           matrix->yy = FT_DivFix( matrix->yy, temp );
837           offset->x  = FT_DivFix( offset->x,  temp );
838           offset->y  = FT_DivFix( offset->y,  temp );
839         }
840 
841         offset->x >>= 16;
842         offset->y >>= 16;
843       }
844 
845       if ( pure_cff )
846       {
847         char*  style_name = NULL;
848 
849 
850         /* set up num_faces */
851         cffface->num_faces = (FT_Long)cff->num_faces;
852 
853         /* compute number of glyphs */
854         if ( dict->cid_registry != 0xFFFFU )
855           cffface->num_glyphs = (FT_Long)( cff->charset.max_cid + 1 );
856         else
857           cffface->num_glyphs = (FT_Long)cff->charstrings_index.count;
858 
859         /* set global bbox, as well as EM size */
860         cffface->bbox.xMin =   dict->font_bbox.xMin            >> 16;
861         cffface->bbox.yMin =   dict->font_bbox.yMin            >> 16;
862         /* no `U' suffix here to 0xFFFF! */
863         cffface->bbox.xMax = ( dict->font_bbox.xMax + 0xFFFF ) >> 16;
864         cffface->bbox.yMax = ( dict->font_bbox.yMax + 0xFFFF ) >> 16;
865 
866         cffface->units_per_EM = (FT_UShort)( dict->units_per_em );
867 
868         cffface->ascender  = (FT_Short)( cffface->bbox.yMax );
869         cffface->descender = (FT_Short)( cffface->bbox.yMin );
870 
871         cffface->height = (FT_Short)( ( cffface->units_per_EM * 12 ) / 10 );
872         if ( cffface->height < cffface->ascender - cffface->descender )
873           cffface->height = (FT_Short)( cffface->ascender -
874                                         cffface->descender );
875 
876         cffface->underline_position  =
877           (FT_Short)( dict->underline_position >> 16 );
878         cffface->underline_thickness =
879           (FT_Short)( dict->underline_thickness >> 16 );
880 
881         /* retrieve font family & style name */
882         if ( dict->family_name )
883         {
884           char*  family_name;
885 
886 
887           family_name = cff_index_get_sid_string( cff, dict->family_name );
888           if ( family_name )
889             cffface->family_name = cff_strcpy( memory, family_name );
890         }
891 
892         if ( !cffface->family_name )
893         {
894           cffface->family_name = cff_index_get_name(
895                                    cff,
896                                    (FT_UInt)( face_index & 0xFFFF ) );
897           if ( cffface->family_name )
898             remove_subset_prefix( cffface->family_name );
899         }
900 
901         if ( cffface->family_name )
902         {
903           char*  full   = cff_index_get_sid_string( cff,
904                                                     dict->full_name );
905           char*  fullp  = full;
906           char*  family = cffface->family_name;
907 
908 
909           /* We try to extract the style name from the full name.   */
910           /* We need to ignore spaces and dashes during the search. */
911           if ( full && family )
912           {
913             while ( *fullp )
914             {
915               /* skip common characters at the start of both strings */
916               if ( *fullp == *family )
917               {
918                 family++;
919                 fullp++;
920                 continue;
921               }
922 
923               /* ignore spaces and dashes in full name during comparison */
924               if ( *fullp == ' ' || *fullp == '-' )
925               {
926                 fullp++;
927                 continue;
928               }
929 
930               /* ignore spaces and dashes in family name during comparison */
931               if ( *family == ' ' || *family == '-' )
932               {
933                 family++;
934                 continue;
935               }
936 
937               if ( !*family && *fullp )
938               {
939                 /* The full name begins with the same characters as the  */
940                 /* family name, with spaces and dashes removed.  In this */
941                 /* case, the remaining string in `fullp' will be used as */
942                 /* the style name.                                       */
943                 style_name = cff_strcpy( memory, fullp );
944 
945                 /* remove the style part from the family name (if present) */
946                 if ( style_name )
947                   remove_style( cffface->family_name, style_name );
948               }
949               break;
950             }
951           }
952         }
953         else
954         {
955           char  *cid_font_name =
956                    cff_index_get_sid_string( cff,
957                                              dict->cid_font_name );
958 
959 
960           /* do we have a `/FontName' for a CID-keyed font? */
961           if ( cid_font_name )
962             cffface->family_name = cff_strcpy( memory, cid_font_name );
963         }
964 
965         if ( style_name )
966           cffface->style_name = style_name;
967         else
968           /* assume "Regular" style if we don't know better */
969           cffface->style_name = cff_strcpy( memory, "Regular" );
970 
971         /********************************************************************
972          *
973          * Compute face flags.
974          */
975         flags = FT_FACE_FLAG_SCALABLE   | /* scalable outlines */
976                 FT_FACE_FLAG_HORIZONTAL | /* horizontal data   */
977                 FT_FACE_FLAG_HINTER;      /* has native hinter */
978 
979         if ( sfnt_format )
980           flags |= FT_FACE_FLAG_SFNT;
981 
982         /* fixed width font? */
983         if ( dict->is_fixed_pitch )
984           flags |= FT_FACE_FLAG_FIXED_WIDTH;
985 
986   /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */
987 #if 0
988         /* kerning available? */
989         if ( face->kern_pairs )
990           flags |= FT_FACE_FLAG_KERNING;
991 #endif
992 
993         cffface->face_flags |= flags;
994 
995         /********************************************************************
996          *
997          * Compute style flags.
998          */
999         flags = 0;
1000 
1001         if ( dict->italic_angle )
1002           flags |= FT_STYLE_FLAG_ITALIC;
1003 
1004         {
1005           char  *weight = cff_index_get_sid_string( cff,
1006                                                     dict->weight );
1007 
1008 
1009           if ( weight )
1010             if ( !ft_strcmp( weight, "Bold"  ) ||
1011                  !ft_strcmp( weight, "Black" ) )
1012               flags |= FT_STYLE_FLAG_BOLD;
1013         }
1014 
1015         /* double check */
1016         if ( !(flags & FT_STYLE_FLAG_BOLD) && cffface->style_name )
1017           if ( !ft_strncmp( cffface->style_name, "Bold", 4 )  ||
1018                !ft_strncmp( cffface->style_name, "Black", 5 ) )
1019             flags |= FT_STYLE_FLAG_BOLD;
1020 
1021         cffface->style_flags = flags;
1022       }
1023 
1024       /* CID-keyed CFF or CFF2 fonts don't have glyph names -- the SFNT */
1025       /* loader has unset this flag because of the 3.0 `post' table.    */
1026       if ( dict->cid_registry == 0xFFFFU && !cff2 )
1027         cffface->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
1028 
1029       if ( dict->cid_registry != 0xFFFFU && pure_cff )
1030         cffface->face_flags |= FT_FACE_FLAG_CID_KEYED;
1031 
1032       /********************************************************************
1033        *
1034        * Compute char maps.
1035        */
1036 
1037       /* Try to synthesize a Unicode charmap if there is none available */
1038       /* already.  If an OpenType font contains a Unicode "cmap", we    */
1039       /* will use it, whatever be in the CFF part of the file.          */
1040       {
1041         FT_CharMapRec  cmaprec;
1042         FT_CharMap     cmap;
1043         FT_Int         nn;
1044         CFF_Encoding   encoding = &cff->encoding;
1045 
1046 
1047         for ( nn = 0; nn < cffface->num_charmaps; nn++ )
1048         {
1049           cmap = cffface->charmaps[nn];
1050 
1051           /* Windows Unicode? */
1052           if ( cmap->platform_id == TT_PLATFORM_MICROSOFT &&
1053                cmap->encoding_id == TT_MS_ID_UNICODE_CS   )
1054             goto Skip_Unicode;
1055 
1056           /* Apple Unicode platform id? */
1057           if ( cmap->platform_id == TT_PLATFORM_APPLE_UNICODE )
1058             goto Skip_Unicode; /* Apple Unicode */
1059         }
1060 
1061         /* since CID-keyed fonts don't contain glyph names, we can't */
1062         /* construct a cmap                                          */
1063         if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU )
1064           goto Exit;
1065 
1066         /* we didn't find a Unicode charmap -- synthesize one */
1067         cmaprec.face        = cffface;
1068         cmaprec.platform_id = TT_PLATFORM_MICROSOFT;
1069         cmaprec.encoding_id = TT_MS_ID_UNICODE_CS;
1070         cmaprec.encoding    = FT_ENCODING_UNICODE;
1071 
1072         nn = cffface->num_charmaps;
1073 
1074         error = FT_CMap_New( &cff_cmap_unicode_class_rec, NULL,
1075                              &cmaprec, NULL );
1076         if ( error                                      &&
1077              FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) &&
1078              FT_ERR_NEQ( error, Unimplemented_Feature ) )
1079           goto Exit;
1080         error = FT_Err_Ok;
1081 
1082         /* if no Unicode charmap was previously selected, select this one */
1083         if ( !cffface->charmap && nn != cffface->num_charmaps )
1084           cffface->charmap = cffface->charmaps[nn];
1085 
1086       Skip_Unicode:
1087         if ( encoding->count > 0 )
1088         {
1089           FT_CMap_Class  clazz;
1090 
1091 
1092           cmaprec.face        = cffface;
1093           cmaprec.platform_id = TT_PLATFORM_ADOBE;  /* Adobe platform id */
1094 
1095           if ( encoding->offset == 0 )
1096           {
1097             cmaprec.encoding_id = TT_ADOBE_ID_STANDARD;
1098             cmaprec.encoding    = FT_ENCODING_ADOBE_STANDARD;
1099             clazz               = &cff_cmap_encoding_class_rec;
1100           }
1101           else if ( encoding->offset == 1 )
1102           {
1103             cmaprec.encoding_id = TT_ADOBE_ID_EXPERT;
1104             cmaprec.encoding    = FT_ENCODING_ADOBE_EXPERT;
1105             clazz               = &cff_cmap_encoding_class_rec;
1106           }
1107           else
1108           {
1109             cmaprec.encoding_id = TT_ADOBE_ID_CUSTOM;
1110             cmaprec.encoding    = FT_ENCODING_ADOBE_CUSTOM;
1111             clazz               = &cff_cmap_encoding_class_rec;
1112           }
1113 
1114           error = FT_CMap_New( clazz, NULL, &cmaprec, NULL );
1115         }
1116       }
1117     }
1118 
1119   Exit:
1120     return error;
1121   }
1122 
1123 
1124   FT_LOCAL_DEF( void )
cff_face_done(FT_Face cffface)1125   cff_face_done( FT_Face  cffface )         /* CFF_Face */
1126   {
1127     CFF_Face      face = (CFF_Face)cffface;
1128     FT_Memory     memory;
1129     SFNT_Service  sfnt;
1130 
1131 
1132     if ( !face )
1133       return;
1134 
1135     memory = cffface->memory;
1136     sfnt   = (SFNT_Service)face->sfnt;
1137 
1138     if ( sfnt )
1139       sfnt->done_face( face );
1140 
1141     {
1142       CFF_Font  cff = (CFF_Font)face->extra.data;
1143 
1144 
1145       if ( cff )
1146       {
1147         cff_font_done( cff );
1148         FT_FREE( face->extra.data );
1149       }
1150     }
1151 
1152 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1153     cff_done_blend( cffface );
1154     face->blend = NULL;
1155 #endif
1156   }
1157 
1158 
1159   FT_LOCAL_DEF( FT_Error )
cff_driver_init(FT_Module module)1160   cff_driver_init( FT_Module  module )        /* CFF_Driver */
1161   {
1162     PS_Driver  driver = (PS_Driver)module;
1163 
1164     FT_UInt32  seed;
1165 
1166 
1167     /* set default property values, cf. `ftcffdrv.h' */
1168     driver->hinting_engine = FT_HINTING_ADOBE;
1169 
1170     driver->no_stem_darkening = TRUE;
1171 
1172     driver->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
1173     driver->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1;
1174     driver->darken_params[2] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2;
1175     driver->darken_params[3] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2;
1176     driver->darken_params[4] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3;
1177     driver->darken_params[5] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3;
1178     driver->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4;
1179     driver->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4;
1180 
1181     /* compute random seed from some memory addresses */
1182     seed = (FT_UInt32)( (FT_Offset)(char*)&seed          ^
1183                         (FT_Offset)(char*)&module        ^
1184                         (FT_Offset)(char*)module->memory );
1185     seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 );
1186 
1187     driver->random_seed = (FT_Int32)seed;
1188     if ( driver->random_seed < 0 )
1189       driver->random_seed = -driver->random_seed;
1190     else if ( driver->random_seed == 0 )
1191       driver->random_seed = 123456789;
1192 
1193     return FT_Err_Ok;
1194   }
1195 
1196 
1197   FT_LOCAL_DEF( void )
cff_driver_done(FT_Module module)1198   cff_driver_done( FT_Module  module )        /* CFF_Driver */
1199   {
1200     FT_UNUSED( module );
1201   }
1202 
1203 
1204 /* END */
1205