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