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