1 /**************************************************************************** 2 * 3 * t42objs.c 4 * 5 * Type 42 objects manager (body). 6 * 7 * Copyright (C) 2002-2020 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 <freetype/internal/ftdebug.h> 23 #include <freetype/ftlist.h> 24 #include <freetype/ttnameid.h> 25 26 27 #undef FT_COMPONENT 28 #define FT_COMPONENT 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 103 104 /* OK, we do the following: for each element in the encoding */ 105 /* table, look up the index of the glyph having the same name */ 106 /* as defined in the CharStrings array. */ 107 /* The index is then stored in type1.encoding.char_index, and */ 108 /* the name in type1.encoding.char_name */ 109 110 min_char = 0; 111 max_char = 0; 112 113 charcode = 0; 114 for ( ; charcode < loader.encoding_table.max_elems; charcode++ ) 115 { 116 const FT_String* char_name = 117 (const FT_String*)loader.encoding_table.elements[charcode]; 118 119 120 type1->encoding.char_index[charcode] = 0; 121 type1->encoding.char_name [charcode] = ".notdef"; 122 123 if ( char_name ) 124 for ( idx = 0; idx < type1->num_glyphs; idx++ ) 125 { 126 const FT_String* glyph_name = type1->glyph_names[idx]; 127 128 129 if ( ft_strcmp( char_name, glyph_name ) == 0 ) 130 { 131 type1->encoding.char_index[charcode] = (FT_UShort)idx; 132 type1->encoding.char_name [charcode] = glyph_name; 133 134 /* Change min/max encoded char only if glyph name is */ 135 /* not /.notdef */ 136 if ( ft_strcmp( ".notdef", glyph_name ) != 0 ) 137 { 138 if ( charcode < min_char ) 139 min_char = charcode; 140 if ( charcode >= max_char ) 141 max_char = charcode + 1; 142 } 143 break; 144 } 145 } 146 } 147 148 type1->encoding.code_first = min_char; 149 type1->encoding.code_last = max_char; 150 type1->encoding.num_chars = loader.num_chars; 151 } 152 153 Exit: 154 t42_loader_done( &loader ); 155 return error; 156 } 157 158 159 /***************** Driver Functions *************/ 160 161 162 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)163 T42_Face_Init( FT_Stream stream, 164 FT_Face t42face, /* T42_Face */ 165 FT_Int face_index, 166 FT_Int num_params, 167 FT_Parameter* params ) 168 { 169 T42_Face face = (T42_Face)t42face; 170 FT_Error error; 171 FT_Service_PsCMaps psnames; 172 PSAux_Service psaux; 173 FT_Face root = (FT_Face)&face->root; 174 T1_Font type1 = &face->type1; 175 PS_FontInfo info = &type1->font_info; 176 177 FT_UNUSED( num_params ); 178 FT_UNUSED( params ); 179 FT_UNUSED( stream ); 180 181 182 face->ttf_face = NULL; 183 face->root.num_faces = 1; 184 185 FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); 186 face->psnames = psnames; 187 188 face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), 189 "psaux" ); 190 psaux = (PSAux_Service)face->psaux; 191 if ( !psaux ) 192 { 193 FT_ERROR(( "T42_Face_Init: cannot access `psaux' module\n" )); 194 error = FT_THROW( Missing_Module ); 195 goto Exit; 196 } 197 198 FT_TRACE2(( "Type 42 driver\n" )); 199 200 /* open the tokenizer, this will also check the font format */ 201 error = T42_Open_Face( face ); 202 if ( error ) 203 goto Exit; 204 205 /* if we just wanted to check the format, leave successfully now */ 206 if ( face_index < 0 ) 207 goto Exit; 208 209 /* check the face index */ 210 if ( ( face_index & 0xFFFF ) > 0 ) 211 { 212 FT_ERROR(( "T42_Face_Init: invalid face index\n" )); 213 error = FT_THROW( Invalid_Argument ); 214 goto Exit; 215 } 216 217 /* Now load the font program into the face object */ 218 219 /* Init the face object fields */ 220 /* Now set up root face fields */ 221 222 root->num_glyphs = type1->num_glyphs; 223 root->num_charmaps = 0; 224 root->face_index = 0; 225 226 root->face_flags |= FT_FACE_FLAG_SCALABLE | 227 FT_FACE_FLAG_HORIZONTAL | 228 FT_FACE_FLAG_GLYPH_NAMES; 229 230 if ( info->is_fixed_pitch ) 231 root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; 232 233 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 234 root->face_flags |= FT_FACE_FLAG_HINTER; 235 #endif 236 237 /* XXX: TODO -- add kerning with .afm support */ 238 239 /* get style name -- be careful, some broken fonts only */ 240 /* have a `/FontName' dictionary entry! */ 241 root->family_name = info->family_name; 242 /* assume "Regular" style if we don't know better */ 243 root->style_name = (char *)"Regular"; 244 if ( root->family_name ) 245 { 246 char* full = info->full_name; 247 char* family = root->family_name; 248 249 250 if ( full ) 251 { 252 while ( *full ) 253 { 254 if ( *full == *family ) 255 { 256 family++; 257 full++; 258 } 259 else 260 { 261 if ( *full == ' ' || *full == '-' ) 262 full++; 263 else if ( *family == ' ' || *family == '-' ) 264 family++; 265 else 266 { 267 if ( !*family ) 268 root->style_name = full; 269 break; 270 } 271 } 272 } 273 } 274 } 275 else 276 { 277 /* do we have a `/FontName'? */ 278 if ( type1->font_name ) 279 root->family_name = type1->font_name; 280 } 281 282 /* no embedded bitmap support */ 283 root->num_fixed_sizes = 0; 284 root->available_sizes = NULL; 285 286 /* Load the TTF font embedded in the T42 font */ 287 { 288 FT_Open_Args args; 289 290 291 args.flags = FT_OPEN_MEMORY | FT_OPEN_DRIVER; 292 args.driver = FT_Get_Module( FT_FACE_LIBRARY( face ), 293 "truetype" ); 294 args.memory_base = face->ttf_data; 295 args.memory_size = face->ttf_size; 296 297 if ( num_params ) 298 { 299 args.flags |= FT_OPEN_PARAMS; 300 args.num_params = num_params; 301 args.params = params; 302 } 303 304 error = FT_Open_Face( FT_FACE_LIBRARY( face ), 305 &args, 0, &face->ttf_face ); 306 } 307 308 if ( error ) 309 goto Exit; 310 311 FT_Done_Size( face->ttf_face->size ); 312 313 /* Ignore info in FontInfo dictionary and use the info from the */ 314 /* loaded TTF font. The PostScript interpreter also ignores it. */ 315 root->bbox = face->ttf_face->bbox; 316 root->units_per_EM = face->ttf_face->units_per_EM; 317 318 root->ascender = face->ttf_face->ascender; 319 root->descender = face->ttf_face->descender; 320 root->height = face->ttf_face->height; 321 322 root->max_advance_width = face->ttf_face->max_advance_width; 323 root->max_advance_height = face->ttf_face->max_advance_height; 324 325 root->underline_position = (FT_Short)info->underline_position; 326 root->underline_thickness = (FT_Short)info->underline_thickness; 327 328 /* compute style flags */ 329 root->style_flags = 0; 330 if ( info->italic_angle ) 331 root->style_flags |= FT_STYLE_FLAG_ITALIC; 332 333 if ( face->ttf_face->style_flags & FT_STYLE_FLAG_BOLD ) 334 root->style_flags |= FT_STYLE_FLAG_BOLD; 335 336 if ( face->ttf_face->face_flags & FT_FACE_FLAG_VERTICAL ) 337 root->face_flags |= FT_FACE_FLAG_VERTICAL; 338 339 { 340 if ( psnames ) 341 { 342 FT_CharMapRec charmap; 343 T1_CMap_Classes cmap_classes = psaux->t1_cmap_classes; 344 FT_CMap_Class clazz; 345 346 347 charmap.face = root; 348 349 /* first of all, try to synthesize a Unicode charmap */ 350 charmap.platform_id = TT_PLATFORM_MICROSOFT; 351 charmap.encoding_id = TT_MS_ID_UNICODE_CS; 352 charmap.encoding = FT_ENCODING_UNICODE; 353 354 error = FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL ); 355 if ( error && 356 FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) && 357 FT_ERR_NEQ( error, Unimplemented_Feature ) ) 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 :: 470 * A handle to the target driver object. 471 * 472 * @Return: 473 * FreeType error code. 0 means success. 474 */ 475 FT_LOCAL_DEF( FT_Error ) T42_Driver_Init(FT_Module module)476 T42_Driver_Init( FT_Module module ) /* T42_Driver */ 477 { 478 T42_Driver driver = (T42_Driver)module; 479 FT_Module ttmodule; 480 481 482 ttmodule = FT_Get_Module( module->library, "truetype" ); 483 if ( !ttmodule ) 484 { 485 FT_ERROR(( "T42_Driver_Init: cannot access `truetype' module\n" )); 486 return FT_THROW( Missing_Module ); 487 } 488 489 driver->ttclazz = (FT_Driver_Class)ttmodule->clazz; 490 491 return FT_Err_Ok; 492 } 493 494 495 FT_LOCAL_DEF( void ) T42_Driver_Done(FT_Module module)496 T42_Driver_Done( FT_Module module ) 497 { 498 FT_UNUSED( module ); 499 } 500 501 502 FT_LOCAL_DEF( FT_Error ) T42_Size_Init(FT_Size size)503 T42_Size_Init( FT_Size size ) /* T42_Size */ 504 { 505 T42_Size t42size = (T42_Size)size; 506 FT_Face face = size->face; 507 T42_Face t42face = (T42_Face)face; 508 FT_Size ttsize; 509 FT_Error error; 510 511 512 error = FT_New_Size( t42face->ttf_face, &ttsize ); 513 t42size->ttsize = ttsize; 514 515 FT_Activate_Size( ttsize ); 516 517 return error; 518 } 519 520 521 FT_LOCAL_DEF( FT_Error ) T42_Size_Request(FT_Size t42size,FT_Size_Request req)522 T42_Size_Request( FT_Size t42size, /* T42_Size */ 523 FT_Size_Request req ) 524 { 525 T42_Size size = (T42_Size)t42size; 526 T42_Face face = (T42_Face)t42size->face; 527 FT_Error error; 528 529 530 FT_Activate_Size( size->ttsize ); 531 532 error = FT_Request_Size( face->ttf_face, req ); 533 if ( !error ) 534 t42size->metrics = face->ttf_face->size->metrics; 535 536 return error; 537 } 538 539 540 FT_LOCAL_DEF( FT_Error ) T42_Size_Select(FT_Size t42size,FT_ULong strike_index)541 T42_Size_Select( FT_Size t42size, /* T42_Size */ 542 FT_ULong strike_index ) 543 { 544 T42_Size size = (T42_Size)t42size; 545 T42_Face face = (T42_Face)t42size->face; 546 FT_Error error; 547 548 549 FT_Activate_Size( size->ttsize ); 550 551 error = FT_Select_Size( face->ttf_face, (FT_Int)strike_index ); 552 if ( !error ) 553 t42size->metrics = face->ttf_face->size->metrics; 554 555 return error; 556 557 } 558 559 560 FT_LOCAL_DEF( void ) T42_Size_Done(FT_Size t42size)561 T42_Size_Done( FT_Size t42size ) /* T42_Size */ 562 { 563 T42_Size size = (T42_Size)t42size; 564 FT_Face face = t42size->face; 565 T42_Face t42face = (T42_Face)face; 566 FT_ListNode node; 567 568 569 node = FT_List_Find( &t42face->ttf_face->sizes_list, size->ttsize ); 570 if ( node ) 571 { 572 FT_Done_Size( size->ttsize ); 573 size->ttsize = NULL; 574 } 575 } 576 577 578 FT_LOCAL_DEF( FT_Error ) T42_GlyphSlot_Init(FT_GlyphSlot t42slot)579 T42_GlyphSlot_Init( FT_GlyphSlot t42slot ) /* T42_GlyphSlot */ 580 { 581 T42_GlyphSlot slot = (T42_GlyphSlot)t42slot; 582 FT_Face face = t42slot->face; 583 T42_Face t42face = (T42_Face)face; 584 FT_GlyphSlot ttslot; 585 FT_Error error = FT_Err_Ok; 586 587 588 if ( !face->glyph ) 589 { 590 /* First glyph slot for this face */ 591 slot->ttslot = t42face->ttf_face->glyph; 592 } 593 else 594 { 595 error = FT_New_GlyphSlot( t42face->ttf_face, &ttslot ); 596 slot->ttslot = ttslot; 597 } 598 599 return error; 600 } 601 602 603 FT_LOCAL_DEF( void ) T42_GlyphSlot_Done(FT_GlyphSlot t42slot)604 T42_GlyphSlot_Done( FT_GlyphSlot t42slot ) /* T42_GlyphSlot */ 605 { 606 T42_GlyphSlot slot = (T42_GlyphSlot)t42slot; 607 608 609 FT_Done_GlyphSlot( slot->ttslot ); 610 } 611 612 613 static void t42_glyphslot_clear(FT_GlyphSlot slot)614 t42_glyphslot_clear( FT_GlyphSlot slot ) 615 { 616 /* free bitmap if needed */ 617 ft_glyphslot_free_bitmap( slot ); 618 619 /* clear all public fields in the glyph slot */ 620 FT_ZERO( &slot->metrics ); 621 FT_ZERO( &slot->outline ); 622 FT_ZERO( &slot->bitmap ); 623 624 slot->bitmap_left = 0; 625 slot->bitmap_top = 0; 626 slot->num_subglyphs = 0; 627 slot->subglyphs = NULL; 628 slot->control_data = NULL; 629 slot->control_len = 0; 630 slot->other = NULL; 631 slot->format = FT_GLYPH_FORMAT_NONE; 632 633 slot->linearHoriAdvance = 0; 634 slot->linearVertAdvance = 0; 635 } 636 637 638 FT_LOCAL_DEF( FT_Error ) T42_GlyphSlot_Load(FT_GlyphSlot glyph,FT_Size size,FT_UInt glyph_index,FT_Int32 load_flags)639 T42_GlyphSlot_Load( FT_GlyphSlot glyph, 640 FT_Size size, 641 FT_UInt glyph_index, 642 FT_Int32 load_flags ) 643 { 644 FT_Error error; 645 T42_GlyphSlot t42slot = (T42_GlyphSlot)glyph; 646 T42_Size t42size = (T42_Size)size; 647 T42_Face t42face = (T42_Face)size->face; 648 FT_Driver_Class ttclazz = ((T42_Driver)glyph->face->driver)->ttclazz; 649 650 651 FT_TRACE1(( "T42_GlyphSlot_Load: glyph index %d\n", glyph_index )); 652 653 /* map T42 glyph index to embedded TTF's glyph index */ 654 glyph_index = (FT_UInt)ft_strtol( 655 (const char *)t42face->type1.charstrings[glyph_index], 656 NULL, 10 ); 657 658 t42_glyphslot_clear( t42slot->ttslot ); 659 error = ttclazz->load_glyph( t42slot->ttslot, 660 t42size->ttsize, 661 glyph_index, 662 load_flags | FT_LOAD_NO_BITMAP ); 663 664 if ( !error ) 665 { 666 glyph->metrics = t42slot->ttslot->metrics; 667 668 glyph->linearHoriAdvance = t42slot->ttslot->linearHoriAdvance; 669 glyph->linearVertAdvance = t42slot->ttslot->linearVertAdvance; 670 671 glyph->format = t42slot->ttslot->format; 672 glyph->outline = t42slot->ttslot->outline; 673 674 glyph->bitmap = t42slot->ttslot->bitmap; 675 glyph->bitmap_left = t42slot->ttslot->bitmap_left; 676 glyph->bitmap_top = t42slot->ttslot->bitmap_top; 677 678 glyph->num_subglyphs = t42slot->ttslot->num_subglyphs; 679 glyph->subglyphs = t42slot->ttslot->subglyphs; 680 681 glyph->control_data = t42slot->ttslot->control_data; 682 glyph->control_len = t42slot->ttslot->control_len; 683 } 684 685 return error; 686 } 687 688 689 /* END */ 690