1 /***************************************************************************/ 2 /* */ 3 /* t42objs.c */ 4 /* */ 5 /* Type 42 objects manager (body). */ 6 /* */ 7 /* Copyright 2002-2009, 2011, 2013 */ 8 /* by 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 error = t42_parser_init( parser, 51 face->root.stream, 52 memory, 53 psaux); 54 if ( error ) 55 goto Exit; 56 57 error = t42_parse_dict( face, &loader, 58 parser->base_dict, parser->base_len ); 59 if ( error ) 60 goto Exit; 61 62 if ( type1->font_type != 42 ) 63 { 64 FT_ERROR(( "T42_Open_Face: cannot handle FontType %d\n", 65 type1->font_type )); 66 error = FT_THROW( Unknown_File_Format ); 67 goto Exit; 68 } 69 70 /* now, propagate the charstrings and glyphnames tables */ 71 /* to the Type1 data */ 72 type1->num_glyphs = loader.num_glyphs; 73 74 if ( !loader.charstrings.init ) 75 { 76 FT_ERROR(( "T42_Open_Face: no charstrings array in face\n" )); 77 error = FT_THROW( Invalid_File_Format ); 78 } 79 80 loader.charstrings.init = 0; 81 type1->charstrings_block = loader.charstrings.block; 82 type1->charstrings = loader.charstrings.elements; 83 type1->charstrings_len = loader.charstrings.lengths; 84 85 /* we copy the glyph names `block' and `elements' fields; */ 86 /* the `lengths' field must be released later */ 87 type1->glyph_names_block = loader.glyph_names.block; 88 type1->glyph_names = (FT_String**)loader.glyph_names.elements; 89 loader.glyph_names.block = 0; 90 loader.glyph_names.elements = 0; 91 92 /* we must now build type1.encoding when we have a custom array */ 93 if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY ) 94 { 95 FT_Int charcode, idx, min_char, max_char; 96 FT_Byte* glyph_name; 97 98 99 /* OK, we do the following: for each element in the encoding */ 100 /* table, look up the index of the glyph having the same name */ 101 /* as defined in the CharStrings array. */ 102 /* The index is then stored in type1.encoding.char_index, and */ 103 /* the name in type1.encoding.char_name */ 104 105 min_char = 0; 106 max_char = 0; 107 108 charcode = 0; 109 for ( ; charcode < loader.encoding_table.max_elems; charcode++ ) 110 { 111 FT_Byte* char_name; 112 113 114 type1->encoding.char_index[charcode] = 0; 115 type1->encoding.char_name [charcode] = (char *)".notdef"; 116 117 char_name = loader.encoding_table.elements[charcode]; 118 if ( char_name ) 119 for ( idx = 0; idx < type1->num_glyphs; idx++ ) 120 { 121 glyph_name = (FT_Byte*)type1->glyph_names[idx]; 122 if ( ft_strcmp( (const char*)char_name, 123 (const char*)glyph_name ) == 0 ) 124 { 125 type1->encoding.char_index[charcode] = (FT_UShort)idx; 126 type1->encoding.char_name [charcode] = (char*)glyph_name; 127 128 /* Change min/max encoded char only if glyph name is */ 129 /* not /.notdef */ 130 if ( ft_strcmp( (const char*)".notdef", 131 (const char*)glyph_name ) != 0 ) 132 { 133 if ( charcode < min_char ) 134 min_char = charcode; 135 if ( charcode >= max_char ) 136 max_char = charcode + 1; 137 } 138 break; 139 } 140 } 141 } 142 143 type1->encoding.code_first = min_char; 144 type1->encoding.code_last = max_char; 145 type1->encoding.num_chars = loader.num_chars; 146 } 147 148 Exit: 149 t42_loader_done( &loader ); 150 return error; 151 } 152 153 154 /***************** Driver Functions *************/ 155 156 157 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)158 T42_Face_Init( FT_Stream stream, 159 FT_Face t42face, /* T42_Face */ 160 FT_Int face_index, 161 FT_Int num_params, 162 FT_Parameter* params ) 163 { 164 T42_Face face = (T42_Face)t42face; 165 FT_Error error; 166 FT_Service_PsCMaps psnames; 167 PSAux_Service psaux; 168 FT_Face root = (FT_Face)&face->root; 169 T1_Font type1 = &face->type1; 170 PS_FontInfo info = &type1->font_info; 171 172 FT_UNUSED( num_params ); 173 FT_UNUSED( params ); 174 FT_UNUSED( stream ); 175 176 177 face->ttf_face = NULL; 178 face->root.num_faces = 1; 179 180 FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); 181 face->psnames = psnames; 182 183 face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), 184 "psaux" ); 185 psaux = (PSAux_Service)face->psaux; 186 if ( !psaux ) 187 { 188 FT_ERROR(( "T42_Face_Init: cannot access `psaux' module\n" )); 189 error = FT_THROW( Missing_Module ); 190 goto Exit; 191 } 192 193 FT_TRACE2(( "Type 42 driver\n" )); 194 195 /* open the tokenizer, this will also check the font format */ 196 error = T42_Open_Face( face ); 197 if ( error ) 198 goto Exit; 199 200 /* if we just wanted to check the format, leave successfully now */ 201 if ( face_index < 0 ) 202 goto Exit; 203 204 /* check the face index */ 205 if ( face_index > 0 ) 206 { 207 FT_ERROR(( "T42_Face_Init: invalid face index\n" )); 208 error = FT_THROW( Invalid_Argument ); 209 goto Exit; 210 } 211 212 /* Now load the font program into the face object */ 213 214 /* Init the face object fields */ 215 /* Now set up root face fields */ 216 217 root->num_glyphs = type1->num_glyphs; 218 root->num_charmaps = 0; 219 root->face_index = 0; 220 221 root->face_flags |= FT_FACE_FLAG_SCALABLE | 222 FT_FACE_FLAG_HORIZONTAL | 223 FT_FACE_FLAG_GLYPH_NAMES; 224 225 if ( info->is_fixed_pitch ) 226 root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; 227 228 /* We only set this flag if we have the patented bytecode interpreter. */ 229 /* There are no known `tricky' Type42 fonts that could be loaded with */ 230 /* the unpatented interpreter. */ 231 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 232 root->face_flags |= FT_FACE_FLAG_HINTER; 233 #endif 234 235 /* XXX: TODO -- add kerning with .afm support */ 236 237 /* get style name -- be careful, some broken fonts only */ 238 /* have a `/FontName' dictionary entry! */ 239 root->family_name = info->family_name; 240 /* assume "Regular" style if we don't know better */ 241 root->style_name = (char *)"Regular"; 242 if ( root->family_name ) 243 { 244 char* full = info->full_name; 245 char* family = root->family_name; 246 247 248 if ( full ) 249 { 250 while ( *full ) 251 { 252 if ( *full == *family ) 253 { 254 family++; 255 full++; 256 } 257 else 258 { 259 if ( *full == ' ' || *full == '-' ) 260 full++; 261 else if ( *family == ' ' || *family == '-' ) 262 family++; 263 else 264 { 265 if ( !*family ) 266 root->style_name = full; 267 break; 268 } 269 } 270 } 271 } 272 } 273 else 274 { 275 /* do we have a `/FontName'? */ 276 if ( type1->font_name ) 277 root->family_name = type1->font_name; 278 } 279 280 /* no embedded bitmap support */ 281 root->num_fixed_sizes = 0; 282 root->available_sizes = 0; 283 284 /* Load the TTF font embedded in the T42 font */ 285 { 286 FT_Open_Args args; 287 288 289 args.flags = FT_OPEN_MEMORY; 290 args.memory_base = face->ttf_data; 291 args.memory_size = face->ttf_size; 292 293 if ( num_params ) 294 { 295 args.flags |= FT_OPEN_PARAMS; 296 args.num_params = num_params; 297 args.params = params; 298 } 299 300 error = FT_Open_Face( FT_FACE_LIBRARY( face ), 301 &args, 0, &face->ttf_face ); 302 } 303 304 if ( error ) 305 goto Exit; 306 307 FT_Done_Size( face->ttf_face->size ); 308 309 /* Ignore info in FontInfo dictionary and use the info from the */ 310 /* loaded TTF font. The PostScript interpreter also ignores it. */ 311 root->bbox = face->ttf_face->bbox; 312 root->units_per_EM = face->ttf_face->units_per_EM; 313 314 root->ascender = face->ttf_face->ascender; 315 root->descender = face->ttf_face->descender; 316 root->height = face->ttf_face->height; 317 318 root->max_advance_width = face->ttf_face->max_advance_width; 319 root->max_advance_height = face->ttf_face->max_advance_height; 320 321 root->underline_position = (FT_Short)info->underline_position; 322 root->underline_thickness = (FT_Short)info->underline_thickness; 323 324 /* compute style flags */ 325 root->style_flags = 0; 326 if ( info->italic_angle ) 327 root->style_flags |= FT_STYLE_FLAG_ITALIC; 328 329 if ( face->ttf_face->style_flags & FT_STYLE_FLAG_BOLD ) 330 root->style_flags |= FT_STYLE_FLAG_BOLD; 331 332 if ( face->ttf_face->face_flags & FT_FACE_FLAG_VERTICAL ) 333 root->face_flags |= FT_FACE_FLAG_VERTICAL; 334 335 { 336 if ( psnames ) 337 { 338 FT_CharMapRec charmap; 339 T1_CMap_Classes cmap_classes = psaux->t1_cmap_classes; 340 FT_CMap_Class clazz; 341 342 343 charmap.face = root; 344 345 /* first of all, try to synthesize a Unicode charmap */ 346 charmap.platform_id = TT_PLATFORM_MICROSOFT; 347 charmap.encoding_id = TT_MS_ID_UNICODE_CS; 348 charmap.encoding = FT_ENCODING_UNICODE; 349 350 error = FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL ); 351 if ( error && 352 FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) ) 353 goto Exit; 354 error = FT_Err_Ok; 355 356 /* now, generate an Adobe Standard encoding when appropriate */ 357 charmap.platform_id = TT_PLATFORM_ADOBE; 358 clazz = NULL; 359 360 switch ( type1->encoding_type ) 361 { 362 case T1_ENCODING_TYPE_STANDARD: 363 charmap.encoding = FT_ENCODING_ADOBE_STANDARD; 364 charmap.encoding_id = TT_ADOBE_ID_STANDARD; 365 clazz = cmap_classes->standard; 366 break; 367 368 case T1_ENCODING_TYPE_EXPERT: 369 charmap.encoding = FT_ENCODING_ADOBE_EXPERT; 370 charmap.encoding_id = TT_ADOBE_ID_EXPERT; 371 clazz = cmap_classes->expert; 372 break; 373 374 case T1_ENCODING_TYPE_ARRAY: 375 charmap.encoding = FT_ENCODING_ADOBE_CUSTOM; 376 charmap.encoding_id = TT_ADOBE_ID_CUSTOM; 377 clazz = cmap_classes->custom; 378 break; 379 380 case T1_ENCODING_TYPE_ISOLATIN1: 381 charmap.encoding = FT_ENCODING_ADOBE_LATIN_1; 382 charmap.encoding_id = TT_ADOBE_ID_LATIN_1; 383 clazz = cmap_classes->unicode; 384 break; 385 386 default: 387 ; 388 } 389 390 if ( clazz ) 391 error = FT_CMap_New( clazz, NULL, &charmap, NULL ); 392 393 #if 0 394 /* Select default charmap */ 395 if ( root->num_charmaps ) 396 root->charmap = root->charmaps[0]; 397 #endif 398 } 399 } 400 Exit: 401 return error; 402 } 403 404 405 FT_LOCAL_DEF( void ) T42_Face_Done(FT_Face t42face)406 T42_Face_Done( FT_Face t42face ) 407 { 408 T42_Face face = (T42_Face)t42face; 409 T1_Font type1; 410 PS_FontInfo info; 411 FT_Memory memory; 412 413 414 if ( !face ) 415 return; 416 417 type1 = &face->type1; 418 info = &type1->font_info; 419 memory = face->root.memory; 420 421 /* delete internal ttf face prior to freeing face->ttf_data */ 422 if ( face->ttf_face ) 423 FT_Done_Face( face->ttf_face ); 424 425 /* release font info strings */ 426 FT_FREE( info->version ); 427 FT_FREE( info->notice ); 428 FT_FREE( info->full_name ); 429 FT_FREE( info->family_name ); 430 FT_FREE( info->weight ); 431 432 /* release top dictionary */ 433 FT_FREE( type1->charstrings_len ); 434 FT_FREE( type1->charstrings ); 435 FT_FREE( type1->glyph_names ); 436 437 FT_FREE( type1->charstrings_block ); 438 FT_FREE( type1->glyph_names_block ); 439 440 FT_FREE( type1->encoding.char_index ); 441 FT_FREE( type1->encoding.char_name ); 442 FT_FREE( type1->font_name ); 443 444 FT_FREE( face->ttf_data ); 445 446 #if 0 447 /* release afm data if present */ 448 if ( face->afm_data ) 449 T1_Done_AFM( memory, (T1_AFM*)face->afm_data ); 450 #endif 451 452 /* release unicode map, if any */ 453 FT_FREE( face->unicode_map.maps ); 454 face->unicode_map.num_maps = 0; 455 456 face->root.family_name = 0; 457 face->root.style_name = 0; 458 } 459 460 461 /*************************************************************************/ 462 /* */ 463 /* <Function> */ 464 /* T42_Driver_Init */ 465 /* */ 466 /* <Description> */ 467 /* Initializes a given Type 42 driver object. */ 468 /* */ 469 /* <Input> */ 470 /* driver :: 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 == NULL ) 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 = 0; 628 slot->control_data = 0; 629 slot->control_len = 0; 630 slot->other = 0; 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 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 t42_glyphslot_clear( t42slot->ttslot ); 653 error = ttclazz->load_glyph( t42slot->ttslot, 654 t42size->ttsize, 655 glyph_index, 656 load_flags | FT_LOAD_NO_BITMAP ); 657 658 if ( !error ) 659 { 660 glyph->metrics = t42slot->ttslot->metrics; 661 662 glyph->linearHoriAdvance = t42slot->ttslot->linearHoriAdvance; 663 glyph->linearVertAdvance = t42slot->ttslot->linearVertAdvance; 664 665 glyph->format = t42slot->ttslot->format; 666 glyph->outline = t42slot->ttslot->outline; 667 668 glyph->bitmap = t42slot->ttslot->bitmap; 669 glyph->bitmap_left = t42slot->ttslot->bitmap_left; 670 glyph->bitmap_top = t42slot->ttslot->bitmap_top; 671 672 glyph->num_subglyphs = t42slot->ttslot->num_subglyphs; 673 glyph->subglyphs = t42slot->ttslot->subglyphs; 674 675 glyph->control_data = t42slot->ttslot->control_data; 676 glyph->control_len = t42slot->ttslot->control_len; 677 } 678 679 return error; 680 } 681 682 683 /* END */ 684