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