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