1 /***************************************************************************/ 2 /* */ 3 /* t1objs.c */ 4 /* */ 5 /* Type 1 objects manager (body). */ 6 /* */ 7 /* Copyright 1996-2009, 2011, 2013 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 T1_Size_Get_Globals_Funcs(T1_Size size)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 ) T1_Size_Done(FT_Size t1size)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 = 0; 90 } 91 } 92 93 94 FT_LOCAL_DEF( FT_Error ) T1_Size_Init(FT_Size t1size)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 ) T1_Size_Request(FT_Size t1size,FT_Size_Request req)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 ) T1_GlyphSlot_Done(FT_GlyphSlot slot)145 T1_GlyphSlot_Done( FT_GlyphSlot slot ) 146 { 147 slot->internal->glyph_hints = 0; 148 } 149 150 151 FT_LOCAL_DEF( FT_Error ) T1_GlyphSlot_Init(FT_GlyphSlot slot)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 ) T1_Face_Done(FT_Face t1face)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 = 0; 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 ) T1_Face_Init(FT_Stream stream,FT_Face t1face,FT_Int face_index,FT_Int num_params,FT_Parameter * params)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 > 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 /* XXX: TODO -- add kerning with .afm support */ 379 380 381 /* The following code to extract the family and the style is very */ 382 /* simplistic and might get some things wrong. For a full-featured */ 383 /* algorithm you might have a look at the whitepaper given at */ 384 /* */ 385 /* http://blogs.msdn.com/text/archive/2007/04/23/wpf-font-selection-model.aspx */ 386 387 /* get style name -- be careful, some broken fonts only */ 388 /* have a `/FontName' dictionary entry! */ 389 root->family_name = info->family_name; 390 root->style_name = NULL; 391 392 if ( root->family_name ) 393 { 394 char* full = info->full_name; 395 char* family = root->family_name; 396 397 398 if ( full ) 399 { 400 FT_Bool the_same = TRUE; 401 402 403 while ( *full ) 404 { 405 if ( *full == *family ) 406 { 407 family++; 408 full++; 409 } 410 else 411 { 412 if ( *full == ' ' || *full == '-' ) 413 full++; 414 else if ( *family == ' ' || *family == '-' ) 415 family++; 416 else 417 { 418 the_same = FALSE; 419 420 if ( !*family ) 421 root->style_name = full; 422 break; 423 } 424 } 425 } 426 427 if ( the_same ) 428 root->style_name = (char *)"Regular"; 429 } 430 } 431 else 432 { 433 /* do we have a `/FontName'? */ 434 if ( type1->font_name ) 435 root->family_name = type1->font_name; 436 } 437 438 if ( !root->style_name ) 439 { 440 if ( info->weight ) 441 root->style_name = info->weight; 442 else 443 /* assume `Regular' style because we don't know better */ 444 root->style_name = (char *)"Regular"; 445 } 446 447 /* compute style flags */ 448 root->style_flags = 0; 449 if ( info->italic_angle ) 450 root->style_flags |= FT_STYLE_FLAG_ITALIC; 451 if ( info->weight ) 452 { 453 if ( !ft_strcmp( info->weight, "Bold" ) || 454 !ft_strcmp( info->weight, "Black" ) ) 455 root->style_flags |= FT_STYLE_FLAG_BOLD; 456 } 457 458 /* no embedded bitmap support */ 459 root->num_fixed_sizes = 0; 460 root->available_sizes = 0; 461 462 root->bbox.xMin = type1->font_bbox.xMin >> 16; 463 root->bbox.yMin = type1->font_bbox.yMin >> 16; 464 /* no `U' suffix here to 0xFFFF! */ 465 root->bbox.xMax = ( type1->font_bbox.xMax + 0xFFFF ) >> 16; 466 root->bbox.yMax = ( type1->font_bbox.yMax + 0xFFFF ) >> 16; 467 468 /* Set units_per_EM if we didn't set it in t1_parse_font_matrix. */ 469 if ( !root->units_per_EM ) 470 root->units_per_EM = 1000; 471 472 root->ascender = (FT_Short)( root->bbox.yMax ); 473 root->descender = (FT_Short)( root->bbox.yMin ); 474 475 root->height = (FT_Short)( ( root->units_per_EM * 12 ) / 10 ); 476 if ( root->height < root->ascender - root->descender ) 477 root->height = (FT_Short)( root->ascender - root->descender ); 478 479 /* now compute the maximum advance width */ 480 root->max_advance_width = 481 (FT_Short)( root->bbox.xMax ); 482 { 483 FT_Pos max_advance; 484 485 486 error = T1_Compute_Max_Advance( face, &max_advance ); 487 488 /* in case of error, keep the standard width */ 489 if ( !error ) 490 root->max_advance_width = (FT_Short)FIXED_TO_INT( max_advance ); 491 else 492 error = FT_Err_Ok; /* clear error */ 493 } 494 495 root->max_advance_height = root->height; 496 497 root->underline_position = (FT_Short)info->underline_position; 498 root->underline_thickness = (FT_Short)info->underline_thickness; 499 } 500 501 { 502 FT_Face root = &face->root; 503 504 505 if ( psnames ) 506 { 507 FT_CharMapRec charmap; 508 T1_CMap_Classes cmap_classes = psaux->t1_cmap_classes; 509 FT_CMap_Class clazz; 510 511 512 charmap.face = root; 513 514 /* first of all, try to synthesize a Unicode charmap */ 515 charmap.platform_id = TT_PLATFORM_MICROSOFT; 516 charmap.encoding_id = TT_MS_ID_UNICODE_CS; 517 charmap.encoding = FT_ENCODING_UNICODE; 518 519 error = FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL ); 520 if ( error && 521 FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) ) 522 goto Exit; 523 error = FT_Err_Ok; 524 525 /* now, generate an Adobe Standard encoding when appropriate */ 526 charmap.platform_id = TT_PLATFORM_ADOBE; 527 clazz = NULL; 528 529 switch ( type1->encoding_type ) 530 { 531 case T1_ENCODING_TYPE_STANDARD: 532 charmap.encoding = FT_ENCODING_ADOBE_STANDARD; 533 charmap.encoding_id = TT_ADOBE_ID_STANDARD; 534 clazz = cmap_classes->standard; 535 break; 536 537 case T1_ENCODING_TYPE_EXPERT: 538 charmap.encoding = FT_ENCODING_ADOBE_EXPERT; 539 charmap.encoding_id = TT_ADOBE_ID_EXPERT; 540 clazz = cmap_classes->expert; 541 break; 542 543 case T1_ENCODING_TYPE_ARRAY: 544 charmap.encoding = FT_ENCODING_ADOBE_CUSTOM; 545 charmap.encoding_id = TT_ADOBE_ID_CUSTOM; 546 clazz = cmap_classes->custom; 547 break; 548 549 case T1_ENCODING_TYPE_ISOLATIN1: 550 charmap.encoding = FT_ENCODING_ADOBE_LATIN_1; 551 charmap.encoding_id = TT_ADOBE_ID_LATIN_1; 552 clazz = cmap_classes->unicode; 553 break; 554 555 default: 556 ; 557 } 558 559 if ( clazz ) 560 error = FT_CMap_New( clazz, NULL, &charmap, NULL ); 561 562 #if 0 563 /* Select default charmap */ 564 if (root->num_charmaps) 565 root->charmap = root->charmaps[0]; 566 #endif 567 } 568 } 569 570 Exit: 571 return error; 572 } 573 574 575 /*************************************************************************/ 576 /* */ 577 /* <Function> */ 578 /* T1_Driver_Init */ 579 /* */ 580 /* <Description> */ 581 /* Initializes a given Type 1 driver object. */ 582 /* */ 583 /* <Input> */ 584 /* driver :: A handle to the target driver object. */ 585 /* */ 586 /* <Return> */ 587 /* FreeType error code. 0 means success. */ 588 /* */ 589 FT_LOCAL_DEF( FT_Error ) T1_Driver_Init(FT_Module driver)590 T1_Driver_Init( FT_Module driver ) 591 { 592 FT_UNUSED( driver ); 593 594 return FT_Err_Ok; 595 } 596 597 598 /*************************************************************************/ 599 /* */ 600 /* <Function> */ 601 /* T1_Driver_Done */ 602 /* */ 603 /* <Description> */ 604 /* Finalizes a given Type 1 driver. */ 605 /* */ 606 /* <Input> */ 607 /* driver :: A handle to the target Type 1 driver. */ 608 /* */ 609 FT_LOCAL_DEF( void ) T1_Driver_Done(FT_Module driver)610 T1_Driver_Done( FT_Module driver ) 611 { 612 FT_UNUSED( driver ); 613 } 614 615 616 /* END */ 617