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