1 /***************************************************************************/ 2 /* */ 3 /* ftbitmap.c */ 4 /* */ 5 /* FreeType utility functions for bitmaps (body). */ 6 /* */ 7 /* Copyright 2004-2009, 2011, 2013, 2014 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 22 #include FT_BITMAP_H 23 #include FT_IMAGE_H 24 #include FT_INTERNAL_OBJECTS_H 25 26 27 static 28 const FT_Bitmap null_bitmap = { 0, 0, 0, 0, 0, 0, 0, 0 }; 29 30 31 /* documentation is in ftbitmap.h */ 32 33 FT_EXPORT_DEF( void ) FT_Bitmap_New(FT_Bitmap * abitmap)34 FT_Bitmap_New( FT_Bitmap *abitmap ) 35 { 36 if ( abitmap ) 37 *abitmap = null_bitmap; 38 } 39 40 41 /* documentation is in ftbitmap.h */ 42 43 FT_EXPORT_DEF( FT_Error ) FT_Bitmap_Copy(FT_Library library,const FT_Bitmap * source,FT_Bitmap * target)44 FT_Bitmap_Copy( FT_Library library, 45 const FT_Bitmap *source, 46 FT_Bitmap *target) 47 { 48 FT_Memory memory; 49 FT_Error error = FT_Err_Ok; 50 51 FT_Int pitch; 52 FT_ULong size; 53 54 FT_Int source_pitch_sign, target_pitch_sign; 55 56 57 if ( !library ) 58 return FT_THROW( Invalid_Library_Handle ); 59 60 if ( !source || !target ) 61 return FT_THROW( Invalid_Argument ); 62 63 if ( source == target ) 64 return FT_Err_Ok; 65 66 source_pitch_sign = source->pitch < 0 ? -1 : 1; 67 target_pitch_sign = target->pitch < 0 ? -1 : 1; 68 69 if ( source->buffer == NULL ) 70 { 71 *target = *source; 72 if ( source_pitch_sign != target_pitch_sign ) 73 target->pitch = -target->pitch; 74 75 return FT_Err_Ok; 76 } 77 78 memory = library->memory; 79 pitch = source->pitch; 80 81 if ( pitch < 0 ) 82 pitch = -pitch; 83 size = (FT_ULong)pitch * source->rows; 84 85 if ( target->buffer ) 86 { 87 FT_Int target_pitch = target->pitch; 88 FT_ULong target_size; 89 90 91 if ( target_pitch < 0 ) 92 target_pitch = -target_pitch; 93 target_size = (FT_ULong)target_pitch * target->rows; 94 95 if ( target_size != size ) 96 (void)FT_QREALLOC( target->buffer, target_size, size ); 97 } 98 else 99 (void)FT_QALLOC( target->buffer, size ); 100 101 if ( !error ) 102 { 103 unsigned char *p; 104 105 106 p = target->buffer; 107 *target = *source; 108 target->buffer = p; 109 110 if ( source_pitch_sign == target_pitch_sign ) 111 FT_MEM_COPY( target->buffer, source->buffer, size ); 112 else 113 { 114 /* take care of bitmap flow */ 115 FT_UInt i; 116 FT_Byte* s = source->buffer; 117 FT_Byte* t = target->buffer; 118 119 120 t += pitch * ( target->rows - 1 ); 121 122 for ( i = target->rows; i > 0; i-- ) 123 { 124 FT_ARRAY_COPY( t, s, pitch ); 125 126 s += pitch; 127 t -= pitch; 128 } 129 } 130 } 131 132 return error; 133 } 134 135 136 /* Enlarge `bitmap' horizontally and vertically by `xpixels' */ 137 /* and `ypixels', respectively. */ 138 139 static FT_Error ft_bitmap_assure_buffer(FT_Memory memory,FT_Bitmap * bitmap,FT_UInt xpixels,FT_UInt ypixels)140 ft_bitmap_assure_buffer( FT_Memory memory, 141 FT_Bitmap* bitmap, 142 FT_UInt xpixels, 143 FT_UInt ypixels ) 144 { 145 FT_Error error; 146 int pitch; 147 int new_pitch; 148 FT_UInt bpp; 149 FT_UInt i, width, height; 150 unsigned char* buffer = NULL; 151 152 153 width = bitmap->width; 154 height = bitmap->rows; 155 pitch = bitmap->pitch; 156 if ( pitch < 0 ) 157 pitch = -pitch; 158 159 switch ( bitmap->pixel_mode ) 160 { 161 case FT_PIXEL_MODE_MONO: 162 bpp = 1; 163 new_pitch = ( width + xpixels + 7 ) >> 3; 164 break; 165 case FT_PIXEL_MODE_GRAY2: 166 bpp = 2; 167 new_pitch = ( width + xpixels + 3 ) >> 2; 168 break; 169 case FT_PIXEL_MODE_GRAY4: 170 bpp = 4; 171 new_pitch = ( width + xpixels + 1 ) >> 1; 172 break; 173 case FT_PIXEL_MODE_GRAY: 174 case FT_PIXEL_MODE_LCD: 175 case FT_PIXEL_MODE_LCD_V: 176 bpp = 8; 177 new_pitch = ( width + xpixels ); 178 break; 179 default: 180 return FT_THROW( Invalid_Glyph_Format ); 181 } 182 183 /* if no need to allocate memory */ 184 if ( ypixels == 0 && new_pitch <= pitch ) 185 { 186 /* zero the padding */ 187 FT_UInt bit_width = pitch * 8; 188 FT_UInt bit_last = ( width + xpixels ) * bpp; 189 190 191 if ( bit_last < bit_width ) 192 { 193 FT_Byte* line = bitmap->buffer + ( bit_last >> 3 ); 194 FT_Byte* end = bitmap->buffer + pitch; 195 FT_UInt shift = bit_last & 7; 196 FT_UInt mask = 0xFF00U >> shift; 197 FT_UInt count = height; 198 199 200 for ( ; count > 0; count--, line += pitch, end += pitch ) 201 { 202 FT_Byte* write = line; 203 204 205 if ( shift > 0 ) 206 { 207 write[0] = (FT_Byte)( write[0] & mask ); 208 write++; 209 } 210 if ( write < end ) 211 FT_MEM_ZERO( write, end - write ); 212 } 213 } 214 215 return FT_Err_Ok; 216 } 217 218 /* otherwise allocate new buffer */ 219 if ( FT_QALLOC_MULT( buffer, new_pitch, bitmap->rows + ypixels ) ) 220 return error; 221 222 /* new rows get added at the top of the bitmap, */ 223 /* thus take care of the flow direction */ 224 if ( bitmap->pitch > 0 ) 225 { 226 FT_UInt len = ( width * bpp + 7 ) >> 3; 227 228 229 for ( i = 0; i < bitmap->rows; i++ ) 230 FT_MEM_COPY( buffer + new_pitch * ( ypixels + i ), 231 bitmap->buffer + pitch * i, len ); 232 } 233 else 234 { 235 FT_UInt len = ( width * bpp + 7 ) >> 3; 236 237 238 for ( i = 0; i < bitmap->rows; i++ ) 239 FT_MEM_COPY( buffer + new_pitch * i, 240 bitmap->buffer + pitch * i, len ); 241 } 242 243 FT_FREE( bitmap->buffer ); 244 bitmap->buffer = buffer; 245 246 if ( bitmap->pitch < 0 ) 247 new_pitch = -new_pitch; 248 249 /* set pitch only, width and height are left untouched */ 250 bitmap->pitch = new_pitch; 251 252 return FT_Err_Ok; 253 } 254 255 256 /* documentation is in ftbitmap.h */ 257 258 FT_EXPORT_DEF( FT_Error ) FT_Bitmap_Embolden(FT_Library library,FT_Bitmap * bitmap,FT_Pos xStrength,FT_Pos yStrength)259 FT_Bitmap_Embolden( FT_Library library, 260 FT_Bitmap* bitmap, 261 FT_Pos xStrength, 262 FT_Pos yStrength ) 263 { 264 FT_Error error; 265 unsigned char* p; 266 FT_Int i, x, pitch; 267 FT_UInt y; 268 FT_Int xstr, ystr; 269 270 271 if ( !library ) 272 return FT_THROW( Invalid_Library_Handle ); 273 274 if ( !bitmap || !bitmap->buffer ) 275 return FT_THROW( Invalid_Argument ); 276 277 if ( ( ( FT_PIX_ROUND( xStrength ) >> 6 ) > FT_INT_MAX ) || 278 ( ( FT_PIX_ROUND( yStrength ) >> 6 ) > FT_INT_MAX ) ) 279 return FT_THROW( Invalid_Argument ); 280 281 xstr = (FT_Int)FT_PIX_ROUND( xStrength ) >> 6; 282 ystr = (FT_Int)FT_PIX_ROUND( yStrength ) >> 6; 283 284 if ( xstr == 0 && ystr == 0 ) 285 return FT_Err_Ok; 286 else if ( xstr < 0 || ystr < 0 ) 287 return FT_THROW( Invalid_Argument ); 288 289 switch ( bitmap->pixel_mode ) 290 { 291 case FT_PIXEL_MODE_GRAY2: 292 case FT_PIXEL_MODE_GRAY4: 293 { 294 FT_Bitmap tmp; 295 296 297 /* convert to 8bpp */ 298 FT_Bitmap_New( &tmp ); 299 error = FT_Bitmap_Convert( library, bitmap, &tmp, 1 ); 300 if ( error ) 301 return error; 302 303 FT_Bitmap_Done( library, bitmap ); 304 *bitmap = tmp; 305 } 306 break; 307 308 case FT_PIXEL_MODE_MONO: 309 if ( xstr > 8 ) 310 xstr = 8; 311 break; 312 313 case FT_PIXEL_MODE_LCD: 314 xstr *= 3; 315 break; 316 317 case FT_PIXEL_MODE_LCD_V: 318 ystr *= 3; 319 break; 320 321 case FT_PIXEL_MODE_BGRA: 322 /* We don't embolden color glyphs. */ 323 return FT_Err_Ok; 324 } 325 326 error = ft_bitmap_assure_buffer( library->memory, bitmap, xstr, ystr ); 327 if ( error ) 328 return error; 329 330 /* take care of bitmap flow */ 331 pitch = bitmap->pitch; 332 if ( pitch > 0 ) 333 p = bitmap->buffer + pitch * ystr; 334 else 335 { 336 pitch = -pitch; 337 p = bitmap->buffer + pitch * ( bitmap->rows - 1 ); 338 } 339 340 /* for each row */ 341 for ( y = 0; y < bitmap->rows ; y++ ) 342 { 343 /* 344 * Horizontally: 345 * 346 * From the last pixel on, make each pixel or'ed with the 347 * `xstr' pixels before it. 348 */ 349 for ( x = pitch - 1; x >= 0; x-- ) 350 { 351 unsigned char tmp; 352 353 354 tmp = p[x]; 355 for ( i = 1; i <= xstr; i++ ) 356 { 357 if ( bitmap->pixel_mode == FT_PIXEL_MODE_MONO ) 358 { 359 p[x] |= tmp >> i; 360 361 /* the maximum value of 8 for `xstr' comes from here */ 362 if ( x > 0 ) 363 p[x] |= p[x - 1] << ( 8 - i ); 364 365 #if 0 366 if ( p[x] == 0xFF ) 367 break; 368 #endif 369 } 370 else 371 { 372 if ( x - i >= 0 ) 373 { 374 if ( p[x] + p[x - i] > bitmap->num_grays - 1 ) 375 { 376 p[x] = (unsigned char)( bitmap->num_grays - 1 ); 377 break; 378 } 379 else 380 { 381 p[x] = (unsigned char)( p[x] + p[x - i] ); 382 if ( p[x] == bitmap->num_grays - 1 ) 383 break; 384 } 385 } 386 else 387 break; 388 } 389 } 390 } 391 392 /* 393 * Vertically: 394 * 395 * Make the above `ystr' rows or'ed with it. 396 */ 397 for ( x = 1; x <= ystr; x++ ) 398 { 399 unsigned char* q; 400 401 402 q = p - bitmap->pitch * x; 403 for ( i = 0; i < pitch; i++ ) 404 q[i] |= p[i]; 405 } 406 407 p += bitmap->pitch; 408 } 409 410 bitmap->width += xstr; 411 bitmap->rows += ystr; 412 413 return FT_Err_Ok; 414 } 415 416 417 static FT_Byte ft_gray_for_premultiplied_srgb_bgra(const FT_Byte * bgra)418 ft_gray_for_premultiplied_srgb_bgra( const FT_Byte* bgra ) 419 { 420 FT_UInt a = bgra[3]; 421 FT_UInt l; 422 423 424 /* Short-circuit transparent color to avoid division by zero. */ 425 if ( !a ) 426 return 0; 427 428 /* 429 * Luminosity for sRGB is defined using ~0.2126,0.7152,0.0722 430 * coefficients for RGB channels *on the linear colors*. 431 * A gamma of 2.2 is fair to assume. And then, we need to 432 * undo the premultiplication too. 433 * 434 * http://accessibility.kde.org/hsl-adjusted.php 435 * 436 * We do the computation with integers only, applying a gamma of 2.0. 437 * We guarantee 32-bit arithmetic to avoid overflow but the resulting 438 * luminosity fits into 16 bits. 439 * 440 */ 441 442 l = ( 4732UL /* 0.0722 * 65536 */ * bgra[0] * bgra[0] + 443 46871UL /* 0.7152 * 65536 */ * bgra[1] * bgra[1] + 444 13933UL /* 0.2126 * 65536 */ * bgra[2] * bgra[2] ) >> 16; 445 446 /* 447 * Final transparency can be determined as follows. 448 * 449 * - If alpha is zero, we want 0. 450 * - If alpha is zero and luminosity is zero, we want 255. 451 * - If alpha is zero and luminosity is one, we want 0. 452 * 453 * So the formula is a * (1 - l) = a - l * a. 454 * 455 * We still need to undo premultiplication by dividing l by a*a. 456 * 457 */ 458 459 return (FT_Byte)( a - l / a ); 460 } 461 462 463 /* documentation is in ftbitmap.h */ 464 465 FT_EXPORT_DEF( FT_Error ) FT_Bitmap_Convert(FT_Library library,const FT_Bitmap * source,FT_Bitmap * target,FT_Int alignment)466 FT_Bitmap_Convert( FT_Library library, 467 const FT_Bitmap *source, 468 FT_Bitmap *target, 469 FT_Int alignment ) 470 { 471 FT_Error error = FT_Err_Ok; 472 FT_Memory memory; 473 474 FT_Byte* s; 475 FT_Byte* t; 476 477 478 if ( !library ) 479 return FT_THROW( Invalid_Library_Handle ); 480 481 if ( !source || !target ) 482 return FT_THROW( Invalid_Argument ); 483 484 memory = library->memory; 485 486 switch ( source->pixel_mode ) 487 { 488 case FT_PIXEL_MODE_MONO: 489 case FT_PIXEL_MODE_GRAY: 490 case FT_PIXEL_MODE_GRAY2: 491 case FT_PIXEL_MODE_GRAY4: 492 case FT_PIXEL_MODE_LCD: 493 case FT_PIXEL_MODE_LCD_V: 494 case FT_PIXEL_MODE_BGRA: 495 { 496 FT_Int pad, old_target_pitch, target_pitch; 497 FT_ULong old_size; 498 499 500 old_target_pitch = target->pitch; 501 if ( old_target_pitch < 0 ) 502 old_target_pitch = -old_target_pitch; 503 504 old_size = target->rows * old_target_pitch; 505 506 target->pixel_mode = FT_PIXEL_MODE_GRAY; 507 target->rows = source->rows; 508 target->width = source->width; 509 510 pad = 0; 511 if ( alignment > 0 ) 512 { 513 pad = source->width % alignment; 514 if ( pad != 0 ) 515 pad = alignment - pad; 516 } 517 518 target_pitch = source->width + pad; 519 520 if ( target_pitch > 0 && 521 (FT_ULong)target->rows > FT_ULONG_MAX / target_pitch ) 522 return FT_THROW( Invalid_Argument ); 523 524 if ( target->rows * target_pitch > old_size && 525 FT_QREALLOC( target->buffer, 526 old_size, target->rows * target_pitch ) ) 527 return error; 528 529 target->pitch = target->pitch < 0 ? -target_pitch : target_pitch; 530 } 531 break; 532 533 default: 534 error = FT_THROW( Invalid_Argument ); 535 } 536 537 s = source->buffer; 538 t = target->buffer; 539 540 /* take care of bitmap flow */ 541 if ( source->pitch < 0 ) 542 s -= source->pitch * ( source->rows - 1 ); 543 if ( target->pitch < 0 ) 544 t -= target->pitch * ( target->rows - 1 ); 545 546 switch ( source->pixel_mode ) 547 { 548 case FT_PIXEL_MODE_MONO: 549 { 550 FT_UInt i; 551 552 553 target->num_grays = 2; 554 555 for ( i = source->rows; i > 0; i-- ) 556 { 557 FT_Byte* ss = s; 558 FT_Byte* tt = t; 559 FT_UInt j; 560 561 562 /* get the full bytes */ 563 for ( j = source->width >> 3; j > 0; j-- ) 564 { 565 FT_Int val = ss[0]; /* avoid a byte->int cast on each line */ 566 567 568 tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7 ); 569 tt[1] = (FT_Byte)( ( val & 0x40 ) >> 6 ); 570 tt[2] = (FT_Byte)( ( val & 0x20 ) >> 5 ); 571 tt[3] = (FT_Byte)( ( val & 0x10 ) >> 4 ); 572 tt[4] = (FT_Byte)( ( val & 0x08 ) >> 3 ); 573 tt[5] = (FT_Byte)( ( val & 0x04 ) >> 2 ); 574 tt[6] = (FT_Byte)( ( val & 0x02 ) >> 1 ); 575 tt[7] = (FT_Byte)( val & 0x01 ); 576 577 tt += 8; 578 ss += 1; 579 } 580 581 /* get remaining pixels (if any) */ 582 j = source->width & 7; 583 if ( j > 0 ) 584 { 585 FT_Int val = *ss; 586 587 588 for ( ; j > 0; j-- ) 589 { 590 tt[0] = (FT_Byte)( ( val & 0x80 ) >> 7); 591 val <<= 1; 592 tt += 1; 593 } 594 } 595 596 s += source->pitch; 597 t += target->pitch; 598 } 599 } 600 break; 601 602 603 case FT_PIXEL_MODE_GRAY: 604 case FT_PIXEL_MODE_LCD: 605 case FT_PIXEL_MODE_LCD_V: 606 { 607 FT_Int width = source->width; 608 FT_UInt i; 609 610 611 target->num_grays = 256; 612 613 for ( i = source->rows; i > 0; i-- ) 614 { 615 FT_ARRAY_COPY( t, s, width ); 616 617 s += source->pitch; 618 t += target->pitch; 619 } 620 } 621 break; 622 623 624 case FT_PIXEL_MODE_GRAY2: 625 { 626 FT_UInt i; 627 628 629 target->num_grays = 4; 630 631 for ( i = source->rows; i > 0; i-- ) 632 { 633 FT_Byte* ss = s; 634 FT_Byte* tt = t; 635 FT_UInt j; 636 637 638 /* get the full bytes */ 639 for ( j = source->width >> 2; j > 0; j-- ) 640 { 641 FT_Int val = ss[0]; 642 643 644 tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 ); 645 tt[1] = (FT_Byte)( ( val & 0x30 ) >> 4 ); 646 tt[2] = (FT_Byte)( ( val & 0x0C ) >> 2 ); 647 tt[3] = (FT_Byte)( ( val & 0x03 ) ); 648 649 ss += 1; 650 tt += 4; 651 } 652 653 j = source->width & 3; 654 if ( j > 0 ) 655 { 656 FT_Int val = ss[0]; 657 658 659 for ( ; j > 0; j-- ) 660 { 661 tt[0] = (FT_Byte)( ( val & 0xC0 ) >> 6 ); 662 val <<= 2; 663 tt += 1; 664 } 665 } 666 667 s += source->pitch; 668 t += target->pitch; 669 } 670 } 671 break; 672 673 674 case FT_PIXEL_MODE_GRAY4: 675 { 676 FT_UInt i; 677 678 679 target->num_grays = 16; 680 681 for ( i = source->rows; i > 0; i-- ) 682 { 683 FT_Byte* ss = s; 684 FT_Byte* tt = t; 685 FT_UInt j; 686 687 688 /* get the full bytes */ 689 for ( j = source->width >> 1; j > 0; j-- ) 690 { 691 FT_Int val = ss[0]; 692 693 694 tt[0] = (FT_Byte)( ( val & 0xF0 ) >> 4 ); 695 tt[1] = (FT_Byte)( ( val & 0x0F ) ); 696 697 ss += 1; 698 tt += 2; 699 } 700 701 if ( source->width & 1 ) 702 tt[0] = (FT_Byte)( ( ss[0] & 0xF0 ) >> 4 ); 703 704 s += source->pitch; 705 t += target->pitch; 706 } 707 } 708 break; 709 710 711 case FT_PIXEL_MODE_BGRA: 712 { 713 FT_UInt i; 714 715 716 target->num_grays = 256; 717 718 for ( i = source->rows; i > 0; i-- ) 719 { 720 FT_Byte* ss = s; 721 FT_Byte* tt = t; 722 FT_UInt j; 723 724 725 for ( j = source->width; j > 0; j-- ) 726 { 727 tt[0] = ft_gray_for_premultiplied_srgb_bgra( ss ); 728 729 ss += 4; 730 tt += 1; 731 } 732 733 s += source->pitch; 734 t += target->pitch; 735 } 736 } 737 break; 738 739 default: 740 ; 741 } 742 743 return error; 744 } 745 746 747 /* documentation is in ftbitmap.h */ 748 749 FT_EXPORT_DEF( FT_Error ) FT_GlyphSlot_Own_Bitmap(FT_GlyphSlot slot)750 FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot slot ) 751 { 752 if ( slot && slot->format == FT_GLYPH_FORMAT_BITMAP && 753 !( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) ) 754 { 755 FT_Bitmap bitmap; 756 FT_Error error; 757 758 759 FT_Bitmap_New( &bitmap ); 760 error = FT_Bitmap_Copy( slot->library, &slot->bitmap, &bitmap ); 761 if ( error ) 762 return error; 763 764 slot->bitmap = bitmap; 765 slot->internal->flags |= FT_GLYPH_OWN_BITMAP; 766 } 767 768 return FT_Err_Ok; 769 } 770 771 772 /* documentation is in ftbitmap.h */ 773 774 FT_EXPORT_DEF( FT_Error ) FT_Bitmap_Done(FT_Library library,FT_Bitmap * bitmap)775 FT_Bitmap_Done( FT_Library library, 776 FT_Bitmap *bitmap ) 777 { 778 FT_Memory memory; 779 780 781 if ( !library ) 782 return FT_THROW( Invalid_Library_Handle ); 783 784 if ( !bitmap ) 785 return FT_THROW( Invalid_Argument ); 786 787 memory = library->memory; 788 789 FT_FREE( bitmap->buffer ); 790 *bitmap = null_bitmap; 791 792 return FT_Err_Ok; 793 } 794 795 796 /* END */ 797