1 /***************************************************************************/ 2 /* */ 3 /* t42objs.c */ 4 /* */ 5 /* Type 42 objects manager (body). */ 6 /* */ 7 /* Copyright 2002-2015 by */ 8 /* Roberto Alameda. */ 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 "t42objs.h" 20 #include "t42parse.h" 21 #include "t42error.h" 22 #include FT_INTERNAL_DEBUG_H 23 #include FT_LIST_H 24 #include FT_TRUETYPE_IDS_H 25 26 27 #undef FT_COMPONENT 28 #define FT_COMPONENT trace_t42 29 30 31 static FT_Error 32 T42_Open_Face( T42_Face face ) 33 { 34 T42_LoaderRec loader; 35 T42_Parser parser; 36 T1_Font type1 = &face->type1; 37 FT_Memory memory = face->root.memory; 38 FT_Error error; 39 40 PSAux_Service psaux = (PSAux_Service)face->psaux; 41 42 43 t42_loader_init( &loader, face ); 44 45 parser = &loader.parser; 46 47 if ( FT_ALLOC( face->ttf_data, 12 ) ) 48 goto Exit; 49 50 /* while parsing the font we always update `face->ttf_size' so that */ 51 /* even in case of buggy data (which might lead to premature end of */ 52 /* scanning without causing an error) the call to `FT_Open_Face' in */ 53 /* `T42_Face_Init' passes the correct size */ 54 face->ttf_size = 12; 55 56 error = t42_parser_init( parser, 57 face->root.stream, 58 memory, 59 psaux); 60 if ( error ) 61 goto Exit; 62 63 error = t42_parse_dict( face, &loader, 64 parser->base_dict, parser->base_len ); 65 if ( error ) 66 goto Exit; 67 68 if ( type1->font_type != 42 ) 69 { 70 FT_ERROR(( "T42_Open_Face: cannot handle FontType %d\n", 71 type1->font_type )); 72 error = FT_THROW( Unknown_File_Format ); 73 goto Exit; 74 } 75 76 /* now, propagate the charstrings and glyphnames tables */ 77 /* to the Type1 data */ 78 type1->num_glyphs = loader.num_glyphs; 79 80 if ( !loader.charstrings.init ) 81 { 82 FT_ERROR(( "T42_Open_Face: no charstrings array in face\n" )); 83 error = FT_THROW( Invalid_File_Format ); 84 } 85 86 loader.charstrings.init = 0; 87 type1->charstrings_block = loader.charstrings.block; 88 type1->charstrings = loader.charstrings.elements; 89 type1->charstrings_len = loader.charstrings.lengths; 90 91 /* we copy the glyph names `block' and `elements' fields; */ 92 /* the `lengths' field must be released later */ 93 type1->glyph_names_block = loader.glyph_names.block; 94 type1->glyph_names = (FT_String**)loader.glyph_names.elements; 95 loader.glyph_names.block = NULL; 96 loader.glyph_names.elements = NULL; 97 98 /* we must now build type1.encoding when we have a custom array */ 99 if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY ) 100 { 101 FT_Int charcode, idx, min_char, max_char; 102 FT_Byte* glyph_name; 103 104 105 /* OK, we do the following: for each element in the encoding */ 106 /* table, look up the index of the glyph having the same name */ 107 /* as defined in the CharStrings array. */ 108 /* The index is then stored in type1.encoding.char_index, and */ 109 /* the name in type1.encoding.char_name */ 110 111 min_char = 0; 112 max_char = 0; 113 114 charcode = 0; 115 for ( ; charcode < loader.encoding_table.max_elems; charcode++ ) 116 { 117 FT_Byte* char_name; 118 119 120 type1->encoding.char_index[charcode] = 0; 121 type1->encoding.char_name [charcode] = (char *)".notdef"; 122 123 char_name = loader.encoding_table.elements[charcode]; 124 if ( char_name ) 125 for ( idx = 0; idx < type1->num_glyphs; idx++ ) 126 { 127 glyph_name = (FT_Byte*)type1->glyph_names[idx]; 128 if ( ft_strcmp( (const char*)char_name, 129 (const char*)glyph_name ) == 0 ) 130 { 131 type1->encoding.char_index[charcode] = (FT_UShort)idx; 132 type1->encoding.char_name [charcode] = (char*)glyph_name; 133 134 /* Change min/max encoded char only if glyph name is */ 135 /* not /.notdef */ 136 if ( ft_strcmp( (const char*)".notdef", 137 (const char*)glyph_name ) != 0 ) 138 { 139 if ( charcode < min_char ) 140 min_char = charcode; 141 if ( charcode >= max_char ) 142 max_char = charcode + 1; 143 } 144 break; 145 } 146 } 147 } 148 149 type1->encoding.code_first = min_char; 150 type1->encoding.code_last = max_char; 151 type1->encoding.num_chars = loader.num_chars; 152 } 153 154 Exit: 155 t42_loader_done( &loader ); 156 return error; 157 } 158 159 160 /***************** Driver Functions *************/ 161 162 163 FT_LOCAL_DEF( FT_Error ) 164 T42_Face_Init( FT_Stream stream, 165 FT_Face t42face, /* T42_Face */ 166 FT_Int face_index, 167 FT_Int num_params, 168 FT_Parameter* params ) 169 { 170 T42_Face face = (T42_Face)t42face; 171 FT_Error error; 172 FT_Service_PsCMaps psnames; 173 PSAux_Service psaux; 174 FT_Face root = (FT_Face)&face->root; 175 T1_Font type1 = &face->type1; 176 PS_FontInfo info = &type1->font_info; 177 178 FT_UNUSED( num_params ); 179 FT_UNUSED( params ); 180 FT_UNUSED( stream ); 181 182 183 face->ttf_face = NULL; 184 face->root.num_faces = 1; 185 186 FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); 187 face->psnames = psnames; 188 189 face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), 190 "psaux" ); 191 psaux = (PSAux_Service)face->psaux; 192 if ( !psaux ) 193 { 194 FT_ERROR(( "T42_Face_Init: cannot access `psaux' module\n" )); 195 error = FT_THROW( Missing_Module ); 196 goto Exit; 197 } 198 199 FT_TRACE2(( "Type 42 driver\n" )); 200 201 /* open the tokenizer, this will also check the font format */ 202 error = T42_Open_Face( face ); 203 if ( error ) 204 goto Exit; 205 206 /* if we just wanted to check the format, leave successfully now */ 207 if ( face_index < 0 ) 208 goto Exit; 209 210 /* check the face index */ 211 if ( ( face_index & 0xFFFF ) > 0 ) 212 { 213 FT_ERROR(( "T42_Face_Init: invalid face index\n" )); 214 error = FT_THROW( Invalid_Argument ); 215 goto Exit; 216 } 217 218 /* Now load the font program into the face object */ 219 220 /* Init the face object fields */ 221 /* Now set up root face fields */ 222 223 root->num_glyphs = type1->num_glyphs; 224 root->num_charmaps = 0; 225 root->face_index = 0; 226 227 root->face_flags |= FT_FACE_FLAG_SCALABLE | 228 FT_FACE_FLAG_HORIZONTAL | 229 FT_FACE_FLAG_GLYPH_NAMES; 230 231 if ( info->is_fixed_pitch ) 232 root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; 233 234 /* We only set this flag if we have the patented bytecode interpreter. */ 235 /* There are no known `tricky' Type42 fonts that could be loaded with */ 236 /* the unpatented interpreter. */ 237 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 238 root->face_flags |= FT_FACE_FLAG_HINTER; 239 #endif 240 241 /* XXX: TODO -- add kerning with .afm support */ 242 243 /* get style name -- be careful, some broken fonts only */ 244 /* have a `/FontName' dictionary entry! */ 245 root->family_name = info->family_name; 246 /* assume "Regular" style if we don't know better */ 247 root->style_name = (char *)"Regular"; 248 if ( root->family_name ) 249 { 250 char* full = info->full_name; 251 char* family = root->family_name; 252 253 254 if ( full ) 255 { 256 while ( *full ) 257 { 258 if ( *full == *family ) 259 { 260 family++; 261 full++; 262 } 263 else 264 { 265 if ( *full == ' ' || *full == '-' ) 266 full++; 267 else if ( *family == ' ' || *family == '-' ) 268 family++; 269 else 270 { 271 if ( !*family ) 272 root->style_name = full; 273 break; 274 } 275 } 276 } 277 } 278 } 279 else 280 { 281 /* do we have a `/FontName'? */ 282 if ( type1->font_name ) 283 root->family_name = type1->font_name; 284 } 285 286 /* no embedded bitmap support */ 287 root->num_fixed_sizes = 0; 288 root->available_sizes = NULL; 289 290 /* Load the TTF font embedded in the T42 font */ 291 { 292 FT_Open_Args args; 293 294 295 args.flags = FT_OPEN_MEMORY | FT_OPEN_DRIVER; 296 args.driver = FT_Get_Module( FT_FACE_LIBRARY( face ), 297 "truetype" ); 298 args.memory_base = face->ttf_data; 299 args.memory_size = face->ttf_size; 300 301 if ( num_params ) 302 { 303 args.flags |= FT_OPEN_PARAMS; 304 args.num_params = num_params; 305 args.params = params; 306 } 307 308 error = FT_Open_Face( FT_FACE_LIBRARY( face ), 309 &args, 0, &face->ttf_face ); 310 } 311 312 if ( error ) 313 goto Exit; 314 315 FT_Done_Size( face->ttf_face->size ); 316 317 /* Ignore info in FontInfo dictionary and use the info from the */ 318 /* loaded TTF font. The PostScript interpreter also ignores it. */ 319 root->bbox = face->ttf_face->bbox; 320 root->units_per_EM = face->ttf_face->units_per_EM; 321 322 root->ascender = face->ttf_face->ascender; 323 root->descender = face->ttf_face->descender; 324 root->height = face->ttf_face->height; 325 326 root->max_advance_width = face->ttf_face->max_advance_width; 327 root->max_advance_height = face->ttf_face->max_advance_height; 328 329 root->underline_position = (FT_Short)info->underline_position; 330 root->underline_thickness = (FT_Short)info->underline_thickness; 331 332 /* compute style flags */ 333 root->style_flags = 0; 334 if ( info->italic_angle ) 335 root->style_flags |= FT_STYLE_FLAG_ITALIC; 336 337 if ( face->ttf_face->style_flags & FT_STYLE_FLAG_BOLD ) 338 root->style_flags |= FT_STYLE_FLAG_BOLD; 339 340 if ( face->ttf_face->face_flags & FT_FACE_FLAG_VERTICAL ) 341 root->face_flags |= FT_FACE_FLAG_VERTICAL; 342 343 { 344 if ( psnames ) 345 { 346 FT_CharMapRec charmap; 347 T1_CMap_Classes cmap_classes = psaux->t1_cmap_classes; 348 FT_CMap_Class clazz; 349 350 351 charmap.face = root; 352 353 /* first of all, try to synthesize a Unicode charmap */ 354 charmap.platform_id = TT_PLATFORM_MICROSOFT; 355 charmap.encoding_id = TT_MS_ID_UNICODE_CS; 356 charmap.encoding = FT_ENCODING_UNICODE; 357 358 error = FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL ); 359 if ( error && 360 FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) ) 361 goto Exit; 362 error = FT_Err_Ok; 363 364 /* now, generate an Adobe Standard encoding when appropriate */ 365 charmap.platform_id = TT_PLATFORM_ADOBE; 366 clazz = NULL; 367 368 switch ( type1->encoding_type ) 369 { 370 case T1_ENCODING_TYPE_STANDARD: 371 charmap.encoding = FT_ENCODING_ADOBE_STANDARD; 372 charmap.encoding_id = TT_ADOBE_ID_STANDARD; 373 clazz = cmap_classes->standard; 374 break; 375 376 case T1_ENCODING_TYPE_EXPERT: 377 charmap.encoding = FT_ENCODING_ADOBE_EXPERT; 378 charmap.encoding_id = TT_ADOBE_ID_EXPERT; 379 clazz = cmap_classes->expert; 380 break; 381 382 case T1_ENCODING_TYPE_ARRAY: 383 charmap.encoding = FT_ENCODING_ADOBE_CUSTOM; 384 charmap.encoding_id = TT_ADOBE_ID_CUSTOM; 385 clazz = cmap_classes->custom; 386 break; 387 388 case T1_ENCODING_TYPE_ISOLATIN1: 389 charmap.encoding = FT_ENCODING_ADOBE_LATIN_1; 390 charmap.encoding_id = TT_ADOBE_ID_LATIN_1; 391 clazz = cmap_classes->unicode; 392 break; 393 394 default: 395 ; 396 } 397 398 if ( clazz ) 399 error = FT_CMap_New( clazz, NULL, &charmap, NULL ); 400 401 #if 0 402 /* Select default charmap */ 403 if ( root->num_charmaps ) 404 root->charmap = root->charmaps[0]; 405 #endif 406 } 407 } 408 Exit: 409 return error; 410 } 411 412 413 FT_LOCAL_DEF( void ) 414 T42_Face_Done( FT_Face t42face ) 415 { 416 T42_Face face = (T42_Face)t42face; 417 T1_Font type1; 418 PS_FontInfo info; 419 FT_Memory memory; 420 421 422 if ( !face ) 423 return; 424 425 type1 = &face->type1; 426 info = &type1->font_info; 427 memory = face->root.memory; 428 429 /* delete internal ttf face prior to freeing face->ttf_data */ 430 if ( face->ttf_face ) 431 FT_Done_Face( face->ttf_face ); 432 433 /* release font info strings */ 434 FT_FREE( info->version ); 435 FT_FREE( info->notice ); 436 FT_FREE( info->full_name ); 437 FT_FREE( info->family_name ); 438 FT_FREE( info->weight ); 439 440 /* release top dictionary */ 441 FT_FREE( type1->charstrings_len ); 442 FT_FREE( type1->charstrings ); 443 FT_FREE( type1->glyph_names ); 444 445 FT_FREE( type1->charstrings_block ); 446 FT_FREE( type1->glyph_names_block ); 447 448 FT_FREE( type1->encoding.char_index ); 449 FT_FREE( type1->encoding.char_name ); 450 FT_FREE( type1->font_name ); 451 452 FT_FREE( face->ttf_data ); 453 454 #if 0 455 /* release afm data if present */ 456 if ( face->afm_data ) 457 T1_Done_AFM( memory, (T1_AFM*)face->afm_data ); 458 #endif 459 460 /* release unicode map, if any */ 461 FT_FREE( face->unicode_map.maps ); 462 face->unicode_map.num_maps = 0; 463 464 face->root.family_name = NULL; 465 face->root.style_name = NULL; 466 } 467 468 469 /*************************************************************************/ 470 /* */ 471 /* <Function> */ 472 /* T42_Driver_Init */ 473 /* */ 474 /* <Description> */ 475 /* Initializes a given Type 42 driver object. */ 476 /* */ 477 /* <Input> */ 478 /* driver :: A handle to the target driver object. */ 479 /* */ 480 /* <Return> */ 481 /* FreeType error code. 0 means success. */ 482 /* */ 483 FT_LOCAL_DEF( FT_Error ) 484 T42_Driver_Init( FT_Module module ) /* T42_Driver */ 485 { 486 T42_Driver driver = (T42_Driver)module; 487 FT_Module ttmodule; 488 489 490 ttmodule = FT_Get_Module( module->library, "truetype" ); 491 if ( !ttmodule ) 492 { 493 FT_ERROR(( "T42_Driver_Init: cannot access `truetype' module\n" )); 494 return FT_THROW( Missing_Module ); 495 } 496 497 driver->ttclazz = (FT_Driver_Class)ttmodule->clazz; 498 499 return FT_Err_Ok; 500 } 501 502 503 FT_LOCAL_DEF( void ) 504 T42_Driver_Done( FT_Module module ) 505 { 506 FT_UNUSED( module ); 507 } 508 509 510 FT_LOCAL_DEF( FT_Error ) 511 T42_Size_Init( FT_Size size ) /* T42_Size */ 512 { 513 T42_Size t42size = (T42_Size)size; 514 FT_Face face = size->face; 515 T42_Face t42face = (T42_Face)face; 516 FT_Size ttsize; 517 FT_Error error; 518 519 520 error = FT_New_Size( t42face->ttf_face, &ttsize ); 521 t42size->ttsize = ttsize; 522 523 FT_Activate_Size( ttsize ); 524 525 return error; 526 } 527 528 529 FT_LOCAL_DEF( FT_Error ) 530 T42_Size_Request( FT_Size t42size, /* T42_Size */ 531 FT_Size_Request req ) 532 { 533 T42_Size size = (T42_Size)t42size; 534 T42_Face face = (T42_Face)t42size->face; 535 FT_Error error; 536 537 538 FT_Activate_Size( size->ttsize ); 539 540 error = FT_Request_Size( face->ttf_face, req ); 541 if ( !error ) 542 t42size->metrics = face->ttf_face->size->metrics; 543 544 return error; 545 } 546 547 548 FT_LOCAL_DEF( FT_Error ) 549 T42_Size_Select( FT_Size t42size, /* T42_Size */ 550 FT_ULong strike_index ) 551 { 552 T42_Size size = (T42_Size)t42size; 553 T42_Face face = (T42_Face)t42size->face; 554 FT_Error error; 555 556 557 FT_Activate_Size( size->ttsize ); 558 559 error = FT_Select_Size( face->ttf_face, (FT_Int)strike_index ); 560 if ( !error ) 561 t42size->metrics = face->ttf_face->size->metrics; 562 563 return error; 564 565 } 566 567 568 FT_LOCAL_DEF( void ) 569 T42_Size_Done( FT_Size t42size ) /* T42_Size */ 570 { 571 T42_Size size = (T42_Size)t42size; 572 FT_Face face = t42size->face; 573 T42_Face t42face = (T42_Face)face; 574 FT_ListNode node; 575 576 577 node = FT_List_Find( &t42face->ttf_face->sizes_list, size->ttsize ); 578 if ( node ) 579 { 580 FT_Done_Size( size->ttsize ); 581 size->ttsize = NULL; 582 } 583 } 584 585 586 FT_LOCAL_DEF( FT_Error ) 587 T42_GlyphSlot_Init( FT_GlyphSlot t42slot ) /* T42_GlyphSlot */ 588 { 589 T42_GlyphSlot slot = (T42_GlyphSlot)t42slot; 590 FT_Face face = t42slot->face; 591 T42_Face t42face = (T42_Face)face; 592 FT_GlyphSlot ttslot; 593 FT_Error error = FT_Err_Ok; 594 595 596 if ( face->glyph == NULL ) 597 { 598 /* First glyph slot for this face */ 599 slot->ttslot = t42face->ttf_face->glyph; 600 } 601 else 602 { 603 error = FT_New_GlyphSlot( t42face->ttf_face, &ttslot ); 604 slot->ttslot = ttslot; 605 } 606 607 return error; 608 } 609 610 611 FT_LOCAL_DEF( void ) 612 T42_GlyphSlot_Done( FT_GlyphSlot t42slot ) /* T42_GlyphSlot */ 613 { 614 T42_GlyphSlot slot = (T42_GlyphSlot)t42slot; 615 616 617 FT_Done_GlyphSlot( slot->ttslot ); 618 } 619 620 621 static void 622 t42_glyphslot_clear( FT_GlyphSlot slot ) 623 { 624 /* free bitmap if needed */ 625 ft_glyphslot_free_bitmap( slot ); 626 627 /* clear all public fields in the glyph slot */ 628 FT_ZERO( &slot->metrics ); 629 FT_ZERO( &slot->outline ); 630 FT_ZERO( &slot->bitmap ); 631 632 slot->bitmap_left = 0; 633 slot->bitmap_top = 0; 634 slot->num_subglyphs = 0; 635 slot->subglyphs = NULL; 636 slot->control_data = NULL; 637 slot->control_len = 0; 638 slot->other = NULL; 639 slot->format = FT_GLYPH_FORMAT_NONE; 640 641 slot->linearHoriAdvance = 0; 642 slot->linearVertAdvance = 0; 643 } 644 645 646 FT_LOCAL_DEF( FT_Error ) 647 T42_GlyphSlot_Load( FT_GlyphSlot glyph, 648 FT_Size size, 649 FT_UInt glyph_index, 650 FT_Int32 load_flags ) 651 { 652 FT_Error error; 653 T42_GlyphSlot t42slot = (T42_GlyphSlot)glyph; 654 T42_Size t42size = (T42_Size)size; 655 T42_Face t42face = (T42_Face)size->face; 656 FT_Driver_Class ttclazz = ((T42_Driver)glyph->face->driver)->ttclazz; 657 658 659 FT_TRACE1(( "T42_GlyphSlot_Load: glyph index %d\n", glyph_index )); 660 661 /* map T42 glyph index to embedded TTF's glyph index */ 662 glyph_index = (FT_UInt)ft_atol( 663 (const char *)t42face->type1.charstrings[glyph_index] ); 664 665 t42_glyphslot_clear( t42slot->ttslot ); 666 error = ttclazz->load_glyph( t42slot->ttslot, 667 t42size->ttsize, 668 glyph_index, 669 load_flags | FT_LOAD_NO_BITMAP ); 670 671 if ( !error ) 672 { 673 glyph->metrics = t42slot->ttslot->metrics; 674 675 glyph->linearHoriAdvance = t42slot->ttslot->linearHoriAdvance; 676 glyph->linearVertAdvance = t42slot->ttslot->linearVertAdvance; 677 678 glyph->format = t42slot->ttslot->format; 679 glyph->outline = t42slot->ttslot->outline; 680 681 glyph->bitmap = t42slot->ttslot->bitmap; 682 glyph->bitmap_left = t42slot->ttslot->bitmap_left; 683 glyph->bitmap_top = t42slot->ttslot->bitmap_top; 684 685 glyph->num_subglyphs = t42slot->ttslot->num_subglyphs; 686 glyph->subglyphs = t42slot->ttslot->subglyphs; 687 688 glyph->control_data = t42slot->ttslot->control_data; 689 glyph->control_len = t42slot->ttslot->control_len; 690 } 691 692 return error; 693 } 694 695 696 /* END */ 697