| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2008 The Android Open Source Project | 3 * Copyright 2008 The Android Open Source Project |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 | 9 |
| 10 #include "SkBitmap.h" | 10 #include "SkBitmap.h" |
| (...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 423 } | 423 } |
| 424 | 424 |
| 425 dst->setPixelRef(pr)->unref(); | 425 dst->setPixelRef(pr)->unref(); |
| 426 // since we're already allocated, we lockPixels right away | 426 // since we're already allocated, we lockPixels right away |
| 427 dst->lockPixels(); | 427 dst->lockPixels(); |
| 428 return true; | 428 return true; |
| 429 } | 429 } |
| 430 | 430 |
| 431 /////////////////////////////////////////////////////////////////////////////// | 431 /////////////////////////////////////////////////////////////////////////////// |
| 432 | 432 |
| 433 bool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize, | 433 static bool copy_pixels_to(const SkPixmap& pmap, void* const dst, size_t dstSize
, |
| 434 size_t dstRowBytes, bool preserveDstPad) const { | 434 size_t dstRowBytes, bool preserveDstPad) { |
| 435 const SkImageInfo& info = pmap.info(); |
| 435 | 436 |
| 436 if (0 == dstRowBytes) { | 437 if (0 == dstRowBytes) { |
| 437 dstRowBytes = fRowBytes; | 438 dstRowBytes = pmap.rowBytes(); |
| 438 } | 439 } |
| 439 | 440 if (dstRowBytes < info.minRowBytes()) { |
| 440 if (dstRowBytes < fInfo.minRowBytes() || | |
| 441 dst == NULL || (getPixels() == NULL && pixelRef() == NULL)) { | |
| 442 return false; | 441 return false; |
| 443 } | 442 } |
| 444 | 443 |
| 445 if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == fRowBytes) { | 444 if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == pmap.rowBytes()
) { |
| 446 size_t safeSize = this->getSafeSize(); | 445 size_t safeSize = pmap.getSafeSize(); |
| 447 if (safeSize > dstSize || safeSize == 0) | 446 if (safeSize > dstSize || safeSize == 0) |
| 448 return false; | 447 return false; |
| 449 else { | 448 else { |
| 450 SkAutoLockPixels lock(*this); | |
| 451 // This implementation will write bytes beyond the end of each row, | 449 // This implementation will write bytes beyond the end of each row, |
| 452 // excluding the last row, if the bitmap's stride is greater than | 450 // excluding the last row, if the bitmap's stride is greater than |
| 453 // strictly required by the current config. | 451 // strictly required by the current config. |
| 454 memcpy(dst, getPixels(), safeSize); | 452 memcpy(dst, pmap.addr(), safeSize); |
| 455 | |
| 456 return true; | 453 return true; |
| 457 } | 454 } |
| 458 } else { | 455 } else { |
| 459 // If destination has different stride than us, then copy line by line. | 456 // If destination has different stride than us, then copy line by line. |
| 460 if (fInfo.getSafeSize(dstRowBytes) > dstSize) { | 457 if (info.getSafeSize(dstRowBytes) > dstSize) { |
| 461 return false; | 458 return false; |
| 462 } else { | 459 } else { |
| 463 // Just copy what we need on each line. | 460 // Just copy what we need on each line. |
| 464 size_t rowBytes = fInfo.minRowBytes(); | 461 size_t rowBytes = info.minRowBytes(); |
| 465 SkAutoLockPixels lock(*this); | 462 const uint8_t* srcP = reinterpret_cast<const uint8_t*>(pmap.addr()); |
| 466 const uint8_t* srcP = reinterpret_cast<const uint8_t*>(getPixels()); | |
| 467 uint8_t* dstP = reinterpret_cast<uint8_t*>(dst); | 463 uint8_t* dstP = reinterpret_cast<uint8_t*>(dst); |
| 468 for (int row = 0; row < fInfo.height(); row++, srcP += fRowBytes, ds
tP += dstRowBytes) { | 464 for (int row = 0; row < info.height(); ++row) { |
| 469 memcpy(dstP, srcP, rowBytes); | 465 memcpy(dstP, srcP, rowBytes); |
| 466 srcP += pmap.rowBytes(); |
| 467 dstP += dstRowBytes; |
| 470 } | 468 } |
| 471 | 469 |
| 472 return true; | 470 return true; |
| 473 } | 471 } |
| 474 } | 472 } |
| 475 } | 473 } |
| 476 | 474 |
| 475 bool SkBitmap::copyPixelsTo(void* dst, size_t dstSize, size_t dstRB, bool preser
veDstPad) const { |
| 476 if (NULL == dst) { |
| 477 return false; |
| 478 } |
| 479 SkAutoBitmapLockResult result; |
| 480 if (!this->requestLock(&result)) { |
| 481 return false; |
| 482 } |
| 483 return copy_pixels_to(result.pixmap(), dst, dstSize, dstRB, preserveDstPad); |
| 484 } |
| 485 |
| 477 /////////////////////////////////////////////////////////////////////////////// | 486 /////////////////////////////////////////////////////////////////////////////// |
| 478 | 487 |
| 479 bool SkBitmap::isImmutable() const { | 488 bool SkBitmap::isImmutable() const { |
| 480 return fPixelRef ? fPixelRef->isImmutable() : false; | 489 return fPixelRef ? fPixelRef->isImmutable() : false; |
| 481 } | 490 } |
| 482 | 491 |
| 483 void SkBitmap::setImmutable() { | 492 void SkBitmap::setImmutable() { |
| 484 if (fPixelRef) { | 493 if (fPixelRef) { |
| 485 fPixelRef->setImmutable(); | 494 fPixelRef->setImmutable(); |
| 486 } | 495 } |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 return SkUnPreMultiply::PMColorToColor(addr[0]); | 569 return SkUnPreMultiply::PMColorToColor(addr[0]); |
| 561 } | 570 } |
| 562 default: | 571 default: |
| 563 SkASSERT(false); | 572 SkASSERT(false); |
| 564 return 0; | 573 return 0; |
| 565 } | 574 } |
| 566 SkASSERT(false); // Not reached. | 575 SkASSERT(false); // Not reached. |
| 567 return 0; | 576 return 0; |
| 568 } | 577 } |
| 569 | 578 |
| 570 bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) { | 579 static bool compute_is_opaque(const SkPixmap& pmap) { |
| 571 SkAutoLockPixels alp(bm); | 580 const int height = pmap.height(); |
| 572 if (!bm.getPixels()) { | 581 const int width = pmap.width(); |
| 573 return false; | |
| 574 } | |
| 575 | 582 |
| 576 const int height = bm.height(); | 583 switch (pmap.colorType()) { |
| 577 const int width = bm.width(); | |
| 578 | |
| 579 switch (bm.colorType()) { | |
| 580 case kAlpha_8_SkColorType: { | 584 case kAlpha_8_SkColorType: { |
| 581 unsigned a = 0xFF; | 585 unsigned a = 0xFF; |
| 582 for (int y = 0; y < height; ++y) { | 586 for (int y = 0; y < height; ++y) { |
| 583 const uint8_t* row = bm.getAddr8(0, y); | 587 const uint8_t* row = pmap.addr8(0, y); |
| 584 for (int x = 0; x < width; ++x) { | 588 for (int x = 0; x < width; ++x) { |
| 585 a &= row[x]; | 589 a &= row[x]; |
| 586 } | 590 } |
| 587 if (0xFF != a) { | 591 if (0xFF != a) { |
| 588 return false; | 592 return false; |
| 589 } | 593 } |
| 590 } | 594 } |
| 591 return true; | 595 return true; |
| 592 } break; | 596 } break; |
| 593 case kIndex_8_SkColorType: { | 597 case kIndex_8_SkColorType: { |
| 594 if (!bm.getColorTable()) { | 598 const SkColorTable* ctable = pmap.ctable(); |
| 599 if (NULL == ctable) { |
| 595 return false; | 600 return false; |
| 596 } | 601 } |
| 597 const SkPMColor* table = bm.getColorTable()->readColors(); | 602 const SkPMColor* table = ctable->readColors(); |
| 598 SkPMColor c = (SkPMColor)~0; | 603 SkPMColor c = (SkPMColor)~0; |
| 599 for (int i = bm.getColorTable()->count() - 1; i >= 0; --i) { | 604 for (int i = ctable->count() - 1; i >= 0; --i) { |
| 600 c &= table[i]; | 605 c &= table[i]; |
| 601 } | 606 } |
| 602 return 0xFF == SkGetPackedA32(c); | 607 return 0xFF == SkGetPackedA32(c); |
| 603 } break; | 608 } break; |
| 604 case kRGB_565_SkColorType: | 609 case kRGB_565_SkColorType: |
| 605 case kGray_8_SkColorType: | 610 case kGray_8_SkColorType: |
| 606 return true; | 611 return true; |
| 607 break; | 612 break; |
| 608 case kARGB_4444_SkColorType: { | 613 case kARGB_4444_SkColorType: { |
| 609 unsigned c = 0xFFFF; | 614 unsigned c = 0xFFFF; |
| 610 for (int y = 0; y < height; ++y) { | 615 for (int y = 0; y < height; ++y) { |
| 611 const SkPMColor16* row = bm.getAddr16(0, y); | 616 const SkPMColor16* row = pmap.addr16(0, y); |
| 612 for (int x = 0; x < width; ++x) { | 617 for (int x = 0; x < width; ++x) { |
| 613 c &= row[x]; | 618 c &= row[x]; |
| 614 } | 619 } |
| 615 if (0xF != SkGetPackedA4444(c)) { | 620 if (0xF != SkGetPackedA4444(c)) { |
| 616 return false; | 621 return false; |
| 617 } | 622 } |
| 618 } | 623 } |
| 619 return true; | 624 return true; |
| 620 } break; | 625 } break; |
| 621 case kBGRA_8888_SkColorType: | 626 case kBGRA_8888_SkColorType: |
| 622 case kRGBA_8888_SkColorType: { | 627 case kRGBA_8888_SkColorType: { |
| 623 SkPMColor c = (SkPMColor)~0; | 628 SkPMColor c = (SkPMColor)~0; |
| 624 for (int y = 0; y < height; ++y) { | 629 for (int y = 0; y < height; ++y) { |
| 625 const SkPMColor* row = bm.getAddr32(0, y); | 630 const SkPMColor* row = pmap.addr32(0, y); |
| 626 for (int x = 0; x < width; ++x) { | 631 for (int x = 0; x < width; ++x) { |
| 627 c &= row[x]; | 632 c &= row[x]; |
| 628 } | 633 } |
| 629 if (0xFF != SkGetPackedA32(c)) { | 634 if (0xFF != SkGetPackedA32(c)) { |
| 630 return false; | 635 return false; |
| 631 } | 636 } |
| 632 } | 637 } |
| 633 return true; | 638 return true; |
| 634 } | 639 } |
| 635 default: | 640 default: |
| 636 break; | 641 break; |
| 637 } | 642 } |
| 638 return false; | 643 return false; |
| 639 } | 644 } |
| 640 | 645 |
| 646 bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) { |
| 647 SkAutoBitmapLockResult result; |
| 648 if (!bm.requestLock(&result)) { |
| 649 return false; |
| 650 } |
| 651 return compute_is_opaque(result.pixmap()); |
| 652 } |
| 653 |
| 641 | 654 |
| 642 /////////////////////////////////////////////////////////////////////////////// | 655 /////////////////////////////////////////////////////////////////////////////// |
| 643 /////////////////////////////////////////////////////////////////////////////// | 656 /////////////////////////////////////////////////////////////////////////////// |
| 644 | 657 |
| 645 static uint16_t pack_8888_to_4444(unsigned a, unsigned r, unsigned g, unsigned b
) { | 658 static uint16_t pack_8888_to_4444(unsigned a, unsigned r, unsigned g, unsigned b
) { |
| 646 unsigned pixel = (SkA32To4444(a) << SK_A4444_SHIFT) | | 659 unsigned pixel = (SkA32To4444(a) << SK_A4444_SHIFT) | |
| 647 (SkR32To4444(r) << SK_R4444_SHIFT) | | 660 (SkR32To4444(r) << SK_R4444_SHIFT) | |
| 648 (SkG32To4444(g) << SK_G4444_SHIFT) | | 661 (SkG32To4444(g) << SK_G4444_SHIFT) | |
| 649 (SkB32To4444(b) << SK_B4444_SHIFT); | 662 (SkB32To4444(b) << SK_B4444_SHIFT); |
| 650 return SkToU16(pixel); | 663 return SkToU16(pixel); |
| 651 } | 664 } |
| 652 | 665 |
| 653 void SkBitmap::internalErase(const SkIRect& area, | 666 static bool internal_erase(const SkPixmap& pmap, const SkIRect& area, |
| 654 U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { | 667 U8CPU a, U8CPU r, U8CPU g, U8CPU b) { |
| 655 #ifdef SK_DEBUG | |
| 656 SkDEBUGCODE(this->validate();) | |
| 657 SkASSERT(!area.isEmpty()); | |
| 658 { | |
| 659 SkIRect total = { 0, 0, this->width(), this->height() }; | |
| 660 SkASSERT(total.contains(area)); | |
| 661 } | |
| 662 #endif | |
| 663 | |
| 664 switch (fInfo.colorType()) { | |
| 665 case kUnknown_SkColorType: | |
| 666 case kIndex_8_SkColorType: | |
| 667 return; // can't erase. Should we bzero so the memory is not uniniti
alized? | |
| 668 default: | |
| 669 break; | |
| 670 } | |
| 671 | |
| 672 SkAutoLockPixels alp(*this); | |
| 673 // perform this check after the lock call | |
| 674 if (!this->readyToDraw()) { | |
| 675 return; | |
| 676 } | |
| 677 | |
| 678 int height = area.height(); | 668 int height = area.height(); |
| 679 const int width = area.width(); | 669 const int width = area.width(); |
| 680 const int rowBytes = fRowBytes; | 670 const int rowBytes = pmap.rowBytes(); |
| 681 | 671 |
| 682 switch (this->colorType()) { | 672 switch (pmap.colorType()) { |
| 683 case kGray_8_SkColorType: { | 673 case kGray_8_SkColorType: { |
| 684 if (255 != a) { | 674 if (255 != a) { |
| 685 r = SkMulDiv255Round(r, a); | 675 r = SkMulDiv255Round(r, a); |
| 686 g = SkMulDiv255Round(g, a); | 676 g = SkMulDiv255Round(g, a); |
| 687 b = SkMulDiv255Round(b, a); | 677 b = SkMulDiv255Round(b, a); |
| 688 } | 678 } |
| 689 int gray = SkComputeLuminance(r, g, b); | 679 int gray = SkComputeLuminance(r, g, b); |
| 690 uint8_t* p = this->getAddr8(area.fLeft, area.fTop); | 680 uint8_t* p = pmap.writable_addr8(area.fLeft, area.fTop); |
| 691 while (--height >= 0) { | 681 while (--height >= 0) { |
| 692 memset(p, gray, width); | 682 memset(p, gray, width); |
| 693 p += rowBytes; | 683 p += rowBytes; |
| 694 } | 684 } |
| 695 break; | 685 break; |
| 696 } | 686 } |
| 697 case kAlpha_8_SkColorType: { | 687 case kAlpha_8_SkColorType: { |
| 698 uint8_t* p = this->getAddr8(area.fLeft, area.fTop); | 688 uint8_t* p = pmap.writable_addr8(area.fLeft, area.fTop); |
| 699 while (--height >= 0) { | 689 while (--height >= 0) { |
| 700 memset(p, a, width); | 690 memset(p, a, width); |
| 701 p += rowBytes; | 691 p += rowBytes; |
| 702 } | 692 } |
| 703 break; | 693 break; |
| 704 } | 694 } |
| 705 case kARGB_4444_SkColorType: | 695 case kARGB_4444_SkColorType: |
| 706 case kRGB_565_SkColorType: { | 696 case kRGB_565_SkColorType: { |
| 707 uint16_t* p = this->getAddr16(area.fLeft, area.fTop); | 697 uint16_t* p = pmap.writable_addr16(area.fLeft, area.fTop); |
| 708 uint16_t v; | 698 uint16_t v; |
| 709 | 699 |
| 710 // make rgb premultiplied | 700 // make rgb premultiplied |
| 711 if (255 != a) { | 701 if (255 != a) { |
| 712 r = SkAlphaMul(r, a); | 702 r = SkAlphaMul(r, a); |
| 713 g = SkAlphaMul(g, a); | 703 g = SkAlphaMul(g, a); |
| 714 b = SkAlphaMul(b, a); | 704 b = SkAlphaMul(b, a); |
| 715 } | 705 } |
| 716 | 706 |
| 717 if (kARGB_4444_SkColorType == this->colorType()) { | 707 if (kARGB_4444_SkColorType == pmap.colorType()) { |
| 718 v = pack_8888_to_4444(a, r, g, b); | 708 v = pack_8888_to_4444(a, r, g, b); |
| 719 } else { | 709 } else { |
| 720 v = SkPackRGB16(r >> (8 - SK_R16_BITS), | 710 v = SkPackRGB16(r >> (8 - SK_R16_BITS), |
| 721 g >> (8 - SK_G16_BITS), | 711 g >> (8 - SK_G16_BITS), |
| 722 b >> (8 - SK_B16_BITS)); | 712 b >> (8 - SK_B16_BITS)); |
| 723 } | 713 } |
| 724 while (--height >= 0) { | 714 while (--height >= 0) { |
| 725 sk_memset16(p, v, width); | 715 sk_memset16(p, v, width); |
| 726 p = (uint16_t*)((char*)p + rowBytes); | 716 p = (uint16_t*)((char*)p + rowBytes); |
| 727 } | 717 } |
| 728 break; | 718 break; |
| 729 } | 719 } |
| 730 case kBGRA_8888_SkColorType: | 720 case kBGRA_8888_SkColorType: |
| 731 case kRGBA_8888_SkColorType: { | 721 case kRGBA_8888_SkColorType: { |
| 732 uint32_t* p = this->getAddr32(area.fLeft, area.fTop); | 722 uint32_t* p = pmap.writable_addr32(area.fLeft, area.fTop); |
| 733 | 723 |
| 734 if (255 != a && kPremul_SkAlphaType == this->alphaType()) { | 724 if (255 != a && kPremul_SkAlphaType == pmap.alphaType()) { |
| 735 r = SkAlphaMul(r, a); | 725 r = SkAlphaMul(r, a); |
| 736 g = SkAlphaMul(g, a); | 726 g = SkAlphaMul(g, a); |
| 737 b = SkAlphaMul(b, a); | 727 b = SkAlphaMul(b, a); |
| 738 } | 728 } |
| 739 uint32_t v = kRGBA_8888_SkColorType == this->colorType() ? | 729 uint32_t v = kRGBA_8888_SkColorType == pmap.colorType() ? |
| 740 SkPackARGB_as_RGBA(a, r, g, b) : SkPackARGB_as_BGRA(a,
r, g, b); | 730 SkPackARGB_as_RGBA(a, r, g, b) : SkPackARGB_as_BGRA(a, r, g, b); |
| 741 | 731 |
| 742 while (--height >= 0) { | 732 while (--height >= 0) { |
| 743 sk_memset32(p, v, width); | 733 sk_memset32(p, v, width); |
| 744 p = (uint32_t*)((char*)p + rowBytes); | 734 p = (uint32_t*)((char*)p + rowBytes); |
| 745 } | 735 } |
| 746 break; | 736 break; |
| 747 } | 737 } |
| 748 default: | 738 default: |
| 749 return; // no change, so don't call notifyPixelsChanged() | 739 return false; // no change, so don't call notifyPixelsChanged() |
| 740 } |
| 741 return true; |
| 742 } |
| 743 |
| 744 void SkBitmap::internalErase(const SkIRect& area, U8CPU a, U8CPU r, U8CPU g, U8C
PU b) const { |
| 745 #ifdef SK_DEBUG |
| 746 SkDEBUGCODE(this->validate();) |
| 747 SkASSERT(!area.isEmpty()); |
| 748 { |
| 749 SkIRect total = { 0, 0, this->width(), this->height() }; |
| 750 SkASSERT(total.contains(area)); |
| 751 } |
| 752 #endif |
| 753 |
| 754 switch (fInfo.colorType()) { |
| 755 case kUnknown_SkColorType: |
| 756 case kIndex_8_SkColorType: |
| 757 return; // can't erase. Should we bzero so the memory is not uniniti
alized? |
| 758 default: |
| 759 break; |
| 750 } | 760 } |
| 751 | 761 |
| 752 this->notifyPixelsChanged(); | 762 SkAutoBitmapLockResult result; |
| 763 if (!this->requestLock(&result)) { |
| 764 return; |
| 765 } |
| 766 |
| 767 if (internal_erase(result.pixmap(), area, a, r, g, b)) { |
| 768 this->notifyPixelsChanged(); |
| 769 } |
| 753 } | 770 } |
| 754 | 771 |
| 755 void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { | 772 void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { |
| 756 SkIRect area = { 0, 0, this->width(), this->height() }; | 773 SkIRect area = { 0, 0, this->width(), this->height() }; |
| 757 if (!area.isEmpty()) { | 774 if (!area.isEmpty()) { |
| 758 this->internalErase(area, a, r, g, b); | 775 this->internalErase(area, a, r, g, b); |
| 759 } | 776 } |
| 760 } | 777 } |
| 761 | 778 |
| 762 void SkBitmap::eraseArea(const SkIRect& rect, SkColor c) const { | 779 void SkBitmap::eraseArea(const SkIRect& rect, SkColor c) const { |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 891 x = 0; | 908 x = 0; |
| 892 } | 909 } |
| 893 if (y > 0) { | 910 if (y > 0) { |
| 894 y = 0; | 911 y = 0; |
| 895 } | 912 } |
| 896 // here x,y are either 0 or negative | 913 // here x,y are either 0 or negative |
| 897 dstPixels = ((char*)dstPixels - y * dstRB - x * dstInfo.bytesPerPixel()); | 914 dstPixels = ((char*)dstPixels - y * dstRB - x * dstInfo.bytesPerPixel()); |
| 898 | 915 |
| 899 ////////////// | 916 ////////////// |
| 900 | 917 |
| 901 SkAutoLockPixels alp(*this); | 918 SkAutoBitmapLockResult result; |
| 902 | 919 if (!this->requestLock(&result)) { |
| 903 // since we don't stop creating un-pixeled devices yet, check for no pixels
here | |
| 904 if (NULL == this->getPixels()) { | |
| 905 return false; | 920 return false; |
| 906 } | 921 } |
| 922 const SkPixmap& pmap = result.pixmap(); |
| 923 const SkImageInfo srcInfo = pmap.info().makeWH(dstInfo.width(), dstInfo.heig
ht()); |
| 907 | 924 |
| 908 const SkImageInfo srcInfo = this->info().makeWH(dstInfo.width(), dstInfo.hei
ght()); | 925 const void* srcPixels = pmap.addr(srcR.x(), srcR.y()); |
| 909 | 926 return SkPixelInfo::CopyPixels(dstInfo, dstPixels, dstRB, srcInfo, srcPixels
, pmap.rowBytes(), |
| 910 const void* srcPixels = this->getAddr(srcR.x(), srcR.y()); | 927 pmap.ctable()); |
| 911 return SkPixelInfo::CopyPixels(dstInfo, dstPixels, dstRB, srcInfo, srcPixels
, this->rowBytes(), | |
| 912 this->getColorTable()); | |
| 913 } | 928 } |
| 914 | 929 |
| 915 bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, Allocator* alloc)
const { | 930 bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, Allocator* alloc)
const { |
| 916 if (!this->canCopyTo(dstColorType)) { | 931 if (!this->canCopyTo(dstColorType)) { |
| 917 return false; | 932 return false; |
| 918 } | 933 } |
| 919 | 934 |
| 920 // if we have a texture, first get those pixels | 935 // if we have a texture, first get those pixels |
| 921 SkBitmap tmpSrc; | 936 SkBitmap tmpSrc; |
| 922 const SkBitmap* src = this; | 937 const SkBitmap* src = this; |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1041 | 1056 |
| 1042 if (this->getTexture()) { | 1057 if (this->getTexture()) { |
| 1043 return false; | 1058 return false; |
| 1044 } else { | 1059 } else { |
| 1045 return this->copyTo(dst, dstCT, NULL); | 1060 return this->copyTo(dst, dstCT, NULL); |
| 1046 } | 1061 } |
| 1047 } | 1062 } |
| 1048 | 1063 |
| 1049 /////////////////////////////////////////////////////////////////////////////// | 1064 /////////////////////////////////////////////////////////////////////////////// |
| 1050 | 1065 |
| 1051 static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, | 1066 static void rect_memset(uint8_t* array, U8CPU value, SkISize size, size_t rowByt
es) { |
| 1052 int alphaRowBytes) { | 1067 for (int y = 0; y < size.height(); ++y) { |
| 1053 SkASSERT(alpha != NULL); | 1068 memset(array, value, size.width()); |
| 1054 SkASSERT(alphaRowBytes >= src.width()); | 1069 array += rowBytes; |
| 1070 } |
| 1071 } |
| 1055 | 1072 |
| 1056 SkColorType colorType = src.colorType(); | 1073 static void get_bitmap_alpha(const SkPixmap& pmap, uint8_t* SK_RESTRICT alpha, i
nt alphaRowBytes) { |
| 1057 int w = src.width(); | 1074 SkColorType colorType = pmap.colorType(); |
| 1058 int h = src.height(); | 1075 int w = pmap.width(); |
| 1059 size_t rb = src.rowBytes(); | 1076 int h = pmap.height(); |
| 1077 size_t rb = pmap.rowBytes(); |
| 1060 | 1078 |
| 1061 SkAutoLockPixels alp(src); | 1079 if (kAlpha_8_SkColorType == colorType && !pmap.isOpaque()) { |
| 1062 if (!src.readyToDraw()) { | 1080 const uint8_t* s = pmap.addr8(0, 0); |
| 1063 // zero out the alpha buffer and return | |
| 1064 while (--h >= 0) { | |
| 1065 memset(alpha, 0, w); | |
| 1066 alpha += alphaRowBytes; | |
| 1067 } | |
| 1068 return false; | |
| 1069 } | |
| 1070 | |
| 1071 if (kAlpha_8_SkColorType == colorType && !src.isOpaque()) { | |
| 1072 const uint8_t* s = src.getAddr8(0, 0); | |
| 1073 while (--h >= 0) { | 1081 while (--h >= 0) { |
| 1074 memcpy(alpha, s, w); | 1082 memcpy(alpha, s, w); |
| 1075 s += rb; | 1083 s += rb; |
| 1076 alpha += alphaRowBytes; | 1084 alpha += alphaRowBytes; |
| 1077 } | 1085 } |
| 1078 } else if (kN32_SkColorType == colorType && !src.isOpaque()) { | 1086 } else if (kN32_SkColorType == colorType && !pmap.isOpaque()) { |
| 1079 const SkPMColor* SK_RESTRICT s = src.getAddr32(0, 0); | 1087 const SkPMColor* SK_RESTRICT s = pmap.addr32(0, 0); |
| 1080 while (--h >= 0) { | 1088 while (--h >= 0) { |
| 1081 for (int x = 0; x < w; x++) { | 1089 for (int x = 0; x < w; x++) { |
| 1082 alpha[x] = SkGetPackedA32(s[x]); | 1090 alpha[x] = SkGetPackedA32(s[x]); |
| 1083 } | 1091 } |
| 1084 s = (const SkPMColor*)((const char*)s + rb); | 1092 s = (const SkPMColor*)((const char*)s + rb); |
| 1085 alpha += alphaRowBytes; | 1093 alpha += alphaRowBytes; |
| 1086 } | 1094 } |
| 1087 } else if (kARGB_4444_SkColorType == colorType && !src.isOpaque()) { | 1095 } else if (kARGB_4444_SkColorType == colorType && !pmap.isOpaque()) { |
| 1088 const SkPMColor16* SK_RESTRICT s = src.getAddr16(0, 0); | 1096 const SkPMColor16* SK_RESTRICT s = pmap.addr16(0, 0); |
| 1089 while (--h >= 0) { | 1097 while (--h >= 0) { |
| 1090 for (int x = 0; x < w; x++) { | 1098 for (int x = 0; x < w; x++) { |
| 1091 alpha[x] = SkPacked4444ToA32(s[x]); | 1099 alpha[x] = SkPacked4444ToA32(s[x]); |
| 1092 } | 1100 } |
| 1093 s = (const SkPMColor16*)((const char*)s + rb); | 1101 s = (const SkPMColor16*)((const char*)s + rb); |
| 1094 alpha += alphaRowBytes; | 1102 alpha += alphaRowBytes; |
| 1095 } | 1103 } |
| 1096 } else if (kIndex_8_SkColorType == colorType && !src.isOpaque()) { | 1104 } else if (kIndex_8_SkColorType == colorType && !pmap.isOpaque()) { |
| 1097 SkColorTable* ct = src.getColorTable(); | 1105 const SkColorTable* ct = pmap.ctable(); |
| 1098 if (ct) { | 1106 if (ct) { |
| 1099 const SkPMColor* SK_RESTRICT table = ct->readColors(); | 1107 const SkPMColor* SK_RESTRICT table = ct->readColors(); |
| 1100 const uint8_t* SK_RESTRICT s = src.getAddr8(0, 0); | 1108 const uint8_t* SK_RESTRICT s = pmap.addr8(0, 0); |
| 1101 while (--h >= 0) { | 1109 while (--h >= 0) { |
| 1102 for (int x = 0; x < w; x++) { | 1110 for (int x = 0; x < w; x++) { |
| 1103 alpha[x] = SkGetPackedA32(table[s[x]]); | 1111 alpha[x] = SkGetPackedA32(table[s[x]]); |
| 1104 } | 1112 } |
| 1105 s += rb; | 1113 s += rb; |
| 1106 alpha += alphaRowBytes; | 1114 alpha += alphaRowBytes; |
| 1107 } | 1115 } |
| 1108 } | 1116 } |
| 1109 } else { // src is opaque, so just fill alpha[] with 0xFF | 1117 } else { // src is opaque, so just fill alpha[] with 0xFF |
| 1110 memset(alpha, 0xFF, h * alphaRowBytes); | 1118 rect_memset(alpha, 0xFF, pmap.info().dimensions(), alphaRowBytes); |
| 1111 } | 1119 } |
| 1120 } |
| 1121 |
| 1122 static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, int
alphaRowBytes) { |
| 1123 SkASSERT(alpha != NULL); |
| 1124 SkASSERT(alphaRowBytes >= src.width()); |
| 1125 |
| 1126 SkAutoBitmapLockResult apl; |
| 1127 if (!src.requestLock(&apl)) { |
| 1128 rect_memset(alpha, 0, src.info().dimensions(), alphaRowBytes); |
| 1129 return false; |
| 1130 } |
| 1131 get_bitmap_alpha(apl.pixmap(), alpha, alphaRowBytes); |
| 1112 return true; | 1132 return true; |
| 1113 } | 1133 } |
| 1114 | 1134 |
| 1115 #include "SkPaint.h" | 1135 #include "SkPaint.h" |
| 1116 #include "SkMaskFilter.h" | 1136 #include "SkMaskFilter.h" |
| 1117 #include "SkMatrix.h" | 1137 #include "SkMatrix.h" |
| 1118 | 1138 |
| 1119 bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint, | 1139 bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint, |
| 1120 Allocator *allocator, SkIPoint* offset) const { | 1140 Allocator *allocator, SkIPoint* offset) const { |
| 1121 SkDEBUGCODE(this->validate();) | 1141 SkDEBUGCODE(this->validate();) |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1176 offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop); | 1196 offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop); |
| 1177 } | 1197 } |
| 1178 SkDEBUGCODE(tmpBitmap.validate();) | 1198 SkDEBUGCODE(tmpBitmap.validate();) |
| 1179 | 1199 |
| 1180 tmpBitmap.swap(*dst); | 1200 tmpBitmap.swap(*dst); |
| 1181 return true; | 1201 return true; |
| 1182 } | 1202 } |
| 1183 | 1203 |
| 1184 /////////////////////////////////////////////////////////////////////////////// | 1204 /////////////////////////////////////////////////////////////////////////////// |
| 1185 | 1205 |
| 1186 void SkBitmap::WriteRawPixels(SkWriteBuffer* buffer, const SkBitmap& bitmap) { | 1206 static void write_raw_pixels(SkWriteBuffer* buffer, const SkPixmap& pmap) { |
| 1187 const SkImageInfo info = bitmap.info(); | 1207 const SkImageInfo& info = pmap.info(); |
| 1188 SkAutoLockPixels alp(bitmap); | |
| 1189 if (0 == info.width() || 0 == info.height() || NULL == bitmap.getPixels()) { | |
| 1190 buffer->writeUInt(0); // instead of snugRB, signaling no pixels | |
| 1191 return; | |
| 1192 } | |
| 1193 | |
| 1194 const size_t snugRB = info.width() * info.bytesPerPixel(); | 1208 const size_t snugRB = info.width() * info.bytesPerPixel(); |
| 1195 const char* src = (const char*)bitmap.getPixels(); | 1209 const char* src = (const char*)pmap.addr(); |
| 1196 const size_t ramRB = bitmap.rowBytes(); | 1210 const size_t ramRB = pmap.rowBytes(); |
| 1197 | 1211 |
| 1198 buffer->write32(SkToU32(snugRB)); | 1212 buffer->write32(SkToU32(snugRB)); |
| 1199 info.flatten(*buffer); | 1213 info.flatten(*buffer); |
| 1200 | 1214 |
| 1201 const size_t size = snugRB * info.height(); | 1215 const size_t size = snugRB * info.height(); |
| 1202 SkAutoMalloc storage(size); | 1216 SkAutoMalloc storage(size); |
| 1203 char* dst = (char*)storage.get(); | 1217 char* dst = (char*)storage.get(); |
| 1204 for (int y = 0; y < info.height(); ++y) { | 1218 for (int y = 0; y < info.height(); ++y) { |
| 1205 memcpy(dst, src, snugRB); | 1219 memcpy(dst, src, snugRB); |
| 1206 dst += snugRB; | 1220 dst += snugRB; |
| 1207 src += ramRB; | 1221 src += ramRB; |
| 1208 } | 1222 } |
| 1209 buffer->writeByteArray(storage.get(), size); | 1223 buffer->writeByteArray(storage.get(), size); |
| 1210 | 1224 |
| 1211 SkColorTable* ct = bitmap.getColorTable(); | 1225 const SkColorTable* ct = pmap.ctable(); |
| 1212 if (kIndex_8_SkColorType == info.colorType() && ct) { | 1226 if (kIndex_8_SkColorType == info.colorType() && ct) { |
| 1213 buffer->writeBool(true); | 1227 buffer->writeBool(true); |
| 1214 ct->writeToBuffer(*buffer); | 1228 ct->writeToBuffer(*buffer); |
| 1215 } else { | 1229 } else { |
| 1216 buffer->writeBool(false); | 1230 buffer->writeBool(false); |
| 1217 } | 1231 } |
| 1218 } | 1232 } |
| 1219 | 1233 |
| 1234 void SkBitmap::WriteRawPixels(SkWriteBuffer* buffer, const SkBitmap& bitmap) { |
| 1235 const SkImageInfo info = bitmap.info(); |
| 1236 if (0 == info.width() || 0 == info.height() || NULL == bitmap.pixelRef()) { |
| 1237 buffer->writeUInt(0); // instead of snugRB, signaling no pixels |
| 1238 return; |
| 1239 } |
| 1240 |
| 1241 SkAutoBitmapLockResult result; |
| 1242 if (!bitmap.requestLock(&result)) { |
| 1243 buffer->writeUInt(0); // instead of snugRB, signaling no pixels |
| 1244 return; |
| 1245 } |
| 1246 |
| 1247 write_raw_pixels(buffer, result.pixmap()); |
| 1248 } |
| 1249 |
| 1220 bool SkBitmap::ReadRawPixels(SkReadBuffer* buffer, SkBitmap* bitmap) { | 1250 bool SkBitmap::ReadRawPixels(SkReadBuffer* buffer, SkBitmap* bitmap) { |
| 1221 const size_t snugRB = buffer->readUInt(); | 1251 const size_t snugRB = buffer->readUInt(); |
| 1222 if (0 == snugRB) { // no pixels | 1252 if (0 == snugRB) { // no pixels |
| 1223 return false; | 1253 return false; |
| 1224 } | 1254 } |
| 1225 | 1255 |
| 1226 SkImageInfo info; | 1256 SkImageInfo info; |
| 1227 info.unflatten(*buffer); | 1257 info.unflatten(*buffer); |
| 1228 | 1258 |
| 1229 // If there was an error reading "info", don't use it to compute minRowBytes
() | 1259 // If there was an error reading "info", don't use it to compute minRowBytes
() |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1357 str->appendf(" pixelref:%p", pr); | 1387 str->appendf(" pixelref:%p", pr); |
| 1358 } | 1388 } |
| 1359 } | 1389 } |
| 1360 | 1390 |
| 1361 str->append(")"); | 1391 str->append(")"); |
| 1362 } | 1392 } |
| 1363 #endif | 1393 #endif |
| 1364 | 1394 |
| 1365 /////////////////////////////////////////////////////////////////////////////// | 1395 /////////////////////////////////////////////////////////////////////////////// |
| 1366 | 1396 |
| 1397 void SkBitmap::LockResult::unlock() { |
| 1398 SkASSERT(fIsLocked); |
| 1399 if (fUnlockProc) { |
| 1400 fUnlockProc(fUnlockContext); |
| 1401 fUnlockProc = NULL; |
| 1402 fUnlockContext = NULL; |
| 1403 SkDEBUGCODE(fIsLocked = false;) |
| 1404 } |
| 1405 } |
| 1406 |
| 1407 bool SkBitmap::requestLock(LockResult* result) const { |
| 1408 SkPixelRef* pr = fPixelRef; |
| 1409 if (NULL == pr) { |
| 1410 return false; |
| 1411 } |
| 1412 |
| 1413 SkPixelRef::LockRequest req = { fInfo.dimensions(), kNone_SkFilterQuality }; |
| 1414 SkPixelRef::LockResult res; |
| 1415 if (pr->requestLock(req, &res)) { |
| 1416 // The bitmap may be a subset of the pixelref's dimensions |
| 1417 SkASSERT(fPixelRefOrigin.x() + fInfo.width() <= res.fSize.width()); |
| 1418 SkASSERT(fPixelRefOrigin.y() + fInfo.height() <= res.fSize.height()); |
| 1419 const void* addr = (const char*)res.fPixels + SkColorTypeComputeOffset(f
Info.colorType(), |
| 1420 f
PixelRefOrigin.x(), |
| 1421 f
PixelRefOrigin.y(), |
| 1422 r
es.fRowBytes); |
| 1423 |
| 1424 new (result) LockResult(SkPixmap(this->info(), addr, res.fRowBytes, res.
fCTable), |
| 1425 res.fUnlockProc, res.fUnlockContext); |
| 1426 return true; |
| 1427 } |
| 1428 return false; |
| 1429 } |
| 1430 |
| 1431 /////////////////////////////////////////////////////////////////////////////// |
| 1432 |
| 1367 #ifdef SK_DEBUG | 1433 #ifdef SK_DEBUG |
| 1368 void SkImageInfo::validate() const { | 1434 void SkImageInfo::validate() const { |
| 1369 SkASSERT(fWidth >= 0); | 1435 SkASSERT(fWidth >= 0); |
| 1370 SkASSERT(fHeight >= 0); | 1436 SkASSERT(fHeight >= 0); |
| 1371 SkASSERT(SkColorTypeIsValid(fColorType)); | 1437 SkASSERT(SkColorTypeIsValid(fColorType)); |
| 1372 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); | 1438 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); |
| 1373 } | 1439 } |
| 1374 #endif | 1440 #endif |
| OLD | NEW |