1 /***************************************************************************/ 2 /* */ 3 /* pfrload.c */ 4 /* */ 5 /* FreeType PFR loader (body). */ 6 /* */ 7 /* Copyright 2002-2015 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 "pfrload.h" 20 #include FT_INTERNAL_DEBUG_H 21 #include FT_INTERNAL_STREAM_H 22 23 #include "pfrerror.h" 24 25 #undef FT_COMPONENT 26 #define FT_COMPONENT trace_pfr 27 28 29 /*************************************************************************/ 30 /*************************************************************************/ 31 /***** *****/ 32 /***** EXTRA ITEMS *****/ 33 /***** *****/ 34 /*************************************************************************/ 35 /*************************************************************************/ 36 37 38 FT_LOCAL_DEF( FT_Error ) pfr_extra_items_skip(FT_Byte ** pp,FT_Byte * limit)39 pfr_extra_items_skip( FT_Byte* *pp, 40 FT_Byte* limit ) 41 { 42 return pfr_extra_items_parse( pp, limit, NULL, NULL ); 43 } 44 45 46 FT_LOCAL_DEF( FT_Error ) pfr_extra_items_parse(FT_Byte ** pp,FT_Byte * limit,PFR_ExtraItem item_list,FT_Pointer item_data)47 pfr_extra_items_parse( FT_Byte* *pp, 48 FT_Byte* limit, 49 PFR_ExtraItem item_list, 50 FT_Pointer item_data ) 51 { 52 FT_Error error = FT_Err_Ok; 53 FT_Byte* p = *pp; 54 FT_UInt num_items, item_type, item_size; 55 56 57 PFR_CHECK( 1 ); 58 num_items = PFR_NEXT_BYTE( p ); 59 60 for ( ; num_items > 0; num_items-- ) 61 { 62 PFR_CHECK( 2 ); 63 item_size = PFR_NEXT_BYTE( p ); 64 item_type = PFR_NEXT_BYTE( p ); 65 66 PFR_CHECK( item_size ); 67 68 if ( item_list ) 69 { 70 PFR_ExtraItem extra = item_list; 71 72 73 for ( extra = item_list; extra->parser != NULL; extra++ ) 74 { 75 if ( extra->type == item_type ) 76 { 77 error = extra->parser( p, p + item_size, item_data ); 78 if ( error ) goto Exit; 79 80 break; 81 } 82 } 83 } 84 85 p += item_size; 86 } 87 88 Exit: 89 *pp = p; 90 return error; 91 92 Too_Short: 93 FT_ERROR(( "pfr_extra_items_parse: invalid extra items table\n" )); 94 error = FT_THROW( Invalid_Table ); 95 goto Exit; 96 } 97 98 99 /*************************************************************************/ 100 /*************************************************************************/ 101 /***** *****/ 102 /***** PFR HEADER *****/ 103 /***** *****/ 104 /*************************************************************************/ 105 /*************************************************************************/ 106 107 static const FT_Frame_Field pfr_header_fields[] = 108 { 109 #undef FT_STRUCTURE 110 #define FT_STRUCTURE PFR_HeaderRec 111 112 FT_FRAME_START( 58 ), 113 FT_FRAME_ULONG ( signature ), 114 FT_FRAME_USHORT( version ), 115 FT_FRAME_USHORT( signature2 ), 116 FT_FRAME_USHORT( header_size ), 117 118 FT_FRAME_USHORT( log_dir_size ), 119 FT_FRAME_USHORT( log_dir_offset ), 120 121 FT_FRAME_USHORT( log_font_max_size ), 122 FT_FRAME_UOFF3 ( log_font_section_size ), 123 FT_FRAME_UOFF3 ( log_font_section_offset ), 124 125 FT_FRAME_USHORT( phy_font_max_size ), 126 FT_FRAME_UOFF3 ( phy_font_section_size ), 127 FT_FRAME_UOFF3 ( phy_font_section_offset ), 128 129 FT_FRAME_USHORT( gps_max_size ), 130 FT_FRAME_UOFF3 ( gps_section_size ), 131 FT_FRAME_UOFF3 ( gps_section_offset ), 132 133 FT_FRAME_BYTE ( max_blue_values ), 134 FT_FRAME_BYTE ( max_x_orus ), 135 FT_FRAME_BYTE ( max_y_orus ), 136 137 FT_FRAME_BYTE ( phy_font_max_size_high ), 138 FT_FRAME_BYTE ( color_flags ), 139 140 FT_FRAME_UOFF3 ( bct_max_size ), 141 FT_FRAME_UOFF3 ( bct_set_max_size ), 142 FT_FRAME_UOFF3 ( phy_bct_set_max_size ), 143 144 FT_FRAME_USHORT( num_phy_fonts ), 145 FT_FRAME_BYTE ( max_vert_stem_snap ), 146 FT_FRAME_BYTE ( max_horz_stem_snap ), 147 FT_FRAME_USHORT( max_chars ), 148 FT_FRAME_END 149 }; 150 151 152 FT_LOCAL_DEF( FT_Error ) pfr_header_load(PFR_Header header,FT_Stream stream)153 pfr_header_load( PFR_Header header, 154 FT_Stream stream ) 155 { 156 FT_Error error; 157 158 159 /* read header directly */ 160 if ( !FT_STREAM_SEEK( 0 ) && 161 !FT_STREAM_READ_FIELDS( pfr_header_fields, header ) ) 162 { 163 /* make a few adjustments to the header */ 164 header->phy_font_max_size += 165 (FT_UInt32)header->phy_font_max_size_high << 16; 166 } 167 168 return error; 169 } 170 171 172 FT_LOCAL_DEF( FT_Bool ) pfr_header_check(PFR_Header header)173 pfr_header_check( PFR_Header header ) 174 { 175 FT_Bool result = 1; 176 177 178 /* check signature and header size */ 179 if ( header->signature != 0x50465230L || /* "PFR0" */ 180 header->version > 4 || 181 header->header_size < 58 || 182 header->signature2 != 0x0D0A ) /* CR/LF */ 183 { 184 result = 0; 185 } 186 return result; 187 } 188 189 190 /***********************************************************************/ 191 /***********************************************************************/ 192 /***** *****/ 193 /***** PFR LOGICAL FONTS *****/ 194 /***** *****/ 195 /***********************************************************************/ 196 /***********************************************************************/ 197 198 199 FT_LOCAL_DEF( FT_Error ) pfr_log_font_count(FT_Stream stream,FT_UInt32 section_offset,FT_Long * acount)200 pfr_log_font_count( FT_Stream stream, 201 FT_UInt32 section_offset, 202 FT_Long *acount ) 203 { 204 FT_Error error; 205 FT_UInt count; 206 FT_UInt result = 0; 207 208 209 if ( FT_STREAM_SEEK( section_offset ) || FT_READ_USHORT( count ) ) 210 goto Exit; 211 212 result = count; 213 214 Exit: 215 *acount = (FT_Long)result; 216 return error; 217 } 218 219 220 FT_LOCAL_DEF( FT_Error ) pfr_log_font_load(PFR_LogFont log_font,FT_Stream stream,FT_UInt idx,FT_UInt32 section_offset,FT_Bool size_increment)221 pfr_log_font_load( PFR_LogFont log_font, 222 FT_Stream stream, 223 FT_UInt idx, 224 FT_UInt32 section_offset, 225 FT_Bool size_increment ) 226 { 227 FT_UInt num_log_fonts; 228 FT_UInt flags; 229 FT_UInt32 offset; 230 FT_UInt32 size; 231 FT_Error error; 232 233 234 if ( FT_STREAM_SEEK( section_offset ) || 235 FT_READ_USHORT( num_log_fonts ) ) 236 goto Exit; 237 238 if ( idx >= num_log_fonts ) 239 return FT_THROW( Invalid_Argument ); 240 241 if ( FT_STREAM_SKIP( idx * 5 ) || 242 FT_READ_USHORT( size ) || 243 FT_READ_UOFF3 ( offset ) ) 244 goto Exit; 245 246 /* save logical font size and offset */ 247 log_font->size = size; 248 log_font->offset = offset; 249 250 /* now, check the rest of the table before loading it */ 251 { 252 FT_Byte* p; 253 FT_Byte* limit; 254 FT_UInt local; 255 256 257 if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) ) 258 goto Exit; 259 260 p = stream->cursor; 261 limit = p + size; 262 263 PFR_CHECK(13); 264 265 log_font->matrix[0] = PFR_NEXT_LONG( p ); 266 log_font->matrix[1] = PFR_NEXT_LONG( p ); 267 log_font->matrix[2] = PFR_NEXT_LONG( p ); 268 log_font->matrix[3] = PFR_NEXT_LONG( p ); 269 270 flags = PFR_NEXT_BYTE( p ); 271 272 local = 0; 273 if ( flags & PFR_LOG_STROKE ) 274 { 275 local++; 276 if ( flags & PFR_LOG_2BYTE_STROKE ) 277 local++; 278 279 if ( (flags & PFR_LINE_JOIN_MASK) == PFR_LINE_JOIN_MITER ) 280 local += 3; 281 } 282 if ( flags & PFR_LOG_BOLD ) 283 { 284 local++; 285 if ( flags & PFR_LOG_2BYTE_BOLD ) 286 local++; 287 } 288 289 PFR_CHECK( local ); 290 291 if ( flags & PFR_LOG_STROKE ) 292 { 293 log_font->stroke_thickness = ( flags & PFR_LOG_2BYTE_STROKE ) 294 ? PFR_NEXT_SHORT( p ) 295 : PFR_NEXT_BYTE( p ); 296 297 if ( ( flags & PFR_LINE_JOIN_MASK ) == PFR_LINE_JOIN_MITER ) 298 log_font->miter_limit = PFR_NEXT_LONG( p ); 299 } 300 301 if ( flags & PFR_LOG_BOLD ) 302 { 303 log_font->bold_thickness = ( flags & PFR_LOG_2BYTE_BOLD ) 304 ? PFR_NEXT_SHORT( p ) 305 : PFR_NEXT_BYTE( p ); 306 } 307 308 if ( flags & PFR_LOG_EXTRA_ITEMS ) 309 { 310 error = pfr_extra_items_skip( &p, limit ); 311 if (error) goto Fail; 312 } 313 314 PFR_CHECK(5); 315 log_font->phys_size = PFR_NEXT_USHORT( p ); 316 log_font->phys_offset = PFR_NEXT_ULONG( p ); 317 if ( size_increment ) 318 { 319 PFR_CHECK( 1 ); 320 log_font->phys_size += (FT_UInt32)PFR_NEXT_BYTE( p ) << 16; 321 } 322 } 323 324 Fail: 325 FT_FRAME_EXIT(); 326 327 Exit: 328 return error; 329 330 Too_Short: 331 FT_ERROR(( "pfr_log_font_load: invalid logical font table\n" )); 332 error = FT_THROW( Invalid_Table ); 333 goto Fail; 334 } 335 336 337 /***********************************************************************/ 338 /***********************************************************************/ 339 /***** *****/ 340 /***** PFR PHYSICAL FONTS *****/ 341 /***** *****/ 342 /***********************************************************************/ 343 /***********************************************************************/ 344 345 346 /* load bitmap strikes lists */ 347 FT_CALLBACK_DEF( FT_Error ) pfr_extra_item_load_bitmap_info(FT_Byte * p,FT_Byte * limit,PFR_PhyFont phy_font)348 pfr_extra_item_load_bitmap_info( FT_Byte* p, 349 FT_Byte* limit, 350 PFR_PhyFont phy_font ) 351 { 352 FT_Memory memory = phy_font->memory; 353 PFR_Strike strike; 354 FT_UInt flags0; 355 FT_UInt n, count, size1; 356 FT_Error error = FT_Err_Ok; 357 358 359 PFR_CHECK( 5 ); 360 361 p += 3; /* skip bctSize */ 362 flags0 = PFR_NEXT_BYTE( p ); 363 count = PFR_NEXT_BYTE( p ); 364 365 /* re-allocate when needed */ 366 if ( phy_font->num_strikes + count > phy_font->max_strikes ) 367 { 368 FT_UInt new_max = FT_PAD_CEIL( phy_font->num_strikes + count, 4 ); 369 370 371 if ( FT_RENEW_ARRAY( phy_font->strikes, 372 phy_font->num_strikes, 373 new_max ) ) 374 goto Exit; 375 376 phy_font->max_strikes = new_max; 377 } 378 379 size1 = 1 + 1 + 1 + 2 + 2 + 1; 380 if ( flags0 & PFR_STRIKE_2BYTE_XPPM ) 381 size1++; 382 383 if ( flags0 & PFR_STRIKE_2BYTE_YPPM ) 384 size1++; 385 386 if ( flags0 & PFR_STRIKE_3BYTE_SIZE ) 387 size1++; 388 389 if ( flags0 & PFR_STRIKE_3BYTE_OFFSET ) 390 size1++; 391 392 if ( flags0 & PFR_STRIKE_2BYTE_COUNT ) 393 size1++; 394 395 strike = phy_font->strikes + phy_font->num_strikes; 396 397 PFR_CHECK( count * size1 ); 398 399 for ( n = 0; n < count; n++, strike++ ) 400 { 401 strike->x_ppm = ( flags0 & PFR_STRIKE_2BYTE_XPPM ) 402 ? PFR_NEXT_USHORT( p ) 403 : PFR_NEXT_BYTE( p ); 404 405 strike->y_ppm = ( flags0 & PFR_STRIKE_2BYTE_YPPM ) 406 ? PFR_NEXT_USHORT( p ) 407 : PFR_NEXT_BYTE( p ); 408 409 strike->flags = PFR_NEXT_BYTE( p ); 410 411 strike->bct_size = ( flags0 & PFR_STRIKE_3BYTE_SIZE ) 412 ? PFR_NEXT_ULONG( p ) 413 : PFR_NEXT_USHORT( p ); 414 415 strike->bct_offset = ( flags0 & PFR_STRIKE_3BYTE_OFFSET ) 416 ? PFR_NEXT_ULONG( p ) 417 : PFR_NEXT_USHORT( p ); 418 419 strike->num_bitmaps = ( flags0 & PFR_STRIKE_2BYTE_COUNT ) 420 ? PFR_NEXT_USHORT( p ) 421 : PFR_NEXT_BYTE( p ); 422 } 423 424 phy_font->num_strikes += count; 425 426 Exit: 427 return error; 428 429 Too_Short: 430 error = FT_THROW( Invalid_Table ); 431 FT_ERROR(( "pfr_extra_item_load_bitmap_info:" 432 " invalid bitmap info table\n" )); 433 goto Exit; 434 } 435 436 437 /* Load font ID. This is a so-called "unique" name that is rather 438 * long and descriptive (like "Tiresias ScreenFont v7.51"). 439 * 440 * Note that a PFR font's family name is contained in an *undocumented* 441 * string of the "auxiliary data" portion of a physical font record. This 442 * may also contain the "real" style name! 443 * 444 * If no family name is present, the font ID is used instead for the 445 * family. 446 */ 447 FT_CALLBACK_DEF( FT_Error ) pfr_extra_item_load_font_id(FT_Byte * p,FT_Byte * limit,PFR_PhyFont phy_font)448 pfr_extra_item_load_font_id( FT_Byte* p, 449 FT_Byte* limit, 450 PFR_PhyFont phy_font ) 451 { 452 FT_Error error = FT_Err_Ok; 453 FT_Memory memory = phy_font->memory; 454 FT_UInt len = (FT_UInt)( limit - p ); 455 456 457 if ( phy_font->font_id != NULL ) 458 goto Exit; 459 460 if ( FT_ALLOC( phy_font->font_id, len + 1 ) ) 461 goto Exit; 462 463 /* copy font ID name, and terminate it for safety */ 464 FT_MEM_COPY( phy_font->font_id, p, len ); 465 phy_font->font_id[len] = 0; 466 467 Exit: 468 return error; 469 } 470 471 472 /* load stem snap tables */ 473 FT_CALLBACK_DEF( FT_Error ) pfr_extra_item_load_stem_snaps(FT_Byte * p,FT_Byte * limit,PFR_PhyFont phy_font)474 pfr_extra_item_load_stem_snaps( FT_Byte* p, 475 FT_Byte* limit, 476 PFR_PhyFont phy_font ) 477 { 478 FT_UInt count, num_vert, num_horz; 479 FT_Int* snaps = NULL; 480 FT_Error error = FT_Err_Ok; 481 FT_Memory memory = phy_font->memory; 482 483 484 if ( phy_font->vertical.stem_snaps != NULL ) 485 goto Exit; 486 487 PFR_CHECK( 1 ); 488 count = PFR_NEXT_BYTE( p ); 489 490 num_vert = count & 15; 491 num_horz = count >> 4; 492 count = num_vert + num_horz; 493 494 PFR_CHECK( count * 2 ); 495 496 if ( FT_NEW_ARRAY( snaps, count ) ) 497 goto Exit; 498 499 phy_font->vertical.stem_snaps = snaps; 500 phy_font->horizontal.stem_snaps = snaps + num_vert; 501 502 for ( ; count > 0; count--, snaps++ ) 503 *snaps = FT_NEXT_SHORT( p ); 504 505 Exit: 506 return error; 507 508 Too_Short: 509 error = FT_THROW( Invalid_Table ); 510 FT_ERROR(( "pfr_exta_item_load_stem_snaps:" 511 " invalid stem snaps table\n" )); 512 goto Exit; 513 } 514 515 516 517 /* load kerning pair data */ 518 FT_CALLBACK_DEF( FT_Error ) pfr_extra_item_load_kerning_pairs(FT_Byte * p,FT_Byte * limit,PFR_PhyFont phy_font)519 pfr_extra_item_load_kerning_pairs( FT_Byte* p, 520 FT_Byte* limit, 521 PFR_PhyFont phy_font ) 522 { 523 PFR_KernItem item = NULL; 524 FT_Error error = FT_Err_Ok; 525 FT_Memory memory = phy_font->memory; 526 527 528 FT_TRACE2(( "pfr_extra_item_load_kerning_pairs()\n" )); 529 530 if ( FT_NEW( item ) ) 531 goto Exit; 532 533 PFR_CHECK( 4 ); 534 535 item->pair_count = PFR_NEXT_BYTE( p ); 536 item->base_adj = PFR_NEXT_SHORT( p ); 537 item->flags = PFR_NEXT_BYTE( p ); 538 item->offset = phy_font->offset + 539 (FT_Offset)( p - phy_font->cursor ); 540 541 #ifndef PFR_CONFIG_NO_CHECKS 542 item->pair_size = 3; 543 544 if ( item->flags & PFR_KERN_2BYTE_CHAR ) 545 item->pair_size += 2; 546 547 if ( item->flags & PFR_KERN_2BYTE_ADJ ) 548 item->pair_size += 1; 549 550 PFR_CHECK( item->pair_count * item->pair_size ); 551 #endif 552 553 /* load first and last pairs into the item to speed up */ 554 /* lookup later... */ 555 if ( item->pair_count > 0 ) 556 { 557 FT_UInt char1, char2; 558 FT_Byte* q; 559 560 561 if ( item->flags & PFR_KERN_2BYTE_CHAR ) 562 { 563 q = p; 564 char1 = PFR_NEXT_USHORT( q ); 565 char2 = PFR_NEXT_USHORT( q ); 566 567 item->pair1 = PFR_KERN_INDEX( char1, char2 ); 568 569 q = p + item->pair_size * ( item->pair_count - 1 ); 570 char1 = PFR_NEXT_USHORT( q ); 571 char2 = PFR_NEXT_USHORT( q ); 572 573 item->pair2 = PFR_KERN_INDEX( char1, char2 ); 574 } 575 else 576 { 577 q = p; 578 char1 = PFR_NEXT_BYTE( q ); 579 char2 = PFR_NEXT_BYTE( q ); 580 581 item->pair1 = PFR_KERN_INDEX( char1, char2 ); 582 583 q = p + item->pair_size * ( item->pair_count - 1 ); 584 char1 = PFR_NEXT_BYTE( q ); 585 char2 = PFR_NEXT_BYTE( q ); 586 587 item->pair2 = PFR_KERN_INDEX( char1, char2 ); 588 } 589 590 /* add new item to the current list */ 591 item->next = NULL; 592 *phy_font->kern_items_tail = item; 593 phy_font->kern_items_tail = &item->next; 594 phy_font->num_kern_pairs += item->pair_count; 595 } 596 else 597 { 598 /* empty item! */ 599 FT_FREE( item ); 600 } 601 602 Exit: 603 return error; 604 605 Too_Short: 606 FT_FREE( item ); 607 608 error = FT_THROW( Invalid_Table ); 609 FT_ERROR(( "pfr_extra_item_load_kerning_pairs:" 610 " invalid kerning pairs table\n" )); 611 goto Exit; 612 } 613 614 615 616 static const PFR_ExtraItemRec pfr_phy_font_extra_items[] = 617 { 618 { 1, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_bitmap_info }, 619 { 2, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_font_id }, 620 { 3, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_stem_snaps }, 621 { 4, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_kerning_pairs }, 622 { 0, NULL } 623 }; 624 625 626 /* Loads a name from the auxiliary data. Since this extracts undocumented 627 * strings from the font file, we need to be careful here. 628 */ 629 static FT_Error pfr_aux_name_load(FT_Byte * p,FT_UInt len,FT_Memory memory,FT_String ** astring)630 pfr_aux_name_load( FT_Byte* p, 631 FT_UInt len, 632 FT_Memory memory, 633 FT_String* *astring ) 634 { 635 FT_Error error = FT_Err_Ok; 636 FT_String* result = NULL; 637 FT_UInt n, ok; 638 639 640 if ( len > 0 && p[len - 1] == 0 ) 641 len--; 642 643 /* check that each character is ASCII for making sure not to 644 load garbage 645 */ 646 ok = ( len > 0 ); 647 for ( n = 0; n < len; n++ ) 648 if ( p[n] < 32 || p[n] > 127 ) 649 { 650 ok = 0; 651 break; 652 } 653 654 if ( ok ) 655 { 656 if ( FT_ALLOC( result, len + 1 ) ) 657 goto Exit; 658 659 FT_MEM_COPY( result, p, len ); 660 result[len] = 0; 661 } 662 Exit: 663 *astring = result; 664 return error; 665 } 666 667 668 FT_LOCAL_DEF( void ) pfr_phy_font_done(PFR_PhyFont phy_font,FT_Memory memory)669 pfr_phy_font_done( PFR_PhyFont phy_font, 670 FT_Memory memory ) 671 { 672 FT_FREE( phy_font->font_id ); 673 FT_FREE( phy_font->family_name ); 674 FT_FREE( phy_font->style_name ); 675 676 FT_FREE( phy_font->vertical.stem_snaps ); 677 phy_font->vertical.num_stem_snaps = 0; 678 679 phy_font->horizontal.stem_snaps = NULL; 680 phy_font->horizontal.num_stem_snaps = 0; 681 682 FT_FREE( phy_font->strikes ); 683 phy_font->num_strikes = 0; 684 phy_font->max_strikes = 0; 685 686 FT_FREE( phy_font->chars ); 687 phy_font->num_chars = 0; 688 phy_font->chars_offset = 0; 689 690 FT_FREE( phy_font->blue_values ); 691 phy_font->num_blue_values = 0; 692 693 { 694 PFR_KernItem item, next; 695 696 697 item = phy_font->kern_items; 698 while ( item ) 699 { 700 next = item->next; 701 FT_FREE( item ); 702 item = next; 703 } 704 phy_font->kern_items = NULL; 705 phy_font->kern_items_tail = NULL; 706 } 707 708 phy_font->num_kern_pairs = 0; 709 } 710 711 712 FT_LOCAL_DEF( FT_Error ) pfr_phy_font_load(PFR_PhyFont phy_font,FT_Stream stream,FT_UInt32 offset,FT_UInt32 size)713 pfr_phy_font_load( PFR_PhyFont phy_font, 714 FT_Stream stream, 715 FT_UInt32 offset, 716 FT_UInt32 size ) 717 { 718 FT_Error error; 719 FT_Memory memory = stream->memory; 720 FT_UInt flags; 721 FT_ULong num_aux; 722 FT_Byte* p; 723 FT_Byte* limit; 724 725 726 phy_font->memory = memory; 727 phy_font->offset = offset; 728 729 phy_font->kern_items = NULL; 730 phy_font->kern_items_tail = &phy_font->kern_items; 731 732 if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) ) 733 goto Exit; 734 735 phy_font->cursor = stream->cursor; 736 737 p = stream->cursor; 738 limit = p + size; 739 740 PFR_CHECK( 15 ); 741 phy_font->font_ref_number = PFR_NEXT_USHORT( p ); 742 phy_font->outline_resolution = PFR_NEXT_USHORT( p ); 743 phy_font->metrics_resolution = PFR_NEXT_USHORT( p ); 744 phy_font->bbox.xMin = PFR_NEXT_SHORT( p ); 745 phy_font->bbox.yMin = PFR_NEXT_SHORT( p ); 746 phy_font->bbox.xMax = PFR_NEXT_SHORT( p ); 747 phy_font->bbox.yMax = PFR_NEXT_SHORT( p ); 748 phy_font->flags = flags = PFR_NEXT_BYTE( p ); 749 750 /* get the standard advance for non-proportional fonts */ 751 if ( !(flags & PFR_PHY_PROPORTIONAL) ) 752 { 753 PFR_CHECK( 2 ); 754 phy_font->standard_advance = PFR_NEXT_SHORT( p ); 755 } 756 757 /* load the extra items when present */ 758 if ( flags & PFR_PHY_EXTRA_ITEMS ) 759 { 760 error = pfr_extra_items_parse( &p, limit, 761 pfr_phy_font_extra_items, phy_font ); 762 763 if ( error ) 764 goto Fail; 765 } 766 767 /* In certain fonts, the auxiliary bytes contain interesting */ 768 /* information. These are not in the specification but can be */ 769 /* guessed by looking at the content of a few PFR0 fonts. */ 770 PFR_CHECK( 3 ); 771 num_aux = PFR_NEXT_ULONG( p ); 772 773 if ( num_aux > 0 ) 774 { 775 FT_Byte* q = p; 776 FT_Byte* q2; 777 778 779 PFR_CHECK( num_aux ); 780 p += num_aux; 781 782 while ( num_aux > 0 ) 783 { 784 FT_UInt length, type; 785 786 787 if ( q + 4 > p ) 788 break; 789 790 length = PFR_NEXT_USHORT( q ); 791 if ( length < 4 || length > num_aux ) 792 break; 793 794 q2 = q + length - 2; 795 type = PFR_NEXT_USHORT( q ); 796 797 switch ( type ) 798 { 799 case 1: 800 /* this seems to correspond to the font's family name, 801 * padded to 16-bits with one zero when necessary 802 */ 803 error = pfr_aux_name_load( q, length - 4U, memory, 804 &phy_font->family_name ); 805 if ( error ) 806 goto Exit; 807 break; 808 809 case 2: 810 if ( q + 32 > q2 ) 811 break; 812 813 q += 10; 814 phy_font->ascent = PFR_NEXT_SHORT( q ); 815 phy_font->descent = PFR_NEXT_SHORT( q ); 816 phy_font->leading = PFR_NEXT_SHORT( q ); 817 break; 818 819 case 3: 820 /* this seems to correspond to the font's style name, 821 * padded to 16-bits with one zero when necessary 822 */ 823 error = pfr_aux_name_load( q, length - 4U, memory, 824 &phy_font->style_name ); 825 if ( error ) 826 goto Exit; 827 break; 828 829 default: 830 ; 831 } 832 833 q = q2; 834 num_aux -= length; 835 } 836 } 837 838 /* read the blue values */ 839 { 840 FT_UInt n, count; 841 842 843 PFR_CHECK( 1 ); 844 phy_font->num_blue_values = count = PFR_NEXT_BYTE( p ); 845 846 PFR_CHECK( count * 2 ); 847 848 if ( FT_NEW_ARRAY( phy_font->blue_values, count ) ) 849 goto Fail; 850 851 for ( n = 0; n < count; n++ ) 852 phy_font->blue_values[n] = PFR_NEXT_SHORT( p ); 853 } 854 855 PFR_CHECK( 8 ); 856 phy_font->blue_fuzz = PFR_NEXT_BYTE( p ); 857 phy_font->blue_scale = PFR_NEXT_BYTE( p ); 858 859 phy_font->vertical.standard = PFR_NEXT_USHORT( p ); 860 phy_font->horizontal.standard = PFR_NEXT_USHORT( p ); 861 862 /* read the character descriptors */ 863 { 864 FT_UInt n, count, Size; 865 866 867 phy_font->num_chars = count = PFR_NEXT_USHORT( p ); 868 phy_font->chars_offset = offset + (FT_Offset)( p - stream->cursor ); 869 870 if ( FT_NEW_ARRAY( phy_font->chars, count ) ) 871 goto Fail; 872 873 Size = 1 + 1 + 2; 874 if ( flags & PFR_PHY_2BYTE_CHARCODE ) 875 Size += 1; 876 877 if ( flags & PFR_PHY_PROPORTIONAL ) 878 Size += 2; 879 880 if ( flags & PFR_PHY_ASCII_CODE ) 881 Size += 1; 882 883 if ( flags & PFR_PHY_2BYTE_GPS_SIZE ) 884 Size += 1; 885 886 if ( flags & PFR_PHY_3BYTE_GPS_OFFSET ) 887 Size += 1; 888 889 PFR_CHECK( count * Size ); 890 891 for ( n = 0; n < count; n++ ) 892 { 893 PFR_Char cur = &phy_font->chars[n]; 894 895 896 cur->char_code = ( flags & PFR_PHY_2BYTE_CHARCODE ) 897 ? PFR_NEXT_USHORT( p ) 898 : PFR_NEXT_BYTE( p ); 899 900 cur->advance = ( flags & PFR_PHY_PROPORTIONAL ) 901 ? PFR_NEXT_SHORT( p ) 902 : phy_font->standard_advance; 903 904 #if 0 905 cur->ascii = ( flags & PFR_PHY_ASCII_CODE ) 906 ? PFR_NEXT_BYTE( p ) 907 : 0; 908 #else 909 if ( flags & PFR_PHY_ASCII_CODE ) 910 p += 1; 911 #endif 912 cur->gps_size = ( flags & PFR_PHY_2BYTE_GPS_SIZE ) 913 ? PFR_NEXT_USHORT( p ) 914 : PFR_NEXT_BYTE( p ); 915 916 cur->gps_offset = ( flags & PFR_PHY_3BYTE_GPS_OFFSET ) 917 ? PFR_NEXT_ULONG( p ) 918 : PFR_NEXT_USHORT( p ); 919 } 920 } 921 922 /* that's it! */ 923 924 Fail: 925 FT_FRAME_EXIT(); 926 927 /* save position of bitmap info */ 928 phy_font->bct_offset = FT_STREAM_POS(); 929 phy_font->cursor = NULL; 930 931 Exit: 932 return error; 933 934 Too_Short: 935 error = FT_THROW( Invalid_Table ); 936 FT_ERROR(( "pfr_phy_font_load: invalid physical font table\n" )); 937 goto Fail; 938 } 939 940 941 /* END */ 942