1 /**************************************************************************** 2 * 3 * t1objs.c 4 * 5 * Type 1 objects manager (body). 6 * 7 * Copyright 1996-2018 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 trace_t1objs 47 48 49 /************************************************************************** 50 * 51 * SIZE FUNCTIONS 52 * 53 */ 54 55 56 static PSH_Globals_Funcs T1_Size_Get_Globals_Funcs(T1_Size size)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 ) T1_Size_Done(FT_Size t1size)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 ) T1_Size_Init(FT_Size t1size)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 ) T1_Size_Request(FT_Size t1size,FT_Size_Request req)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 ) T1_GlyphSlot_Done(FT_GlyphSlot slot)143 T1_GlyphSlot_Done( FT_GlyphSlot slot ) 144 { 145 slot->internal->glyph_hints = NULL; 146 } 147 148 149 FT_LOCAL_DEF( FT_Error ) T1_GlyphSlot_Init(FT_GlyphSlot slot)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 ) T1_Face_Done(FT_Face t1face)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 ) T1_Face_Init(FT_Stream stream,FT_Face t1face,FT_Int face_index,FT_Int num_params,FT_Parameter * params)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 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