1 /***************************************************************************/ 2 /* */ 3 /* t42objs.c */ 4 /* */ 5 /* Type 42 objects manager (body). */ 6 /* */ 7 /* Copyright 2002-2018 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 T42_Open_Face(T42_Face face)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 ) T42_Face_Init(FT_Stream stream,FT_Face t42face,FT_Int face_index,FT_Int num_params,FT_Parameter * params)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 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 235 root->face_flags |= FT_FACE_FLAG_HINTER; 236 #endif 237 238 /* XXX: TODO -- add kerning with .afm support */ 239 240 /* get style name -- be careful, some broken fonts only */ 241 /* have a `/FontName' dictionary entry! */ 242 root->family_name = info->family_name; 243 /* assume "Regular" style if we don't know better */ 244 root->style_name = (char *)"Regular"; 245 if ( root->family_name ) 246 { 247 char* full = info->full_name; 248 char* family = root->family_name; 249 250 251 if ( full ) 252 { 253 while ( *full ) 254 { 255 if ( *full == *family ) 256 { 257 family++; 258 full++; 259 } 260 else 261 { 262 if ( *full == ' ' || *full == '-' ) 263 full++; 264 else if ( *family == ' ' || *family == '-' ) 265 family++; 266 else 267 { 268 if ( !*family ) 269 root->style_name = full; 270 break; 271 } 272 } 273 } 274 } 275 } 276 else 277 { 278 /* do we have a `/FontName'? */ 279 if ( type1->font_name ) 280 root->family_name = type1->font_name; 281 } 282 283 /* no embedded bitmap support */ 284 root->num_fixed_sizes = 0; 285 root->available_sizes = NULL; 286 287 /* Load the TTF font embedded in the T42 font */ 288 { 289 FT_Open_Args args; 290 291 292 args.flags = FT_OPEN_MEMORY | FT_OPEN_DRIVER; 293 args.driver = FT_Get_Module( FT_FACE_LIBRARY( face ), 294 "truetype" ); 295 args.memory_base = face->ttf_data; 296 args.memory_size = face->ttf_size; 297 298 if ( num_params ) 299 { 300 args.flags |= FT_OPEN_PARAMS; 301 args.num_params = num_params; 302 args.params = params; 303 } 304 305 error = FT_Open_Face( FT_FACE_LIBRARY( face ), 306 &args, 0, &face->ttf_face ); 307 } 308 309 if ( error ) 310 goto Exit; 311 312 FT_Done_Size( face->ttf_face->size ); 313 314 /* Ignore info in FontInfo dictionary and use the info from the */ 315 /* loaded TTF font. The PostScript interpreter also ignores it. */ 316 root->bbox = face->ttf_face->bbox; 317 root->units_per_EM = face->ttf_face->units_per_EM; 318 319 root->ascender = face->ttf_face->ascender; 320 root->descender = face->ttf_face->descender; 321 root->height = face->ttf_face->height; 322 323 root->max_advance_width = face->ttf_face->max_advance_width; 324 root->max_advance_height = face->ttf_face->max_advance_height; 325 326 root->underline_position = (FT_Short)info->underline_position; 327 root->underline_thickness = (FT_Short)info->underline_thickness; 328 329 /* compute style flags */ 330 root->style_flags = 0; 331 if ( info->italic_angle ) 332 root->style_flags |= FT_STYLE_FLAG_ITALIC; 333 334 if ( face->ttf_face->style_flags & FT_STYLE_FLAG_BOLD ) 335 root->style_flags |= FT_STYLE_FLAG_BOLD; 336 337 if ( face->ttf_face->face_flags & FT_FACE_FLAG_VERTICAL ) 338 root->face_flags |= FT_FACE_FLAG_VERTICAL; 339 340 { 341 if ( psnames ) 342 { 343 FT_CharMapRec charmap; 344 T1_CMap_Classes cmap_classes = psaux->t1_cmap_classes; 345 FT_CMap_Class clazz; 346 347 348 charmap.face = root; 349 350 /* first of all, try to synthesize a Unicode charmap */ 351 charmap.platform_id = TT_PLATFORM_MICROSOFT; 352 charmap.encoding_id = TT_MS_ID_UNICODE_CS; 353 charmap.encoding = FT_ENCODING_UNICODE; 354 355 error = FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL ); 356 if ( error && 357 FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) ) 358 goto Exit; 359 error = FT_Err_Ok; 360 361 /* now, generate an Adobe Standard encoding when appropriate */ 362 charmap.platform_id = TT_PLATFORM_ADOBE; 363 clazz = NULL; 364 365 switch ( type1->encoding_type ) 366 { 367 case T1_ENCODING_TYPE_STANDARD: 368 charmap.encoding = FT_ENCODING_ADOBE_STANDARD; 369 charmap.encoding_id = TT_ADOBE_ID_STANDARD; 370 clazz = cmap_classes->standard; 371 break; 372 373 case T1_ENCODING_TYPE_EXPERT: 374 charmap.encoding = FT_ENCODING_ADOBE_EXPERT; 375 charmap.encoding_id = TT_ADOBE_ID_EXPERT; 376 clazz = cmap_classes->expert; 377 break; 378 379 case T1_ENCODING_TYPE_ARRAY: 380 charmap.encoding = FT_ENCODING_ADOBE_CUSTOM; 381 charmap.encoding_id = TT_ADOBE_ID_CUSTOM; 382 clazz = cmap_classes->custom; 383 break; 384 385 case T1_ENCODING_TYPE_ISOLATIN1: 386 charmap.encoding = FT_ENCODING_ADOBE_LATIN_1; 387 charmap.encoding_id = TT_ADOBE_ID_LATIN_1; 388 clazz = cmap_classes->unicode; 389 break; 390 391 default: 392 ; 393 } 394 395 if ( clazz ) 396 error = FT_CMap_New( clazz, NULL, &charmap, NULL ); 397 } 398 } 399 Exit: 400 return error; 401 } 402 403 404 FT_LOCAL_DEF( void ) T42_Face_Done(FT_Face t42face)405 T42_Face_Done( FT_Face t42face ) 406 { 407 T42_Face face = (T42_Face)t42face; 408 T1_Font type1; 409 PS_FontInfo info; 410 FT_Memory memory; 411 412 413 if ( !face ) 414 return; 415 416 type1 = &face->type1; 417 info = &type1->font_info; 418 memory = face->root.memory; 419 420 /* delete internal ttf face prior to freeing face->ttf_data */ 421 if ( face->ttf_face ) 422 FT_Done_Face( face->ttf_face ); 423 424 /* release font info strings */ 425 FT_FREE( info->version ); 426 FT_FREE( info->notice ); 427 FT_FREE( info->full_name ); 428 FT_FREE( info->family_name ); 429 FT_FREE( info->weight ); 430 431 /* release top dictionary */ 432 FT_FREE( type1->charstrings_len ); 433 FT_FREE( type1->charstrings ); 434 FT_FREE( type1->glyph_names ); 435 436 FT_FREE( type1->charstrings_block ); 437 FT_FREE( type1->glyph_names_block ); 438 439 FT_FREE( type1->encoding.char_index ); 440 FT_FREE( type1->encoding.char_name ); 441 FT_FREE( type1->font_name ); 442 443 FT_FREE( face->ttf_data ); 444 445 #if 0 446 /* release afm data if present */ 447 if ( face->afm_data ) 448 T1_Done_AFM( memory, (T1_AFM*)face->afm_data ); 449 #endif 450 451 /* release unicode map, if any */ 452 FT_FREE( face->unicode_map.maps ); 453 face->unicode_map.num_maps = 0; 454 455 face->root.family_name = NULL; 456 face->root.style_name = NULL; 457 } 458 459 460 /*************************************************************************/ 461 /* */ 462 /* <Function> */ 463 /* T42_Driver_Init */ 464 /* */ 465 /* <Description> */ 466 /* Initializes a given Type 42 driver object. */ 467 /* */ 468 /* <Input> */ 469 /* driver :: A handle to the target driver object. */ 470 /* */ 471 /* <Return> */ 472 /* FreeType error code. 0 means success. */ 473 /* */ 474 FT_LOCAL_DEF( FT_Error ) T42_Driver_Init(FT_Module module)475 T42_Driver_Init( FT_Module module ) /* T42_Driver */ 476 { 477 T42_Driver driver = (T42_Driver)module; 478 FT_Module ttmodule; 479 480 481 ttmodule = FT_Get_Module( module->library, "truetype" ); 482 if ( !ttmodule ) 483 { 484 FT_ERROR(( "T42_Driver_Init: cannot access `truetype' module\n" )); 485 return FT_THROW( Missing_Module ); 486 } 487 488 driver->ttclazz = (FT_Driver_Class)ttmodule->clazz; 489 490 return FT_Err_Ok; 491 } 492 493 494 FT_LOCAL_DEF( void ) T42_Driver_Done(FT_Module module)495 T42_Driver_Done( FT_Module module ) 496 { 497 FT_UNUSED( module ); 498 } 499 500 501 FT_LOCAL_DEF( FT_Error ) T42_Size_Init(FT_Size size)502 T42_Size_Init( FT_Size size ) /* T42_Size */ 503 { 504 T42_Size t42size = (T42_Size)size; 505 FT_Face face = size->face; 506 T42_Face t42face = (T42_Face)face; 507 FT_Size ttsize; 508 FT_Error error; 509 510 511 error = FT_New_Size( t42face->ttf_face, &ttsize ); 512 t42size->ttsize = ttsize; 513 514 FT_Activate_Size( ttsize ); 515 516 return error; 517 } 518 519 520 FT_LOCAL_DEF( FT_Error ) T42_Size_Request(FT_Size t42size,FT_Size_Request req)521 T42_Size_Request( FT_Size t42size, /* T42_Size */ 522 FT_Size_Request req ) 523 { 524 T42_Size size = (T42_Size)t42size; 525 T42_Face face = (T42_Face)t42size->face; 526 FT_Error error; 527 528 529 FT_Activate_Size( size->ttsize ); 530 531 error = FT_Request_Size( face->ttf_face, req ); 532 if ( !error ) 533 t42size->metrics = face->ttf_face->size->metrics; 534 535 return error; 536 } 537 538 539 FT_LOCAL_DEF( FT_Error ) T42_Size_Select(FT_Size t42size,FT_ULong strike_index)540 T42_Size_Select( FT_Size t42size, /* T42_Size */ 541 FT_ULong strike_index ) 542 { 543 T42_Size size = (T42_Size)t42size; 544 T42_Face face = (T42_Face)t42size->face; 545 FT_Error error; 546 547 548 FT_Activate_Size( size->ttsize ); 549 550 error = FT_Select_Size( face->ttf_face, (FT_Int)strike_index ); 551 if ( !error ) 552 t42size->metrics = face->ttf_face->size->metrics; 553 554 return error; 555 556 } 557 558 559 FT_LOCAL_DEF( void ) T42_Size_Done(FT_Size t42size)560 T42_Size_Done( FT_Size t42size ) /* T42_Size */ 561 { 562 T42_Size size = (T42_Size)t42size; 563 FT_Face face = t42size->face; 564 T42_Face t42face = (T42_Face)face; 565 FT_ListNode node; 566 567 568 node = FT_List_Find( &t42face->ttf_face->sizes_list, size->ttsize ); 569 if ( node ) 570 { 571 FT_Done_Size( size->ttsize ); 572 size->ttsize = NULL; 573 } 574 } 575 576 577 FT_LOCAL_DEF( FT_Error ) T42_GlyphSlot_Init(FT_GlyphSlot t42slot)578 T42_GlyphSlot_Init( FT_GlyphSlot t42slot ) /* T42_GlyphSlot */ 579 { 580 T42_GlyphSlot slot = (T42_GlyphSlot)t42slot; 581 FT_Face face = t42slot->face; 582 T42_Face t42face = (T42_Face)face; 583 FT_GlyphSlot ttslot; 584 FT_Error error = FT_Err_Ok; 585 586 587 if ( !face->glyph ) 588 { 589 /* First glyph slot for this face */ 590 slot->ttslot = t42face->ttf_face->glyph; 591 } 592 else 593 { 594 error = FT_New_GlyphSlot( t42face->ttf_face, &ttslot ); 595 slot->ttslot = ttslot; 596 } 597 598 return error; 599 } 600 601 602 FT_LOCAL_DEF( void ) T42_GlyphSlot_Done(FT_GlyphSlot t42slot)603 T42_GlyphSlot_Done( FT_GlyphSlot t42slot ) /* T42_GlyphSlot */ 604 { 605 T42_GlyphSlot slot = (T42_GlyphSlot)t42slot; 606 607 608 FT_Done_GlyphSlot( slot->ttslot ); 609 } 610 611 612 static void t42_glyphslot_clear(FT_GlyphSlot slot)613 t42_glyphslot_clear( FT_GlyphSlot slot ) 614 { 615 /* free bitmap if needed */ 616 ft_glyphslot_free_bitmap( slot ); 617 618 /* clear all public fields in the glyph slot */ 619 FT_ZERO( &slot->metrics ); 620 FT_ZERO( &slot->outline ); 621 FT_ZERO( &slot->bitmap ); 622 623 slot->bitmap_left = 0; 624 slot->bitmap_top = 0; 625 slot->num_subglyphs = 0; 626 slot->subglyphs = NULL; 627 slot->control_data = NULL; 628 slot->control_len = 0; 629 slot->other = NULL; 630 slot->format = FT_GLYPH_FORMAT_NONE; 631 632 slot->linearHoriAdvance = 0; 633 slot->linearVertAdvance = 0; 634 } 635 636 637 FT_LOCAL_DEF( FT_Error ) T42_GlyphSlot_Load(FT_GlyphSlot glyph,FT_Size size,FT_UInt glyph_index,FT_Int32 load_flags)638 T42_GlyphSlot_Load( FT_GlyphSlot glyph, 639 FT_Size size, 640 FT_UInt glyph_index, 641 FT_Int32 load_flags ) 642 { 643 FT_Error error; 644 T42_GlyphSlot t42slot = (T42_GlyphSlot)glyph; 645 T42_Size t42size = (T42_Size)size; 646 T42_Face t42face = (T42_Face)size->face; 647 FT_Driver_Class ttclazz = ((T42_Driver)glyph->face->driver)->ttclazz; 648 649 650 FT_TRACE1(( "T42_GlyphSlot_Load: glyph index %d\n", glyph_index )); 651 652 /* map T42 glyph index to embedded TTF's glyph index */ 653 glyph_index = (FT_UInt)ft_strtol( 654 (const char *)t42face->type1.charstrings[glyph_index], 655 NULL, 10 ); 656 657 t42_glyphslot_clear( t42slot->ttslot ); 658 error = ttclazz->load_glyph( t42slot->ttslot, 659 t42size->ttsize, 660 glyph_index, 661 load_flags | FT_LOAD_NO_BITMAP ); 662 663 if ( !error ) 664 { 665 glyph->metrics = t42slot->ttslot->metrics; 666 667 glyph->linearHoriAdvance = t42slot->ttslot->linearHoriAdvance; 668 glyph->linearVertAdvance = t42slot->ttslot->linearVertAdvance; 669 670 glyph->format = t42slot->ttslot->format; 671 glyph->outline = t42slot->ttslot->outline; 672 673 glyph->bitmap = t42slot->ttslot->bitmap; 674 glyph->bitmap_left = t42slot->ttslot->bitmap_left; 675 glyph->bitmap_top = t42slot->ttslot->bitmap_top; 676 677 glyph->num_subglyphs = t42slot->ttslot->num_subglyphs; 678 glyph->subglyphs = t42slot->ttslot->subglyphs; 679 680 glyph->control_data = t42slot->ttslot->control_data; 681 glyph->control_len = t42slot->ttslot->control_len; 682 } 683 684 return error; 685 } 686 687 688 /* END */ 689