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