1 /***************************************************************************/ 2 /* */ 3 /* ttsbit.c */ 4 /* */ 5 /* TrueType and OpenType embedded bitmap support (body). */ 6 /* */ 7 /* Copyright 1996-2001, 2002 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 <ft2build.h> 20 #include FT_INTERNAL_DEBUG_H 21 #include FT_INTERNAL_STREAM_H 22 #include FT_TRUETYPE_TAGS_H 23 #include "ttsbit.h" 24 25 #include "sferrors.h" 26 27 28 /*************************************************************************/ 29 /* */ 30 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 31 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 32 /* messages during execution. */ 33 /* */ 34 #undef FT_COMPONENT 35 #define FT_COMPONENT trace_ttsbit 36 37 38 /*************************************************************************/ 39 /* */ 40 /* <Function> */ 41 /* blit_sbit */ 42 /* */ 43 /* <Description> */ 44 /* Blits a bitmap from an input stream into a given target. Supports */ 45 /* x and y offsets as well as byte padded lines. */ 46 /* */ 47 /* <Input> */ 48 /* target :: The target bitmap/pixmap. */ 49 /* */ 50 /* source :: The input packed bitmap data. */ 51 /* */ 52 /* line_bits :: The number of bits per line. */ 53 /* */ 54 /* byte_padded :: A flag which is true if lines are byte-padded. */ 55 /* */ 56 /* x_offset :: The horizontal offset. */ 57 /* */ 58 /* y_offset :: The vertical offset. */ 59 /* */ 60 /* <Note> */ 61 /* IMPORTANT: The x and y offsets are relative to the top corner of */ 62 /* the target bitmap (unlike the normal TrueType */ 63 /* convention). A positive y offset indicates a downwards */ 64 /* direction! */ 65 /* */ 66 static void 67 blit_sbit( FT_Bitmap* target, 68 FT_Byte* source, 69 FT_Int line_bits, 70 FT_Bool byte_padded, 71 FT_Int x_offset, 72 FT_Int y_offset ) 73 { 74 FT_Byte* line_buff; 75 FT_Int line_incr; 76 FT_Int height; 77 78 FT_UShort acc; 79 FT_UInt loaded; 80 81 82 /* first of all, compute starting write position */ 83 line_incr = target->pitch; 84 line_buff = target->buffer; 85 86 if ( line_incr < 0 ) 87 line_buff -= line_incr * ( target->rows - 1 ); 88 89 line_buff += ( x_offset >> 3 ) + y_offset * line_incr; 90 91 /***********************************************************************/ 92 /* */ 93 /* We use the extra-classic `accumulator' trick to extract the bits */ 94 /* from the source byte stream. */ 95 /* */ 96 /* Namely, the variable `acc' is a 16-bit accumulator containing the */ 97 /* last `loaded' bits from the input stream. The bits are shifted to */ 98 /* the upmost position in `acc'. */ 99 /* */ 100 /***********************************************************************/ 101 102 acc = 0; /* clear accumulator */ 103 loaded = 0; /* no bits were loaded */ 104 105 for ( height = target->rows; height > 0; height-- ) 106 { 107 FT_Byte* cur = line_buff; /* current write cursor */ 108 FT_Int count = line_bits; /* # of bits to extract per line */ 109 FT_Byte shift = (FT_Byte)( x_offset & 7 ); /* current write shift */ 110 FT_Byte space = (FT_Byte)( 8 - shift ); 111 112 113 /* first of all, read individual source bytes */ 114 if ( count >= 8 ) 115 { 116 count -= 8; 117 { 118 do 119 { 120 FT_Byte val; 121 122 123 /* ensure that there are at least 8 bits in the accumulator */ 124 if ( loaded < 8 ) 125 { 126 acc |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded )); 127 loaded += 8; 128 } 129 130 /* now write one byte */ 131 val = (FT_Byte)( acc >> 8 ); 132 if ( shift ) 133 { 134 cur[0] |= (FT_Byte)( val >> shift ); 135 cur[1] |= (FT_Byte)( val << space ); 136 } 137 else 138 cur[0] |= val; 139 140 cur++; 141 acc <<= 8; /* remove bits from accumulator */ 142 loaded -= 8; 143 count -= 8; 144 145 } while ( count >= 0 ); 146 } 147 148 /* restore `count' to correct value */ 149 count += 8; 150 } 151 152 /* now write remaining bits (count < 8) */ 153 if ( count > 0 ) 154 { 155 FT_Byte val; 156 157 158 /* ensure that there are at least `count' bits in the accumulator */ 159 if ( (FT_Int)loaded < count ) 160 { 161 acc |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded )); 162 loaded += 8; 163 } 164 165 /* now write remaining bits */ 166 val = (FT_Byte)( ( (FT_Byte)( acc >> 8 ) ) & ~( 0xFF >> count ) ); 167 cur[0] |= (FT_Byte)( val >> shift ); 168 169 if ( count > space ) 170 cur[1] |= (FT_Byte)( val << space ); 171 172 acc <<= count; 173 loaded -= count; 174 } 175 176 /* now, skip to next line */ 177 if ( byte_padded ) 178 { 179 acc = 0; 180 loaded = 0; /* clear accumulator on byte-padded lines */ 181 } 182 183 line_buff += line_incr; 184 } 185 } 186 187 188 const FT_Frame_Field sbit_metrics_fields[] = 189 { 190 #undef FT_STRUCTURE 191 #define FT_STRUCTURE TT_SBit_MetricsRec 192 193 FT_FRAME_START( 8 ), 194 FT_FRAME_BYTE( height ), 195 FT_FRAME_BYTE( width ), 196 197 FT_FRAME_CHAR( horiBearingX ), 198 FT_FRAME_CHAR( horiBearingY ), 199 FT_FRAME_BYTE( horiAdvance ), 200 201 FT_FRAME_CHAR( vertBearingX ), 202 FT_FRAME_CHAR( vertBearingY ), 203 FT_FRAME_BYTE( vertAdvance ), 204 FT_FRAME_END 205 }; 206 207 208 /*************************************************************************/ 209 /* */ 210 /* <Function> */ 211 /* TT_Load_SBit_Const_Metrics */ 212 /* */ 213 /* <Description> */ 214 /* Loads the metrics for `EBLC' index tables format 2 and 5. */ 215 /* */ 216 /* <Input> */ 217 /* range :: The target range. */ 218 /* */ 219 /* stream :: The input stream. */ 220 /* */ 221 /* <Return> */ 222 /* FreeType error code. 0 means success. */ 223 /* */ 224 static FT_Error 225 Load_SBit_Const_Metrics( TT_SBit_Range range, 226 FT_Stream stream ) 227 { 228 FT_Error error; 229 230 231 if ( FT_READ_ULONG( range->image_size ) ) 232 return error; 233 234 return FT_STREAM_READ_FIELDS( sbit_metrics_fields, &range->metrics ); 235 } 236 237 238 /*************************************************************************/ 239 /* */ 240 /* <Function> */ 241 /* TT_Load_SBit_Range_Codes */ 242 /* */ 243 /* <Description> */ 244 /* Loads the range codes for `EBLC' index tables format 4 and 5. */ 245 /* */ 246 /* <Input> */ 247 /* range :: The target range. */ 248 /* */ 249 /* stream :: The input stream. */ 250 /* */ 251 /* load_offsets :: A flag whether to load the glyph offset table. */ 252 /* */ 253 /* <Return> */ 254 /* FreeType error code. 0 means success. */ 255 /* */ 256 static FT_Error 257 Load_SBit_Range_Codes( TT_SBit_Range range, 258 FT_Stream stream, 259 FT_Bool load_offsets ) 260 { 261 FT_Error error; 262 FT_ULong count, n, size; 263 FT_Memory memory = stream->memory; 264 265 266 if ( FT_READ_ULONG( count ) ) 267 goto Exit; 268 269 range->num_glyphs = count; 270 271 /* Allocate glyph offsets table if needed */ 272 if ( load_offsets ) 273 { 274 if ( FT_NEW_ARRAY( range->glyph_offsets, count ) ) 275 goto Exit; 276 277 size = count * 4L; 278 } 279 else 280 size = count * 2L; 281 282 /* Allocate glyph codes table and access frame */ 283 if ( FT_NEW_ARRAY ( range->glyph_codes, count ) || 284 FT_FRAME_ENTER( size ) ) 285 goto Exit; 286 287 for ( n = 0; n < count; n++ ) 288 { 289 range->glyph_codes[n] = FT_GET_USHORT(); 290 291 if ( load_offsets ) 292 range->glyph_offsets[n] = (FT_ULong)range->image_offset + 293 FT_GET_USHORT(); 294 } 295 296 FT_FRAME_EXIT(); 297 298 Exit: 299 return error; 300 } 301 302 303 /*************************************************************************/ 304 /* */ 305 /* <Function> */ 306 /* TT_Load_SBit_Range */ 307 /* */ 308 /* <Description> */ 309 /* Loads a given `EBLC' index/range table. */ 310 /* */ 311 /* <Input> */ 312 /* range :: The target range. */ 313 /* */ 314 /* stream :: The input stream. */ 315 /* */ 316 /* <Return> */ 317 /* FreeType error code. 0 means success. */ 318 /* */ 319 static FT_Error 320 Load_SBit_Range( TT_SBit_Range range, 321 FT_Stream stream ) 322 { 323 FT_Error error; 324 FT_Memory memory = stream->memory; 325 326 327 switch( range->index_format ) 328 { 329 case 1: /* variable metrics with 4-byte offsets */ 330 case 3: /* variable metrics with 2-byte offsets */ 331 { 332 FT_ULong num_glyphs, n; 333 FT_Int size_elem; 334 FT_Bool large = FT_BOOL( range->index_format == 1 ); 335 336 337 num_glyphs = range->last_glyph - range->first_glyph + 1L; 338 range->num_glyphs = num_glyphs; 339 num_glyphs++; /* XXX: BEWARE - see spec */ 340 341 size_elem = large ? 4 : 2; 342 343 if ( FT_NEW_ARRAY( range->glyph_offsets, num_glyphs ) || 344 FT_FRAME_ENTER( num_glyphs * size_elem ) ) 345 goto Exit; 346 347 for ( n = 0; n < num_glyphs; n++ ) 348 range->glyph_offsets[n] = (FT_ULong)( range->image_offset + 349 ( large ? FT_GET_ULONG() 350 : FT_GET_USHORT() ) ); 351 FT_FRAME_EXIT(); 352 } 353 break; 354 355 case 2: /* all glyphs have identical metrics */ 356 error = Load_SBit_Const_Metrics( range, stream ); 357 break; 358 359 case 4: 360 error = Load_SBit_Range_Codes( range, stream, 1 ); 361 break; 362 363 case 5: 364 error = Load_SBit_Const_Metrics( range, stream ) || 365 Load_SBit_Range_Codes( range, stream, 0 ); 366 break; 367 368 default: 369 error = SFNT_Err_Invalid_File_Format; 370 } 371 372 Exit: 373 return error; 374 } 375 376 377 /*************************************************************************/ 378 /* */ 379 /* <Function> */ 380 /* tt_face_load_sbit_strikes */ 381 /* */ 382 /* <Description> */ 383 /* Loads the table of embedded bitmap sizes for this face. */ 384 /* */ 385 /* <Input> */ 386 /* face :: The target face object. */ 387 /* */ 388 /* stream :: The input stream. */ 389 /* */ 390 /* <Return> */ 391 /* FreeType error code. 0 means success. */ 392 /* */ 393 FT_LOCAL_DEF( FT_Error ) 394 tt_face_load_sbit_strikes( TT_Face face, 395 FT_Stream stream ) 396 { 397 FT_Error error = 0; 398 FT_Memory memory = stream->memory; 399 FT_Fixed version; 400 FT_ULong num_strikes; 401 FT_ULong table_base; 402 403 const FT_Frame_Field sbit_line_metrics_fields[] = 404 { 405 #undef FT_STRUCTURE 406 #define FT_STRUCTURE TT_SBit_LineMetricsRec 407 408 /* no FT_FRAME_START */ 409 FT_FRAME_CHAR( ascender ), 410 FT_FRAME_CHAR( descender ), 411 FT_FRAME_BYTE( max_width ), 412 413 FT_FRAME_CHAR( caret_slope_numerator ), 414 FT_FRAME_CHAR( caret_slope_denominator ), 415 FT_FRAME_CHAR( caret_offset ), 416 417 FT_FRAME_CHAR( min_origin_SB ), 418 FT_FRAME_CHAR( min_advance_SB ), 419 FT_FRAME_CHAR( max_before_BL ), 420 FT_FRAME_CHAR( min_after_BL ), 421 FT_FRAME_CHAR( pads[0] ), 422 FT_FRAME_CHAR( pads[1] ), 423 FT_FRAME_END 424 }; 425 426 const FT_Frame_Field strike_start_fields[] = 427 { 428 #undef FT_STRUCTURE 429 #define FT_STRUCTURE TT_SBit_StrikeRec 430 431 /* no FT_FRAME_START */ 432 FT_FRAME_ULONG( ranges_offset ), 433 FT_FRAME_SKIP_LONG, 434 FT_FRAME_ULONG( num_ranges ), 435 FT_FRAME_ULONG( color_ref ), 436 FT_FRAME_END 437 }; 438 439 const FT_Frame_Field strike_end_fields[] = 440 { 441 /* no FT_FRAME_START */ 442 FT_FRAME_USHORT( start_glyph ), 443 FT_FRAME_USHORT( end_glyph ), 444 FT_FRAME_BYTE ( x_ppem ), 445 FT_FRAME_BYTE ( y_ppem ), 446 FT_FRAME_BYTE ( bit_depth ), 447 FT_FRAME_CHAR ( flags ), 448 FT_FRAME_END 449 }; 450 451 452 face->num_sbit_strikes = 0; 453 454 /* this table is optional */ 455 error = face->goto_table( face, TTAG_EBLC, stream, 0 ); 456 if ( error ) 457 error = face->goto_table( face, TTAG_bloc, stream, 0 ); 458 if ( error ) 459 goto Exit; 460 461 table_base = FT_STREAM_POS(); 462 if ( FT_FRAME_ENTER( 8L ) ) 463 goto Exit; 464 465 version = FT_GET_LONG(); 466 num_strikes = FT_GET_ULONG(); 467 468 FT_FRAME_EXIT(); 469 470 /* check version number and strike count */ 471 if ( version != 0x00020000L || 472 num_strikes >= 0x10000L ) 473 { 474 FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version!\n" )); 475 error = SFNT_Err_Invalid_File_Format; 476 477 goto Exit; 478 } 479 480 /* allocate the strikes table */ 481 if ( FT_NEW_ARRAY( face->sbit_strikes, num_strikes ) ) 482 goto Exit; 483 484 face->num_sbit_strikes = num_strikes; 485 486 /* now read each strike table separately */ 487 { 488 TT_SBit_Strike strike = face->sbit_strikes; 489 FT_ULong count = num_strikes; 490 491 492 if ( FT_FRAME_ENTER( 48L * num_strikes ) ) 493 goto Exit; 494 495 while ( count > 0 ) 496 { 497 if ( FT_STREAM_READ_FIELDS( strike_start_fields, strike ) || 498 FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->hori ) || 499 FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->vert ) || 500 FT_STREAM_READ_FIELDS( strike_end_fields, strike ) ) 501 break; 502 503 count--; 504 strike++; 505 } 506 507 FT_FRAME_EXIT(); 508 } 509 510 /* allocate the index ranges for each strike table */ 511 { 512 TT_SBit_Strike strike = face->sbit_strikes; 513 FT_ULong count = num_strikes; 514 515 516 while ( count > 0 ) 517 { 518 TT_SBit_Range range; 519 FT_ULong count2 = strike->num_ranges; 520 521 522 if ( FT_NEW_ARRAY( strike->sbit_ranges, strike->num_ranges ) ) 523 goto Exit; 524 525 /* read each range */ 526 if ( FT_STREAM_SEEK( table_base + strike->ranges_offset ) || 527 FT_FRAME_ENTER( strike->num_ranges * 8L ) ) 528 goto Exit; 529 530 range = strike->sbit_ranges; 531 while ( count2 > 0 ) 532 { 533 range->first_glyph = FT_GET_USHORT(); 534 range->last_glyph = FT_GET_USHORT(); 535 range->table_offset = table_base + strike->ranges_offset + 536 FT_GET_ULONG(); 537 count2--; 538 range++; 539 } 540 541 FT_FRAME_EXIT(); 542 543 /* Now, read each index table */ 544 count2 = strike->num_ranges; 545 range = strike->sbit_ranges; 546 while ( count2 > 0 ) 547 { 548 /* Read the header */ 549 if ( FT_STREAM_SEEK( range->table_offset ) || 550 FT_FRAME_ENTER( 8L ) ) 551 goto Exit; 552 553 range->index_format = FT_GET_USHORT(); 554 range->image_format = FT_GET_USHORT(); 555 range->image_offset = FT_GET_ULONG(); 556 557 FT_FRAME_EXIT(); 558 559 error = Load_SBit_Range( range, stream ); 560 if ( error ) 561 goto Exit; 562 563 count2--; 564 range++; 565 } 566 567 count--; 568 strike++; 569 } 570 } 571 572 Exit: 573 return error; 574 } 575 576 577 /*************************************************************************/ 578 /* */ 579 /* <Function> */ 580 /* tt_face_free_sbit_strikes */ 581 /* */ 582 /* <Description> */ 583 /* Releases the embedded bitmap tables. */ 584 /* */ 585 /* <Input> */ 586 /* face :: The target face object. */ 587 /* */ 588 FT_LOCAL_DEF( void ) 589 tt_face_free_sbit_strikes( TT_Face face ) 590 { 591 FT_Memory memory = face->root.memory; 592 TT_SBit_Strike strike = face->sbit_strikes; 593 TT_SBit_Strike strike_limit = strike + face->num_sbit_strikes; 594 595 596 if ( strike ) 597 { 598 for ( ; strike < strike_limit; strike++ ) 599 { 600 TT_SBit_Range range = strike->sbit_ranges; 601 TT_SBit_Range range_limit = range + strike->num_ranges; 602 603 604 if ( range ) 605 { 606 for ( ; range < range_limit; range++ ) 607 { 608 /* release the glyph offsets and codes tables */ 609 /* where appropriate */ 610 FT_FREE( range->glyph_offsets ); 611 FT_FREE( range->glyph_codes ); 612 } 613 } 614 FT_FREE( strike->sbit_ranges ); 615 strike->num_ranges = 0; 616 } 617 FT_FREE( face->sbit_strikes ); 618 } 619 face->num_sbit_strikes = 0; 620 } 621 622 623 FT_LOCAL_DEF( FT_Error ) 624 tt_face_set_sbit_strike( TT_Face face, 625 FT_Int x_ppem, 626 FT_Int y_ppem, 627 FT_ULong *astrike_index ) 628 { 629 FT_ULong i; 630 631 632 if ( x_ppem < 0 || x_ppem > 255 || 633 y_ppem < 1 || y_ppem > 255 ) 634 return SFNT_Err_Invalid_PPem; 635 636 for ( i = 0; i < face->num_sbit_strikes; i++ ) 637 { 638 if ( ( face->sbit_strikes[i].y_ppem == y_ppem ) && 639 ( ( x_ppem == 0 ) || 640 ( face->sbit_strikes[i].x_ppem == x_ppem ) ) ) 641 { 642 *astrike_index = i; 643 return SFNT_Err_Ok; 644 } 645 } 646 647 return SFNT_Err_Invalid_PPem; 648 } 649 650 651 /*************************************************************************/ 652 /* */ 653 /* <Function> */ 654 /* find_sbit_range */ 655 /* */ 656 /* <Description> */ 657 /* Scans a given strike's ranges and return, for a given glyph */ 658 /* index, the corresponding sbit range, and `EBDT' offset. */ 659 /* */ 660 /* <Input> */ 661 /* glyph_index :: The glyph index. */ 662 /* */ 663 /* strike :: The source/current sbit strike. */ 664 /* */ 665 /* <Output> */ 666 /* arange :: The sbit range containing the glyph index. */ 667 /* */ 668 /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */ 669 /* */ 670 /* <Return> */ 671 /* FreeType error code. 0 means the glyph index was found. */ 672 /* */ 673 static FT_Error 674 find_sbit_range( FT_UInt glyph_index, 675 TT_SBit_Strike strike, 676 TT_SBit_Range *arange, 677 FT_ULong *aglyph_offset ) 678 { 679 TT_SBit_RangeRec *range, *range_limit; 680 681 682 /* check whether the glyph index is within this strike's */ 683 /* glyph range */ 684 if ( glyph_index < (FT_UInt)strike->start_glyph || 685 glyph_index > (FT_UInt)strike->end_glyph ) 686 goto Fail; 687 688 /* scan all ranges in strike */ 689 range = strike->sbit_ranges; 690 range_limit = range + strike->num_ranges; 691 if ( !range ) 692 goto Fail; 693 694 for ( ; range < range_limit; range++ ) 695 { 696 if ( glyph_index >= (FT_UInt)range->first_glyph && 697 glyph_index <= (FT_UInt)range->last_glyph ) 698 { 699 FT_UShort delta = (FT_UShort)( glyph_index - range->first_glyph ); 700 701 702 switch ( range->index_format ) 703 { 704 case 1: 705 case 3: 706 *aglyph_offset = range->glyph_offsets[delta]; 707 break; 708 709 case 2: 710 *aglyph_offset = range->image_offset + 711 range->image_size * delta; 712 break; 713 714 case 4: 715 case 5: 716 { 717 FT_ULong n; 718 719 720 for ( n = 0; n < range->num_glyphs; n++ ) 721 { 722 if ( (FT_UInt)range->glyph_codes[n] == glyph_index ) 723 { 724 if ( range->index_format == 4 ) 725 *aglyph_offset = range->glyph_offsets[n]; 726 else 727 *aglyph_offset = range->image_offset + 728 n * range->image_size; 729 goto Found; 730 } 731 } 732 } 733 734 /* fall-through */ 735 default: 736 goto Fail; 737 } 738 739 Found: 740 /* return successfully! */ 741 *arange = range; 742 return 0; 743 } 744 } 745 746 Fail: 747 *arange = 0; 748 *aglyph_offset = 0; 749 750 return SFNT_Err_Invalid_Argument; 751 } 752 753 754 /*************************************************************************/ 755 /* */ 756 /* <Function> */ 757 /* find_sbit_image */ 758 /* */ 759 /* <Description> */ 760 /* Checks whether an embedded bitmap (an `sbit') exists for a given */ 761 /* glyph, at a given strike. */ 762 /* */ 763 /* <Input> */ 764 /* face :: The target face object. */ 765 /* */ 766 /* glyph_index :: The glyph index. */ 767 /* */ 768 /* strike_index :: The current strike index. */ 769 /* */ 770 /* <Output> */ 771 /* arange :: The SBit range containing the glyph index. */ 772 /* */ 773 /* astrike :: The SBit strike containing the glyph index. */ 774 /* */ 775 /* aglyph_offset :: The offset of the glyph data in `EBDT' table. */ 776 /* */ 777 /* <Return> */ 778 /* FreeType error code. 0 means success. Returns */ 779 /* SFNT_Err_Invalid_Argument if no sbit exists for the requested */ 780 /* glyph. */ 781 /* */ 782 static FT_Error 783 find_sbit_image( TT_Face face, 784 FT_UInt glyph_index, 785 FT_ULong strike_index, 786 TT_SBit_Range *arange, 787 TT_SBit_Strike *astrike, 788 FT_ULong *aglyph_offset ) 789 { 790 FT_Error error; 791 TT_SBit_Strike strike; 792 793 794 if ( !face->sbit_strikes || 795 ( face->num_sbit_strikes <= strike_index ) ) 796 goto Fail; 797 798 strike = &face->sbit_strikes[strike_index]; 799 800 error = find_sbit_range( glyph_index, strike, 801 arange, aglyph_offset ); 802 if ( error ) 803 goto Fail; 804 805 *astrike = strike; 806 807 return SFNT_Err_Ok; 808 809 Fail: 810 /* no embedded bitmap for this glyph in face */ 811 *arange = 0; 812 *astrike = 0; 813 *aglyph_offset = 0; 814 815 return SFNT_Err_Invalid_Argument; 816 } 817 818 819 /*************************************************************************/ 820 /* */ 821 /* <Function> */ 822 /* load_sbit_metrics */ 823 /* */ 824 /* <Description> */ 825 /* Gets the big metrics for a given SBit. */ 826 /* */ 827 /* <Input> */ 828 /* stream :: The input stream. */ 829 /* */ 830 /* range :: The SBit range containing the glyph. */ 831 /* */ 832 /* <Output> */ 833 /* big_metrics :: A big SBit metrics structure for the glyph. */ 834 /* */ 835 /* <Return> */ 836 /* FreeType error code. 0 means success. */ 837 /* */ 838 /* <Note> */ 839 /* The stream cursor must be positioned at the glyph's offset within */ 840 /* the `EBDT' table before the call. */ 841 /* */ 842 /* If the image format uses variable metrics, the stream cursor is */ 843 /* positioned just after the metrics header in the `EBDT' table on */ 844 /* function exit. */ 845 /* */ 846 static FT_Error 847 load_sbit_metrics( FT_Stream stream, 848 TT_SBit_Range range, 849 TT_SBit_Metrics metrics ) 850 { 851 FT_Error error = SFNT_Err_Ok; 852 853 854 switch ( range->image_format ) 855 { 856 case 1: 857 case 2: 858 case 8: 859 /* variable small metrics */ 860 { 861 TT_SBit_SmallMetricsRec smetrics; 862 863 const FT_Frame_Field sbit_small_metrics_fields[] = 864 { 865 #undef FT_STRUCTURE 866 #define FT_STRUCTURE TT_SBit_SmallMetricsRec 867 868 FT_FRAME_START( 5 ), 869 FT_FRAME_BYTE( height ), 870 FT_FRAME_BYTE( width ), 871 FT_FRAME_CHAR( bearingX ), 872 FT_FRAME_CHAR( bearingY ), 873 FT_FRAME_BYTE( advance ), 874 FT_FRAME_END 875 }; 876 877 878 /* read small metrics */ 879 if ( FT_STREAM_READ_FIELDS( sbit_small_metrics_fields, &smetrics ) ) 880 goto Exit; 881 882 /* convert it to a big metrics */ 883 metrics->height = smetrics.height; 884 metrics->width = smetrics.width; 885 metrics->horiBearingX = smetrics.bearingX; 886 metrics->horiBearingY = smetrics.bearingY; 887 metrics->horiAdvance = smetrics.advance; 888 889 /* these metrics are made up at a higher level when */ 890 /* needed. */ 891 metrics->vertBearingX = 0; 892 metrics->vertBearingY = 0; 893 metrics->vertAdvance = 0; 894 } 895 break; 896 897 case 6: 898 case 7: 899 case 9: 900 /* variable big metrics */ 901 if ( FT_STREAM_READ_FIELDS( sbit_metrics_fields, metrics ) ) 902 goto Exit; 903 break; 904 905 case 5: 906 default: /* constant metrics */ 907 if ( range->index_format == 2 || range->index_format == 5 ) 908 *metrics = range->metrics; 909 else 910 return SFNT_Err_Invalid_File_Format; 911 } 912 913 Exit: 914 return error; 915 } 916 917 918 /*************************************************************************/ 919 /* */ 920 /* <Function> */ 921 /* crop_bitmap */ 922 /* */ 923 /* <Description> */ 924 /* Crops a bitmap to its tightest bounding box, and adjusts its */ 925 /* metrics. */ 926 /* */ 927 /* <InOut> */ 928 /* map :: The bitmap. */ 929 /* */ 930 /* metrics :: The corresponding metrics structure. */ 931 /* */ 932 static void 933 crop_bitmap( FT_Bitmap* map, 934 TT_SBit_Metrics metrics ) 935 { 936 /***********************************************************************/ 937 /* */ 938 /* In this situation, some bounding boxes of embedded bitmaps are too */ 939 /* large. We need to crop it to a reasonable size. */ 940 /* */ 941 /* --------- */ 942 /* | | ----- */ 943 /* | *** | |***| */ 944 /* | * | | * | */ 945 /* | * | ------> | * | */ 946 /* | * | | * | */ 947 /* | * | | * | */ 948 /* | *** | |***| */ 949 /* --------- ----- */ 950 /* */ 951 /***********************************************************************/ 952 953 FT_Int rows, count; 954 FT_Long line_len; 955 FT_Byte* line; 956 957 958 /***********************************************************************/ 959 /* */ 960 /* first of all, check the top-most lines of the bitmap, and remove */ 961 /* them if they're empty. */ 962 /* */ 963 { 964 line = (FT_Byte*)map->buffer; 965 rows = map->rows; 966 line_len = map->pitch; 967 968 969 for ( count = 0; count < rows; count++ ) 970 { 971 FT_Byte* cur = line; 972 FT_Byte* limit = line + line_len; 973 974 975 for ( ; cur < limit; cur++ ) 976 if ( cur[0] ) 977 goto Found_Top; 978 979 /* the current line was empty - skip to next one */ 980 line = limit; 981 } 982 983 Found_Top: 984 /* check that we have at least one filled line */ 985 if ( count >= rows ) 986 goto Empty_Bitmap; 987 988 /* now, crop the empty upper lines */ 989 if ( count > 0 ) 990 { 991 line = (FT_Byte*)map->buffer; 992 993 FT_MEM_MOVE( line, line + count * line_len, 994 ( rows - count ) * line_len ); 995 996 metrics->height = (FT_Byte)( metrics->height - count ); 997 metrics->horiBearingY = (FT_Char)( metrics->horiBearingY - count ); 998 metrics->vertBearingY = (FT_Char)( metrics->vertBearingY - count ); 999 1000 map->rows -= count; 1001 rows -= count; 1002 } 1003 } 1004 1005 /***********************************************************************/ 1006 /* */ 1007 /* second, crop the lower lines */ 1008 /* */ 1009 { 1010 line = (FT_Byte*)map->buffer + ( rows - 1 ) * line_len; 1011 1012 for ( count = 0; count < rows; count++ ) 1013 { 1014 FT_Byte* cur = line; 1015 FT_Byte* limit = line + line_len; 1016 1017 1018 for ( ; cur < limit; cur++ ) 1019 if ( cur[0] ) 1020 goto Found_Bottom; 1021 1022 /* the current line was empty - skip to previous one */ 1023 line -= line_len; 1024 } 1025 1026 Found_Bottom: 1027 if ( count > 0 ) 1028 { 1029 metrics->height = (FT_Byte)( metrics->height - count ); 1030 rows -= count; 1031 map->rows -= count; 1032 } 1033 } 1034 1035 /***********************************************************************/ 1036 /* */ 1037 /* third, get rid of the space on the left side of the glyph */ 1038 /* */ 1039 do 1040 { 1041 FT_Byte* limit; 1042 1043 1044 line = (FT_Byte*)map->buffer; 1045 limit = line + rows * line_len; 1046 1047 for ( ; line < limit; line += line_len ) 1048 if ( line[0] & 0x80 ) 1049 goto Found_Left; 1050 1051 /* shift the whole glyph one pixel to the left */ 1052 line = (FT_Byte*)map->buffer; 1053 limit = line + rows * line_len; 1054 1055 for ( ; line < limit; line += line_len ) 1056 { 1057 FT_Int n, width = map->width; 1058 FT_Byte old; 1059 FT_Byte* cur = line; 1060 1061 1062 old = (FT_Byte)(cur[0] << 1); 1063 for ( n = 8; n < width; n += 8 ) 1064 { 1065 FT_Byte val; 1066 1067 1068 val = cur[1]; 1069 cur[0] = (FT_Byte)( old | ( val >> 7 ) ); 1070 old = (FT_Byte)( val << 1 ); 1071 cur++; 1072 } 1073 cur[0] = old; 1074 } 1075 1076 map->width--; 1077 metrics->horiBearingX++; 1078 metrics->vertBearingX++; 1079 metrics->width--; 1080 1081 } while ( map->width > 0 ); 1082 1083 Found_Left: 1084 1085 /***********************************************************************/ 1086 /* */ 1087 /* finally, crop the bitmap width to get rid of the space on the right */ 1088 /* side of the glyph. */ 1089 /* */ 1090 do 1091 { 1092 FT_Int right = map->width - 1; 1093 FT_Byte* limit; 1094 FT_Byte mask; 1095 1096 1097 line = (FT_Byte*)map->buffer + ( right >> 3 ); 1098 limit = line + rows * line_len; 1099 mask = (FT_Byte)( 0x80 >> ( right & 7 ) ); 1100 1101 for ( ; line < limit; line += line_len ) 1102 if ( line[0] & mask ) 1103 goto Found_Right; 1104 1105 /* crop the whole glyph to the right */ 1106 map->width--; 1107 metrics->width--; 1108 1109 } while ( map->width > 0 ); 1110 1111 Found_Right: 1112 /* all right, the bitmap was cropped */ 1113 return; 1114 1115 Empty_Bitmap: 1116 map->width = 0; 1117 map->rows = 0; 1118 map->pitch = 0; 1119 map->pixel_mode = FT_PIXEL_MODE_MONO; 1120 } 1121 1122 1123 static FT_Error 1124 Load_SBit_Single( FT_Bitmap* map, 1125 FT_Int x_offset, 1126 FT_Int y_offset, 1127 FT_Int pix_bits, 1128 FT_UShort image_format, 1129 TT_SBit_Metrics metrics, 1130 FT_Stream stream ) 1131 { 1132 FT_Error error; 1133 1134 1135 /* check that the source bitmap fits into the target pixmap */ 1136 if ( x_offset < 0 || x_offset + metrics->width > map->width || 1137 y_offset < 0 || y_offset + metrics->height > map->rows ) 1138 { 1139 error = SFNT_Err_Invalid_Argument; 1140 1141 goto Exit; 1142 } 1143 1144 { 1145 FT_Int glyph_width = metrics->width; 1146 FT_Int glyph_height = metrics->height; 1147 FT_Int glyph_size; 1148 FT_Int line_bits = pix_bits * glyph_width; 1149 FT_Bool pad_bytes = 0; 1150 1151 1152 /* compute size of glyph image */ 1153 switch ( image_format ) 1154 { 1155 case 1: /* byte-padded formats */ 1156 case 6: 1157 { 1158 FT_Int line_length; 1159 1160 1161 switch ( pix_bits ) 1162 { 1163 case 1: 1164 line_length = ( glyph_width + 7 ) >> 3; 1165 break; 1166 case 2: 1167 line_length = ( glyph_width + 3 ) >> 2; 1168 break; 1169 case 4: 1170 line_length = ( glyph_width + 1 ) >> 1; 1171 break; 1172 default: 1173 line_length = glyph_width; 1174 } 1175 1176 glyph_size = glyph_height * line_length; 1177 pad_bytes = 1; 1178 } 1179 break; 1180 1181 case 2: 1182 case 5: 1183 case 7: 1184 line_bits = glyph_width * pix_bits; 1185 glyph_size = ( glyph_height * line_bits + 7 ) >> 3; 1186 break; 1187 1188 default: /* invalid format */ 1189 return SFNT_Err_Invalid_File_Format; 1190 } 1191 1192 /* Now read data and draw glyph into target pixmap */ 1193 if ( FT_FRAME_ENTER( glyph_size ) ) 1194 goto Exit; 1195 1196 /* don't forget to multiply `x_offset' by `map->pix_bits' as */ 1197 /* the sbit blitter doesn't make a difference between pixmap */ 1198 /* depths. */ 1199 blit_sbit( map, (FT_Byte*)stream->cursor, line_bits, pad_bytes, 1200 x_offset * pix_bits, y_offset ); 1201 1202 FT_FRAME_EXIT(); 1203 } 1204 1205 Exit: 1206 return error; 1207 } 1208 1209 1210 static FT_Error 1211 Load_SBit_Image( TT_SBit_Strike strike, 1212 TT_SBit_Range range, 1213 FT_ULong ebdt_pos, 1214 FT_ULong glyph_offset, 1215 FT_Bitmap* map, 1216 FT_Int x_offset, 1217 FT_Int y_offset, 1218 FT_Stream stream, 1219 TT_SBit_Metrics metrics ) 1220 { 1221 FT_Memory memory = stream->memory; 1222 FT_Error error; 1223 1224 1225 /* place stream at beginning of glyph data and read metrics */ 1226 if ( FT_STREAM_SEEK( ebdt_pos + glyph_offset ) ) 1227 goto Exit; 1228 1229 error = load_sbit_metrics( stream, range, metrics ); 1230 if ( error ) 1231 goto Exit; 1232 1233 /* this function is recursive. At the top-level call, the */ 1234 /* field map.buffer is NULL. We thus begin by finding the */ 1235 /* dimensions of the higher-level glyph to allocate the */ 1236 /* final pixmap buffer */ 1237 if ( map->buffer == 0 ) 1238 { 1239 FT_Long size; 1240 1241 1242 map->width = metrics->width; 1243 map->rows = metrics->height; 1244 1245 switch ( strike->bit_depth ) 1246 { 1247 case 1: 1248 map->pixel_mode = FT_PIXEL_MODE_MONO; 1249 map->pitch = ( map->width + 7 ) >> 3; 1250 break; 1251 1252 case 2: 1253 map->pixel_mode = FT_PIXEL_MODE_GRAY2; 1254 map->pitch = ( map->width + 3 ) >> 2; 1255 break; 1256 1257 case 4: 1258 map->pixel_mode = FT_PIXEL_MODE_GRAY4; 1259 map->pitch = ( map->width + 1 ) >> 1; 1260 break; 1261 1262 case 8: 1263 map->pixel_mode = FT_PIXEL_MODE_GRAY; 1264 map->pitch = map->width; 1265 break; 1266 1267 default: 1268 return SFNT_Err_Invalid_File_Format; 1269 } 1270 1271 size = map->rows * map->pitch; 1272 1273 /* check that there is no empty image */ 1274 if ( size == 0 ) 1275 goto Exit; /* exit successfully! */ 1276 1277 if ( FT_ALLOC( map->buffer, size ) ) 1278 goto Exit; 1279 } 1280 1281 switch ( range->image_format ) 1282 { 1283 case 1: /* single sbit image - load it */ 1284 case 2: 1285 case 5: 1286 case 6: 1287 case 7: 1288 return Load_SBit_Single( map, x_offset, y_offset, strike->bit_depth, 1289 range->image_format, metrics, stream ); 1290 1291 case 8: /* compound format */ 1292 FT_Stream_Skip( stream, 1L ); 1293 /* fallthrough */ 1294 1295 case 9: 1296 break; 1297 1298 default: /* invalid image format */ 1299 return SFNT_Err_Invalid_File_Format; 1300 } 1301 1302 /* All right, we have a compound format. First of all, read */ 1303 /* the array of elements. */ 1304 { 1305 TT_SBit_Component components; 1306 TT_SBit_Component comp; 1307 FT_UShort num_components, count; 1308 1309 1310 if ( FT_READ_USHORT( num_components ) || 1311 FT_NEW_ARRAY( components, num_components ) ) 1312 goto Exit; 1313 1314 count = num_components; 1315 1316 if ( FT_FRAME_ENTER( 4L * num_components ) ) 1317 goto Fail_Memory; 1318 1319 for ( comp = components; count > 0; count--, comp++ ) 1320 { 1321 comp->glyph_code = FT_GET_USHORT(); 1322 comp->x_offset = FT_GET_CHAR(); 1323 comp->y_offset = FT_GET_CHAR(); 1324 } 1325 1326 FT_FRAME_EXIT(); 1327 1328 /* Now recursively load each element glyph */ 1329 count = num_components; 1330 comp = components; 1331 for ( ; count > 0; count--, comp++ ) 1332 { 1333 TT_SBit_Range elem_range; 1334 TT_SBit_MetricsRec elem_metrics; 1335 FT_ULong elem_offset; 1336 1337 1338 /* find the range for this element */ 1339 error = find_sbit_range( comp->glyph_code, 1340 strike, 1341 &elem_range, 1342 &elem_offset ); 1343 if ( error ) 1344 goto Fail_Memory; 1345 1346 /* now load the element, recursively */ 1347 error = Load_SBit_Image( strike, 1348 elem_range, 1349 ebdt_pos, 1350 elem_offset, 1351 map, 1352 x_offset + comp->x_offset, 1353 y_offset + comp->y_offset, 1354 stream, 1355 &elem_metrics ); 1356 if ( error ) 1357 goto Fail_Memory; 1358 } 1359 1360 Fail_Memory: 1361 FT_FREE( components ); 1362 } 1363 1364 Exit: 1365 return error; 1366 } 1367 1368 1369 /*************************************************************************/ 1370 /* */ 1371 /* <Function> */ 1372 /* tt_face_load_sbit_image */ 1373 /* */ 1374 /* <Description> */ 1375 /* Loads a given glyph sbit image from the font resource. This also */ 1376 /* returns its metrics. */ 1377 /* */ 1378 /* <Input> */ 1379 /* face :: The target face object. */ 1380 /* */ 1381 /* strike_index :: The current strike index. */ 1382 /* */ 1383 /* glyph_index :: The current glyph index. */ 1384 /* */ 1385 /* load_flags :: The glyph load flags (the code checks for the flag */ 1386 /* FT_LOAD_CROP_BITMAP). */ 1387 /* */ 1388 /* stream :: The input stream. */ 1389 /* */ 1390 /* <Output> */ 1391 /* map :: The target pixmap. */ 1392 /* */ 1393 /* metrics :: A big sbit metrics structure for the glyph image. */ 1394 /* */ 1395 /* <Return> */ 1396 /* FreeType error code. 0 means success. Returns an error if no */ 1397 /* glyph sbit exists for the index. */ 1398 /* */ 1399 /* <Note> */ 1400 /* The `map.buffer' field is always freed before the glyph is loaded. */ 1401 /* */ 1402 FT_LOCAL_DEF( FT_Error ) 1403 tt_face_load_sbit_image( TT_Face face, 1404 FT_ULong strike_index, 1405 FT_UInt glyph_index, 1406 FT_UInt load_flags, 1407 FT_Stream stream, 1408 FT_Bitmap *map, 1409 TT_SBit_MetricsRec *metrics ) 1410 { 1411 FT_Error error; 1412 FT_Memory memory = stream->memory; 1413 FT_ULong ebdt_pos, glyph_offset; 1414 1415 TT_SBit_Strike strike; 1416 TT_SBit_Range range; 1417 1418 1419 /* Check whether there is a glyph sbit for the current index */ 1420 error = find_sbit_image( face, glyph_index, strike_index, 1421 &range, &strike, &glyph_offset ); 1422 if ( error ) 1423 goto Exit; 1424 1425 /* now, find the location of the `EBDT' table in */ 1426 /* the font file */ 1427 error = face->goto_table( face, TTAG_EBDT, stream, 0 ); 1428 if ( error ) 1429 error = face->goto_table( face, TTAG_bdat, stream, 0 ); 1430 if (error) 1431 goto Exit; 1432 1433 ebdt_pos = FT_STREAM_POS(); 1434 1435 /* clear the bitmap & load the bitmap */ 1436 if ( face->root.glyph->flags & FT_GLYPH_OWN_BITMAP ) 1437 FT_FREE( map->buffer ); 1438 1439 map->rows = map->pitch = map->width = 0; 1440 1441 error = Load_SBit_Image( strike, range, ebdt_pos, glyph_offset, 1442 map, 0, 0, stream, metrics ); 1443 if ( error ) 1444 goto Exit; 1445 1446 /* the glyph slot owns this bitmap buffer */ 1447 face->root.glyph->flags |= FT_GLYPH_OWN_BITMAP; 1448 1449 /* setup vertical metrics if needed */ 1450 if ( strike->flags & 1 ) 1451 { 1452 /* in case of a horizontal strike only */ 1453 FT_Int advance; 1454 1455 1456 advance = strike->hori.ascender - strike->hori.descender; 1457 1458 /* some heuristic values */ 1459 1460 metrics->vertBearingX = (FT_Char)(-metrics->width / 2 ); 1461 metrics->vertBearingY = (FT_Char)( advance / 10 ); 1462 metrics->vertAdvance = (FT_Char)( advance * 12 / 10 ); 1463 } 1464 1465 /* Crop the bitmap now, unless specified otherwise */ 1466 if ( load_flags & FT_LOAD_CROP_BITMAP ) 1467 crop_bitmap( map, metrics ); 1468 1469 Exit: 1470 return error; 1471 } 1472 1473 1474 /* END */ 1475