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 :: 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 :: input stream where to load font data. */ 287 /* */ 288 /* face_index :: The index of the font face in the resource. */ 289 /* */ 290 /* num_params :: Number of additional generic parameters. Ignored. */ 291 /* */ 292 /* params :: Additional generic parameters. Ignored. */ 293 /* */ 294 /* <InOut> */ 295 /* face :: The face record to build. */ 296 /* */ 297 /* <Return> */ 298 /* FreeType error code. 0 means success. */ 299 /* */ 300 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)301 T1_Face_Init( FT_Stream stream, 302 FT_Face t1face, /* T1_Face */ 303 FT_Int face_index, 304 FT_Int num_params, 305 FT_Parameter* params ) 306 { 307 T1_Face face = (T1_Face)t1face; 308 FT_Error error; 309 FT_Service_PsCMaps psnames; 310 PSAux_Service psaux; 311 T1_Font type1 = &face->type1; 312 PS_FontInfo info = &type1->font_info; 313 314 FT_UNUSED( num_params ); 315 FT_UNUSED( params ); 316 FT_UNUSED( stream ); 317 318 319 face->root.num_faces = 1; 320 321 FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); 322 face->psnames = psnames; 323 324 face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), 325 "psaux" ); 326 psaux = (PSAux_Service)face->psaux; 327 if ( !psaux ) 328 { 329 FT_ERROR(( "T1_Face_Init: cannot access `psaux' module\n" )); 330 error = FT_THROW( Missing_Module ); 331 goto Exit; 332 } 333 334 face->pshinter = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), 335 "pshinter" ); 336 337 FT_TRACE2(( "Type 1 driver\n" )); 338 339 /* open the tokenizer; this will also check the font format */ 340 error = T1_Open_Face( face ); 341 if ( error ) 342 goto Exit; 343 344 /* if we just wanted to check the format, leave successfully now */ 345 if ( face_index < 0 ) 346 goto Exit; 347 348 /* check the face index */ 349 if ( ( face_index & 0xFFFF ) > 0 ) 350 { 351 FT_ERROR(( "T1_Face_Init: invalid face index\n" )); 352 error = FT_THROW( Invalid_Argument ); 353 goto Exit; 354 } 355 356 /* now load the font program into the face object */ 357 358 /* initialize the face object fields */ 359 360 /* set up root face fields */ 361 { 362 FT_Face root = (FT_Face)&face->root; 363 364 365 root->num_glyphs = type1->num_glyphs; 366 root->face_index = 0; 367 368 root->face_flags |= FT_FACE_FLAG_SCALABLE | 369 FT_FACE_FLAG_HORIZONTAL | 370 FT_FACE_FLAG_GLYPH_NAMES | 371 FT_FACE_FLAG_HINTER; 372 373 if ( info->is_fixed_pitch ) 374 root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; 375 376 if ( face->blend ) 377 root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; 378 379 /* The following code to extract the family and the style is very */ 380 /* simplistic and might get some things wrong. For a full-featured */ 381 /* algorithm you might have a look at the whitepaper given at */ 382 /* */ 383 /* https://blogs.msdn.com/text/archive/2007/04/23/wpf-font-selection-model.aspx */ 384 385 /* get style name -- be careful, some broken fonts only */ 386 /* have a `/FontName' dictionary entry! */ 387 root->family_name = info->family_name; 388 root->style_name = NULL; 389 390 if ( root->family_name ) 391 { 392 char* full = info->full_name; 393 char* family = root->family_name; 394 395 396 if ( full ) 397 { 398 FT_Bool the_same = TRUE; 399 400 401 while ( *full ) 402 { 403 if ( *full == *family ) 404 { 405 family++; 406 full++; 407 } 408 else 409 { 410 if ( *full == ' ' || *full == '-' ) 411 full++; 412 else if ( *family == ' ' || *family == '-' ) 413 family++; 414 else 415 { 416 the_same = FALSE; 417 418 if ( !*family ) 419 root->style_name = full; 420 break; 421 } 422 } 423 } 424 425 if ( the_same ) 426 root->style_name = (char *)"Regular"; 427 } 428 } 429 else 430 { 431 /* do we have a `/FontName'? */ 432 if ( type1->font_name ) 433 root->family_name = type1->font_name; 434 } 435 436 if ( !root->style_name ) 437 { 438 if ( info->weight ) 439 root->style_name = info->weight; 440 else 441 /* assume `Regular' style because we don't know better */ 442 root->style_name = (char *)"Regular"; 443 } 444 445 /* compute style flags */ 446 root->style_flags = 0; 447 if ( info->italic_angle ) 448 root->style_flags |= FT_STYLE_FLAG_ITALIC; 449 if ( info->weight ) 450 { 451 if ( !ft_strcmp( info->weight, "Bold" ) || 452 !ft_strcmp( info->weight, "Black" ) ) 453 root->style_flags |= FT_STYLE_FLAG_BOLD; 454 } 455 456 /* no embedded bitmap support */ 457 root->num_fixed_sizes = 0; 458 root->available_sizes = NULL; 459 460 root->bbox.xMin = type1->font_bbox.xMin >> 16; 461 root->bbox.yMin = type1->font_bbox.yMin >> 16; 462 /* no `U' suffix here to 0xFFFF! */ 463 root->bbox.xMax = ( type1->font_bbox.xMax + 0xFFFF ) >> 16; 464 root->bbox.yMax = ( type1->font_bbox.yMax + 0xFFFF ) >> 16; 465 466 /* Set units_per_EM if we didn't set it in t1_parse_font_matrix. */ 467 if ( !root->units_per_EM ) 468 root->units_per_EM = 1000; 469 470 root->ascender = (FT_Short)( root->bbox.yMax ); 471 root->descender = (FT_Short)( root->bbox.yMin ); 472 473 root->height = (FT_Short)( ( root->units_per_EM * 12 ) / 10 ); 474 if ( root->height < root->ascender - root->descender ) 475 root->height = (FT_Short)( root->ascender - root->descender ); 476 477 /* now compute the maximum advance width */ 478 root->max_advance_width = 479 (FT_Short)( root->bbox.xMax ); 480 { 481 FT_Pos max_advance; 482 483 484 error = T1_Compute_Max_Advance( face, &max_advance ); 485 486 /* in case of error, keep the standard width */ 487 if ( !error ) 488 root->max_advance_width = (FT_Short)FIXED_TO_INT( max_advance ); 489 else 490 error = FT_Err_Ok; /* clear error */ 491 } 492 493 root->max_advance_height = root->height; 494 495 root->underline_position = (FT_Short)info->underline_position; 496 root->underline_thickness = (FT_Short)info->underline_thickness; 497 } 498 499 { 500 FT_Face root = &face->root; 501 502 503 if ( psnames ) 504 { 505 FT_CharMapRec charmap; 506 T1_CMap_Classes cmap_classes = psaux->t1_cmap_classes; 507 FT_CMap_Class clazz; 508 509 510 charmap.face = root; 511 512 /* first of all, try to synthesize a Unicode charmap */ 513 charmap.platform_id = TT_PLATFORM_MICROSOFT; 514 charmap.encoding_id = TT_MS_ID_UNICODE_CS; 515 charmap.encoding = FT_ENCODING_UNICODE; 516 517 error = FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL ); 518 if ( error && 519 FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) ) 520 goto Exit; 521 error = FT_Err_Ok; 522 523 /* now, generate an Adobe Standard encoding when appropriate */ 524 charmap.platform_id = TT_PLATFORM_ADOBE; 525 clazz = NULL; 526 527 switch ( type1->encoding_type ) 528 { 529 case T1_ENCODING_TYPE_STANDARD: 530 charmap.encoding = FT_ENCODING_ADOBE_STANDARD; 531 charmap.encoding_id = TT_ADOBE_ID_STANDARD; 532 clazz = cmap_classes->standard; 533 break; 534 535 case T1_ENCODING_TYPE_EXPERT: 536 charmap.encoding = FT_ENCODING_ADOBE_EXPERT; 537 charmap.encoding_id = TT_ADOBE_ID_EXPERT; 538 clazz = cmap_classes->expert; 539 break; 540 541 case T1_ENCODING_TYPE_ARRAY: 542 charmap.encoding = FT_ENCODING_ADOBE_CUSTOM; 543 charmap.encoding_id = TT_ADOBE_ID_CUSTOM; 544 clazz = cmap_classes->custom; 545 break; 546 547 case T1_ENCODING_TYPE_ISOLATIN1: 548 charmap.encoding = FT_ENCODING_ADOBE_LATIN_1; 549 charmap.encoding_id = TT_ADOBE_ID_LATIN_1; 550 clazz = cmap_classes->unicode; 551 break; 552 553 default: 554 ; 555 } 556 557 if ( clazz ) 558 error = FT_CMap_New( clazz, NULL, &charmap, NULL ); 559 } 560 } 561 562 Exit: 563 return error; 564 } 565 566 567 /*************************************************************************/ 568 /* */ 569 /* <Function> */ 570 /* T1_Driver_Init */ 571 /* */ 572 /* <Description> */ 573 /* Initializes a given Type 1 driver object. */ 574 /* */ 575 /* <Input> */ 576 /* driver :: A handle to the target driver object. */ 577 /* */ 578 /* <Return> */ 579 /* FreeType error code. 0 means success. */ 580 /* */ 581 FT_LOCAL_DEF( FT_Error ) T1_Driver_Init(FT_Module module)582 T1_Driver_Init( FT_Module module ) 583 { 584 PS_Driver driver = (PS_Driver)module; 585 586 FT_UInt32 seed; 587 588 589 /* set default property values, cf. `ftt1drv.h' */ 590 #ifdef T1_CONFIG_OPTION_OLD_ENGINE 591 driver->hinting_engine = FT_HINTING_FREETYPE; 592 #else 593 driver->hinting_engine = FT_HINTING_ADOBE; 594 #endif 595 596 driver->no_stem_darkening = TRUE; 597 598 driver->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1; 599 driver->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1; 600 driver->darken_params[2] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2; 601 driver->darken_params[3] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2; 602 driver->darken_params[4] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3; 603 driver->darken_params[5] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3; 604 driver->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4; 605 driver->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4; 606 607 /* compute random seed from some memory addresses */ 608 seed = (FT_UInt32)( (FT_Offset)(char*)&seed ^ 609 (FT_Offset)(char*)&module ^ 610 (FT_Offset)(char*)module->memory ); 611 seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 ); 612 613 driver->random_seed = (FT_Int32)seed; 614 if ( driver->random_seed < 0 ) 615 driver->random_seed = -driver->random_seed; 616 else if ( driver->random_seed == 0 ) 617 driver->random_seed = 123456789; 618 619 return FT_Err_Ok; 620 } 621 622 623 /*************************************************************************/ 624 /* */ 625 /* <Function> */ 626 /* T1_Driver_Done */ 627 /* */ 628 /* <Description> */ 629 /* Finalizes a given Type 1 driver. */ 630 /* */ 631 /* <Input> */ 632 /* driver :: A handle to the target Type 1 driver. */ 633 /* */ 634 FT_LOCAL_DEF( void ) T1_Driver_Done(FT_Module driver)635 T1_Driver_Done( FT_Module driver ) 636 { 637 FT_UNUSED( driver ); 638 } 639 640 641 /* END */ 642