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