xref: /aosp_15_r20/external/freetype/src/type1/t1objs.c (revision 63949dbd25bcc50c4e1178497ff9e9574d44fc5a)
1 /****************************************************************************
2  *
3  * t1objs.c
4  *
5  *   Type 1 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 #include <freetype/internal/ftcalc.h>
20 #include <freetype/internal/ftdebug.h>
21 #include <freetype/internal/ftstream.h>
22 #include <freetype/ttnameid.h>
23 #include <freetype/ftdriver.h>
24 
25 #include "t1gload.h"
26 #include "t1load.h"
27 
28 #include "t1errors.h"
29 
30 #ifndef T1_CONFIG_OPTION_NO_AFM
31 #include "t1afm.h"
32 #endif
33 
34 #include <freetype/internal/services/svpscmap.h>
35 #include <freetype/internal/psaux.h>
36 
37 
38   /**************************************************************************
39    *
40    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
41    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
42    * messages during execution.
43    */
44 #undef  FT_COMPONENT
45 #define FT_COMPONENT  t1objs
46 
47 
48   /**************************************************************************
49    *
50    *                           SIZE FUNCTIONS
51    *
52    */
53 
54 
55   static PSH_Globals_Funcs
T1_Size_Get_Globals_Funcs(T1_Size size)56   T1_Size_Get_Globals_Funcs( T1_Size  size )
57   {
58     T1_Face           face     = (T1_Face)size->root.face;
59     PSHinter_Service  pshinter = (PSHinter_Service)face->pshinter;
60     FT_Module         module;
61 
62 
63     module = FT_Get_Module( size->root.face->driver->root.library,
64                             "pshinter" );
65     return ( module && pshinter && pshinter->get_globals_funcs )
66            ? pshinter->get_globals_funcs( module )
67            : 0;
68   }
69 
70 
71   FT_LOCAL_DEF( void )
T1_Size_Done(FT_Size t1size)72   T1_Size_Done( FT_Size  t1size )          /* T1_Size */
73   {
74     T1_Size  size = (T1_Size)t1size;
75 
76 
77     if ( t1size->internal->module_data )
78     {
79       PSH_Globals_Funcs  funcs;
80 
81 
82       funcs = T1_Size_Get_Globals_Funcs( size );
83       if ( funcs )
84         funcs->destroy( (PSH_Globals)t1size->internal->module_data );
85 
86       t1size->internal->module_data = NULL;
87     }
88   }
89 
90 
91   FT_LOCAL_DEF( FT_Error )
T1_Size_Init(FT_Size t1size)92   T1_Size_Init( FT_Size  t1size )      /* T1_Size */
93   {
94     T1_Size            size  = (T1_Size)t1size;
95     FT_Error           error = FT_Err_Ok;
96     PSH_Globals_Funcs  funcs = T1_Size_Get_Globals_Funcs( size );
97 
98 
99     if ( funcs )
100     {
101       PSH_Globals  globals;
102       T1_Face      face = (T1_Face)size->root.face;
103 
104 
105       error = funcs->create( size->root.face->memory,
106                              &face->type1.private_dict, &globals );
107       if ( !error )
108         t1size->internal->module_data = globals;
109     }
110 
111     return error;
112   }
113 
114 
115   FT_LOCAL_DEF( FT_Error )
T1_Size_Request(FT_Size t1size,FT_Size_Request req)116   T1_Size_Request( FT_Size          t1size,     /* T1_Size */
117                    FT_Size_Request  req )
118   {
119     FT_Error  error;
120 
121     T1_Size            size  = (T1_Size)t1size;
122     PSH_Globals_Funcs  funcs = T1_Size_Get_Globals_Funcs( size );
123 
124 
125     error = FT_Request_Metrics( size->root.face, req );
126     if ( error )
127       goto Exit;
128 
129     if ( funcs )
130       funcs->set_scale( (PSH_Globals)t1size->internal->module_data,
131                         size->root.metrics.x_scale,
132                         size->root.metrics.y_scale,
133                         0, 0 );
134 
135   Exit:
136     return error;
137   }
138 
139 
140   /**************************************************************************
141    *
142    *                           SLOT  FUNCTIONS
143    *
144    */
145 
146   FT_LOCAL_DEF( void )
T1_GlyphSlot_Done(FT_GlyphSlot slot)147   T1_GlyphSlot_Done( FT_GlyphSlot  slot )
148   {
149     /* `slot->internal` might be NULL in out-of-memory situations. */
150     if ( slot->internal )
151       slot->internal->glyph_hints = NULL;
152   }
153 
154 
155   FT_LOCAL_DEF( FT_Error )
T1_GlyphSlot_Init(FT_GlyphSlot slot)156   T1_GlyphSlot_Init( FT_GlyphSlot  slot )
157   {
158     T1_Face           face;
159     PSHinter_Service  pshinter;
160 
161 
162     face     = (T1_Face)slot->face;
163     pshinter = (PSHinter_Service)face->pshinter;
164 
165     if ( pshinter )
166     {
167       FT_Module  module;
168 
169 
170       module = FT_Get_Module( slot->library, "pshinter" );
171       if ( module )
172       {
173         T1_Hints_Funcs  funcs;
174 
175 
176         funcs = pshinter->get_t1_funcs( module );
177         slot->internal->glyph_hints = (void*)funcs;
178       }
179     }
180 
181     return 0;
182   }
183 
184 
185   /**************************************************************************
186    *
187    *                           FACE  FUNCTIONS
188    *
189    */
190 
191 
192   /**************************************************************************
193    *
194    * @Function:
195    *   T1_Face_Done
196    *
197    * @Description:
198    *   The face object destructor.
199    *
200    * @Input:
201    *   face ::
202    *     A typeless pointer to the face object to destroy.
203    */
204   FT_LOCAL_DEF( void )
T1_Face_Done(FT_Face t1face)205   T1_Face_Done( FT_Face  t1face )         /* T1_Face */
206   {
207     T1_Face    face = (T1_Face)t1face;
208     FT_Memory  memory;
209     T1_Font    type1;
210 
211 
212     if ( !face )
213       return;
214 
215     memory = face->root.memory;
216     type1  = &face->type1;
217 
218 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
219     /* release multiple masters information */
220     FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) );
221 
222     if ( face->buildchar )
223     {
224       FT_FREE( face->buildchar );
225 
226       face->len_buildchar = 0;
227     }
228 
229     T1_Done_Blend( t1face );
230     face->blend = NULL;
231 #endif
232 
233     /* release font info strings */
234     {
235       PS_FontInfo  info = &type1->font_info;
236 
237 
238       FT_FREE( info->version );
239       FT_FREE( info->notice );
240       FT_FREE( info->full_name );
241       FT_FREE( info->family_name );
242       FT_FREE( info->weight );
243     }
244 
245     /* release top dictionary */
246     FT_FREE( type1->charstrings_len );
247     FT_FREE( type1->charstrings );
248     FT_FREE( type1->glyph_names );
249 
250     FT_FREE( type1->subrs );
251     FT_FREE( type1->subrs_len );
252 
253     ft_hash_num_free( type1->subrs_hash, memory );
254     FT_FREE( type1->subrs_hash );
255 
256     FT_FREE( type1->subrs_block );
257     FT_FREE( type1->charstrings_block );
258     FT_FREE( type1->glyph_names_block );
259 
260     FT_FREE( type1->encoding.char_index );
261     FT_FREE( type1->encoding.char_name );
262     FT_FREE( type1->font_name );
263 
264 #ifndef T1_CONFIG_OPTION_NO_AFM
265     /* release afm data if present */
266     if ( face->afm_data )
267       T1_Done_Metrics( memory, (AFM_FontInfo)face->afm_data );
268 #endif
269 
270     /* release unicode map, if any */
271 #if 0
272     FT_FREE( face->unicode_map_rec.maps );
273     face->unicode_map_rec.num_maps = 0;
274     face->unicode_map              = NULL;
275 #endif
276 
277     face->root.family_name = NULL;
278     face->root.style_name  = NULL;
279   }
280 
281 
282   /**************************************************************************
283    *
284    * @Function:
285    *   T1_Face_Init
286    *
287    * @Description:
288    *   The face object constructor.
289    *
290    * @Input:
291    *   stream ::
292    *     Dummy argument for compatibility with the `FT_Face_InitFunc` API.
293    *     Ignored.  The stream should be passed through `face->root.stream`.
294    *
295    *   face_index ::
296    *     The index of the font face in the resource.
297    *
298    *   num_params ::
299    *     Number of additional generic parameters.  Ignored.
300    *
301    *   params ::
302    *     Additional generic parameters.  Ignored.
303    *
304    * @InOut:
305    *   face ::
306    *     The face record to build.
307    *
308    * @Return:
309    *   FreeType error code.  0 means success.
310    */
311   FT_LOCAL_DEF( FT_Error )
T1_Face_Init(FT_Stream stream,FT_Face t1face,FT_Int face_index,FT_Int num_params,FT_Parameter * params)312   T1_Face_Init( FT_Stream      stream,
313                 FT_Face        t1face,          /* T1_Face */
314                 FT_Int         face_index,
315                 FT_Int         num_params,
316                 FT_Parameter*  params )
317   {
318     T1_Face             face = (T1_Face)t1face;
319     FT_Error            error;
320     FT_Service_PsCMaps  psnames;
321     PSAux_Service       psaux;
322     T1_Font             type1 = &face->type1;
323     PS_FontInfo         info = &type1->font_info;
324 
325     FT_UNUSED( num_params );
326     FT_UNUSED( params );
327     FT_UNUSED( stream );
328 
329 
330     face->root.num_faces = 1;
331 
332     FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
333     face->psnames = psnames;
334 
335     face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
336                                            "psaux" );
337     psaux = (PSAux_Service)face->psaux;
338     if ( !psaux )
339     {
340       FT_ERROR(( "T1_Face_Init: cannot access `psaux' module\n" ));
341       error = FT_THROW( Missing_Module );
342       goto Exit;
343     }
344 
345     face->pshinter = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
346                                               "pshinter" );
347 
348     FT_TRACE2(( "Type 1 driver\n" ));
349 
350     /* open the tokenizer; this will also check the font format */
351     error = T1_Open_Face( face );
352     if ( error )
353       goto Exit;
354 
355     FT_TRACE2(( "T1_Face_Init: %p (index %d)\n",
356                 (void *)face,
357                 face_index ));
358 
359     /* if we just wanted to check the format, leave successfully now */
360     if ( face_index < 0 )
361       goto Exit;
362 
363     /* check the face index */
364     if ( ( face_index & 0xFFFF ) > 0 )
365     {
366       FT_ERROR(( "T1_Face_Init: invalid face index\n" ));
367       error = FT_THROW( Invalid_Argument );
368       goto Exit;
369     }
370 
371     /* now load the font program into the face object */
372 
373     /* initialize the face object fields */
374 
375     /* set up root face fields */
376     {
377       FT_Face  root = (FT_Face)&face->root;
378 
379 
380       root->num_glyphs = type1->num_glyphs;
381       root->face_index = 0;
382 
383       root->face_flags |= FT_FACE_FLAG_SCALABLE    |
384                           FT_FACE_FLAG_HORIZONTAL  |
385                           FT_FACE_FLAG_GLYPH_NAMES |
386                           FT_FACE_FLAG_HINTER;
387 
388       if ( info->is_fixed_pitch )
389         root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
390 
391       if ( face->blend )
392         root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
393 
394       /* The following code to extract the family and the style is very   */
395       /* simplistic and might get some things wrong.  For a full-featured */
396       /* algorithm you might have a look at the whitepaper given at       */
397       /*                                                                  */
398       /*   https://blogs.msdn.com/text/archive/2007/04/23/wpf-font-selection-model.aspx */
399 
400       /* get style name -- be careful, some broken fonts only */
401       /* have a `/FontName' dictionary entry!                 */
402       root->family_name = info->family_name;
403       root->style_name  = NULL;
404 
405       if ( root->family_name )
406       {
407         char*  full   = info->full_name;
408         char*  family = root->family_name;
409 
410 
411         if ( full )
412         {
413           FT_Bool  the_same = TRUE;
414 
415 
416           while ( *full )
417           {
418             if ( *full == *family )
419             {
420               family++;
421               full++;
422             }
423             else
424             {
425               if ( *full == ' ' || *full == '-' )
426                 full++;
427               else if ( *family == ' ' || *family == '-' )
428                 family++;
429               else
430               {
431                 the_same = FALSE;
432 
433                 if ( !*family )
434                   root->style_name = full;
435                 break;
436               }
437             }
438           }
439 
440           if ( the_same )
441             root->style_name = (char *)"Regular";
442         }
443       }
444       else
445       {
446         /* do we have a `/FontName'? */
447         if ( type1->font_name )
448           root->family_name = type1->font_name;
449       }
450 
451       if ( !root->style_name )
452       {
453         if ( info->weight )
454           root->style_name = info->weight;
455         else
456           /* assume `Regular' style because we don't know better */
457           root->style_name = (char *)"Regular";
458       }
459 
460       /* compute style flags */
461       root->style_flags = 0;
462       if ( info->italic_angle )
463         root->style_flags |= FT_STYLE_FLAG_ITALIC;
464       if ( info->weight )
465       {
466         if ( !ft_strcmp( info->weight, "Bold"  ) ||
467              !ft_strcmp( info->weight, "Black" ) )
468           root->style_flags |= FT_STYLE_FLAG_BOLD;
469       }
470 
471       /* no embedded bitmap support */
472       root->num_fixed_sizes = 0;
473       root->available_sizes = NULL;
474 
475       root->bbox.xMin =   type1->font_bbox.xMin            >> 16;
476       root->bbox.yMin =   type1->font_bbox.yMin            >> 16;
477       /* no `U' suffix here to 0xFFFF! */
478       root->bbox.xMax = ( type1->font_bbox.xMax + 0xFFFF ) >> 16;
479       root->bbox.yMax = ( type1->font_bbox.yMax + 0xFFFF ) >> 16;
480 
481       /* Set units_per_EM if we didn't set it in t1_parse_font_matrix. */
482       if ( !root->units_per_EM )
483         root->units_per_EM = 1000;
484 
485       root->ascender  = (FT_Short)( root->bbox.yMax );
486       root->descender = (FT_Short)( root->bbox.yMin );
487 
488       root->height = (FT_Short)( ( root->units_per_EM * 12 ) / 10 );
489       if ( root->height < root->ascender - root->descender )
490         root->height = (FT_Short)( root->ascender - root->descender );
491 
492       /* now compute the maximum advance width */
493       root->max_advance_width =
494         (FT_Short)( root->bbox.xMax );
495       {
496         FT_Pos  max_advance;
497 
498 
499         error = T1_Compute_Max_Advance( face, &max_advance );
500 
501         /* in case of error, keep the standard width */
502         if ( !error )
503           root->max_advance_width = (FT_Short)FIXED_TO_INT( max_advance );
504         else
505           error = FT_Err_Ok;   /* clear error */
506       }
507 
508       root->max_advance_height = root->height;
509 
510       root->underline_position  = (FT_Short)info->underline_position;
511       root->underline_thickness = (FT_Short)info->underline_thickness;
512     }
513 
514     {
515       FT_Face  root = &face->root;
516 
517 
518       if ( psnames )
519       {
520         FT_CharMapRec    charmap;
521         T1_CMap_Classes  cmap_classes = psaux->t1_cmap_classes;
522         FT_CMap_Class    clazz;
523 
524 
525         charmap.face = root;
526 
527         /* first of all, try to synthesize a Unicode charmap */
528         charmap.platform_id = TT_PLATFORM_MICROSOFT;
529         charmap.encoding_id = TT_MS_ID_UNICODE_CS;
530         charmap.encoding    = FT_ENCODING_UNICODE;
531 
532         error = FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL );
533         if ( error                                      &&
534              FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) &&
535              FT_ERR_NEQ( error, Unimplemented_Feature ) )
536           goto Exit;
537         error = FT_Err_Ok;
538 
539         /* now, generate an Adobe Standard encoding when appropriate */
540         charmap.platform_id = TT_PLATFORM_ADOBE;
541         clazz               = NULL;
542 
543         switch ( type1->encoding_type )
544         {
545         case T1_ENCODING_TYPE_STANDARD:
546           charmap.encoding    = FT_ENCODING_ADOBE_STANDARD;
547           charmap.encoding_id = TT_ADOBE_ID_STANDARD;
548           clazz               = cmap_classes->standard;
549           break;
550 
551         case T1_ENCODING_TYPE_EXPERT:
552           charmap.encoding    = FT_ENCODING_ADOBE_EXPERT;
553           charmap.encoding_id = TT_ADOBE_ID_EXPERT;
554           clazz               = cmap_classes->expert;
555           break;
556 
557         case T1_ENCODING_TYPE_ARRAY:
558           charmap.encoding    = FT_ENCODING_ADOBE_CUSTOM;
559           charmap.encoding_id = TT_ADOBE_ID_CUSTOM;
560           clazz               = cmap_classes->custom;
561           break;
562 
563         case T1_ENCODING_TYPE_ISOLATIN1:
564           charmap.encoding    = FT_ENCODING_ADOBE_LATIN_1;
565           charmap.encoding_id = TT_ADOBE_ID_LATIN_1;
566           clazz               = cmap_classes->unicode;
567           break;
568 
569         default:
570           ;
571         }
572 
573         if ( clazz )
574           error = FT_CMap_New( clazz, NULL, &charmap, NULL );
575       }
576     }
577 
578   Exit:
579     return error;
580   }
581 
582 
583   /**************************************************************************
584    *
585    * @Function:
586    *   T1_Driver_Init
587    *
588    * @Description:
589    *   Initializes a given Type 1 driver object.
590    *
591    * @Input:
592    *   driver ::
593    *     A handle to the target driver object.
594    *
595    * @Return:
596    *   FreeType error code.  0 means success.
597    */
598   FT_LOCAL_DEF( FT_Error )
T1_Driver_Init(FT_Module module)599   T1_Driver_Init( FT_Module  module )
600   {
601     PS_Driver  driver = (PS_Driver)module;
602 
603     FT_UInt32  seed;
604 
605 
606     /* set default property values, cf. `ftt1drv.h' */
607     driver->hinting_engine = FT_HINTING_ADOBE;
608 
609     driver->no_stem_darkening = TRUE;
610 
611     driver->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
612     driver->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1;
613     driver->darken_params[2] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2;
614     driver->darken_params[3] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2;
615     driver->darken_params[4] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3;
616     driver->darken_params[5] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3;
617     driver->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4;
618     driver->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4;
619 
620     /* compute random seed from some memory addresses */
621     seed = (FT_UInt32)( (FT_Offset)(char*)&seed          ^
622                         (FT_Offset)(char*)&module        ^
623                         (FT_Offset)(char*)module->memory );
624     seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 );
625 
626     driver->random_seed = (FT_Int32)seed;
627     if ( driver->random_seed < 0 )
628       driver->random_seed = -driver->random_seed;
629     else if ( driver->random_seed == 0 )
630       driver->random_seed = 123456789;
631 
632     return FT_Err_Ok;
633   }
634 
635 
636   /**************************************************************************
637    *
638    * @Function:
639    *   T1_Driver_Done
640    *
641    * @Description:
642    *   Finalizes a given Type 1 driver.
643    *
644    * @Input:
645    *   driver ::
646    *     A handle to the target Type 1 driver.
647    */
648   FT_LOCAL_DEF( void )
T1_Driver_Done(FT_Module driver)649   T1_Driver_Done( FT_Module  driver )
650   {
651     FT_UNUSED( driver );
652   }
653 
654 
655 /* END */
656