| 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& src, void* const dst, size_t dstSize, |
| 434 size_t dstRowBytes, bool preserveDstPad) const { | 434 size_t dstRowBytes, bool preserveDstPad) { |
| 435 const SkImageInfo& info = src.info(); |
| 435 | 436 |
| 436 if (0 == dstRowBytes) { | 437 if (0 == dstRowBytes) { |
| 437 dstRowBytes = fRowBytes; | 438 dstRowBytes = src.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) == src.rowBytes())
{ |
| 446 size_t safeSize = this->getSafeSize(); | 445 size_t safeSize = src.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, src.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*>(src.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 += src.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 SkAutoPixmapUnlock 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 SkAutoPixmapUnlock 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 // TODO: can we ASSERT that we never get here? |
| 758 return; // can't erase. Should we bzero so the memory is not uniniti
alized? |
| 759 default: |
| 760 break; |
| 750 } | 761 } |
| 751 | 762 |
| 752 this->notifyPixelsChanged(); | 763 SkAutoPixmapUnlock result; |
| 764 if (!this->requestLock(&result)) { |
| 765 return; |
| 766 } |
| 767 |
| 768 if (internal_erase(result.pixmap(), area, a, r, g, b)) { |
| 769 this->notifyPixelsChanged(); |
| 770 } |
| 753 } | 771 } |
| 754 | 772 |
| 755 void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { | 773 void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { |
| 756 SkIRect area = { 0, 0, this->width(), this->height() }; | 774 SkIRect area = { 0, 0, this->width(), this->height() }; |
| 757 if (!area.isEmpty()) { | 775 if (!area.isEmpty()) { |
| 758 this->internalErase(area, a, r, g, b); | 776 this->internalErase(area, a, r, g, b); |
| 759 } | 777 } |
| 760 } | 778 } |
| 761 | 779 |
| 762 void SkBitmap::eraseArea(const SkIRect& rect, SkColor c) const { | 780 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; | 909 x = 0; |
| 892 } | 910 } |
| 893 if (y > 0) { | 911 if (y > 0) { |
| 894 y = 0; | 912 y = 0; |
| 895 } | 913 } |
| 896 // here x,y are either 0 or negative | 914 // here x,y are either 0 or negative |
| 897 dstPixels = ((char*)dstPixels - y * dstRB - x * dstInfo.bytesPerPixel()); | 915 dstPixels = ((char*)dstPixels - y * dstRB - x * dstInfo.bytesPerPixel()); |
| 898 | 916 |
| 899 ////////////// | 917 ////////////// |
| 900 | 918 |
| 901 SkAutoLockPixels alp(*this); | 919 SkAutoPixmapUnlock result; |
| 902 | 920 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; | 921 return false; |
| 906 } | 922 } |
| 923 const SkPixmap& pmap = result.pixmap(); |
| 924 const SkImageInfo srcInfo = pmap.info().makeWH(dstInfo.width(), dstInfo.heig
ht()); |
| 907 | 925 |
| 908 const SkImageInfo srcInfo = this->info().makeWH(dstInfo.width(), dstInfo.hei
ght()); | 926 const void* srcPixels = pmap.addr(srcR.x(), srcR.y()); |
| 909 | 927 return SkPixelInfo::CopyPixels(dstInfo, dstPixels, dstRB, srcInfo, srcPixels
, pmap.rowBytes(), |
| 910 const void* srcPixels = this->getAddr(srcR.x(), srcR.y()); | 928 pmap.ctable()); |
| 911 return SkPixelInfo::CopyPixels(dstInfo, dstPixels, dstRB, srcInfo, srcPixels
, this->rowBytes(), | |
| 912 this->getColorTable()); | |
| 913 } | 929 } |
| 914 | 930 |
| 915 bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, Allocator* alloc)
const { | 931 bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, Allocator* alloc)
const { |
| 916 if (!this->canCopyTo(dstColorType)) { | 932 if (!this->canCopyTo(dstColorType)) { |
| 917 return false; | 933 return false; |
| 918 } | 934 } |
| 919 | 935 |
| 920 // if we have a texture, first get those pixels | 936 // if we have a texture, first get those pixels |
| 921 SkBitmap tmpSrc; | 937 SkBitmap tmpSrc; |
| 922 const SkBitmap* src = this; | 938 const SkBitmap* src = this; |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1041 | 1057 |
| 1042 if (this->getTexture()) { | 1058 if (this->getTexture()) { |
| 1043 return false; | 1059 return false; |
| 1044 } else { | 1060 } else { |
| 1045 return this->copyTo(dst, dstCT, NULL); | 1061 return this->copyTo(dst, dstCT, NULL); |
| 1046 } | 1062 } |
| 1047 } | 1063 } |
| 1048 | 1064 |
| 1049 /////////////////////////////////////////////////////////////////////////////// | 1065 /////////////////////////////////////////////////////////////////////////////// |
| 1050 | 1066 |
| 1051 static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, | 1067 static void rect_memset(uint8_t* array, U8CPU value, SkISize size, size_t rowByt
es) { |
| 1052 int alphaRowBytes) { | 1068 for (int y = 0; y < size.height(); ++y) { |
| 1053 SkASSERT(alpha != NULL); | 1069 memset(array, value, size.width()); |
| 1054 SkASSERT(alphaRowBytes >= src.width()); | 1070 array += rowBytes; |
| 1071 } |
| 1072 } |
| 1055 | 1073 |
| 1056 SkColorType colorType = src.colorType(); | 1074 static void get_bitmap_alpha(const SkPixmap& pmap, uint8_t* SK_RESTRICT alpha, i
nt alphaRowBytes) { |
| 1057 int w = src.width(); | 1075 SkColorType colorType = pmap.colorType(); |
| 1058 int h = src.height(); | 1076 int w = pmap.width(); |
| 1059 size_t rb = src.rowBytes(); | 1077 int h = pmap.height(); |
| 1078 size_t rb = pmap.rowBytes(); |
| 1060 | 1079 |
| 1061 SkAutoLockPixels alp(src); | 1080 if (kAlpha_8_SkColorType == colorType && !pmap.isOpaque()) { |
| 1062 if (!src.readyToDraw()) { | 1081 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) { | 1082 while (--h >= 0) { |
| 1074 memcpy(alpha, s, w); | 1083 memcpy(alpha, s, w); |
| 1075 s += rb; | 1084 s += rb; |
| 1076 alpha += alphaRowBytes; | 1085 alpha += alphaRowBytes; |
| 1077 } | 1086 } |
| 1078 } else if (kN32_SkColorType == colorType && !src.isOpaque()) { | 1087 } else if (kN32_SkColorType == colorType && !pmap.isOpaque()) { |
| 1079 const SkPMColor* SK_RESTRICT s = src.getAddr32(0, 0); | 1088 const SkPMColor* SK_RESTRICT s = pmap.addr32(0, 0); |
| 1080 while (--h >= 0) { | 1089 while (--h >= 0) { |
| 1081 for (int x = 0; x < w; x++) { | 1090 for (int x = 0; x < w; x++) { |
| 1082 alpha[x] = SkGetPackedA32(s[x]); | 1091 alpha[x] = SkGetPackedA32(s[x]); |
| 1083 } | 1092 } |
| 1084 s = (const SkPMColor*)((const char*)s + rb); | 1093 s = (const SkPMColor*)((const char*)s + rb); |
| 1085 alpha += alphaRowBytes; | 1094 alpha += alphaRowBytes; |
| 1086 } | 1095 } |
| 1087 } else if (kARGB_4444_SkColorType == colorType && !src.isOpaque()) { | 1096 } else if (kARGB_4444_SkColorType == colorType && !pmap.isOpaque()) { |
| 1088 const SkPMColor16* SK_RESTRICT s = src.getAddr16(0, 0); | 1097 const SkPMColor16* SK_RESTRICT s = pmap.addr16(0, 0); |
| 1089 while (--h >= 0) { | 1098 while (--h >= 0) { |
| 1090 for (int x = 0; x < w; x++) { | 1099 for (int x = 0; x < w; x++) { |
| 1091 alpha[x] = SkPacked4444ToA32(s[x]); | 1100 alpha[x] = SkPacked4444ToA32(s[x]); |
| 1092 } | 1101 } |
| 1093 s = (const SkPMColor16*)((const char*)s + rb); | 1102 s = (const SkPMColor16*)((const char*)s + rb); |
| 1094 alpha += alphaRowBytes; | 1103 alpha += alphaRowBytes; |
| 1095 } | 1104 } |
| 1096 } else if (kIndex_8_SkColorType == colorType && !src.isOpaque()) { | 1105 } else if (kIndex_8_SkColorType == colorType && !pmap.isOpaque()) { |
| 1097 SkColorTable* ct = src.getColorTable(); | 1106 const SkColorTable* ct = pmap.ctable(); |
| 1098 if (ct) { | 1107 if (ct) { |
| 1099 const SkPMColor* SK_RESTRICT table = ct->readColors(); | 1108 const SkPMColor* SK_RESTRICT table = ct->readColors(); |
| 1100 const uint8_t* SK_RESTRICT s = src.getAddr8(0, 0); | 1109 const uint8_t* SK_RESTRICT s = pmap.addr8(0, 0); |
| 1101 while (--h >= 0) { | 1110 while (--h >= 0) { |
| 1102 for (int x = 0; x < w; x++) { | 1111 for (int x = 0; x < w; x++) { |
| 1103 alpha[x] = SkGetPackedA32(table[s[x]]); | 1112 alpha[x] = SkGetPackedA32(table[s[x]]); |
| 1104 } | 1113 } |
| 1105 s += rb; | 1114 s += rb; |
| 1106 alpha += alphaRowBytes; | 1115 alpha += alphaRowBytes; |
| 1107 } | 1116 } |
| 1108 } | 1117 } |
| 1109 } else { // src is opaque, so just fill alpha[] with 0xFF | 1118 } else { // src is opaque, so just fill alpha[] with 0xFF |
| 1110 memset(alpha, 0xFF, h * alphaRowBytes); | 1119 rect_memset(alpha, 0xFF, pmap.info().dimensions(), alphaRowBytes); |
| 1111 } | 1120 } |
| 1121 } |
| 1122 |
| 1123 static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, int
alphaRowBytes) { |
| 1124 SkASSERT(alpha != NULL); |
| 1125 SkASSERT(alphaRowBytes >= src.width()); |
| 1126 |
| 1127 SkAutoPixmapUnlock apl; |
| 1128 if (!src.requestLock(&apl)) { |
| 1129 rect_memset(alpha, 0, src.info().dimensions(), alphaRowBytes); |
| 1130 return false; |
| 1131 } |
| 1132 get_bitmap_alpha(apl.pixmap(), alpha, alphaRowBytes); |
| 1112 return true; | 1133 return true; |
| 1113 } | 1134 } |
| 1114 | 1135 |
| 1115 #include "SkPaint.h" | 1136 #include "SkPaint.h" |
| 1116 #include "SkMaskFilter.h" | 1137 #include "SkMaskFilter.h" |
| 1117 #include "SkMatrix.h" | 1138 #include "SkMatrix.h" |
| 1118 | 1139 |
| 1119 bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint, | 1140 bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint, |
| 1120 Allocator *allocator, SkIPoint* offset) const { | 1141 Allocator *allocator, SkIPoint* offset) const { |
| 1121 SkDEBUGCODE(this->validate();) | 1142 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); | 1197 offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop); |
| 1177 } | 1198 } |
| 1178 SkDEBUGCODE(tmpBitmap.validate();) | 1199 SkDEBUGCODE(tmpBitmap.validate();) |
| 1179 | 1200 |
| 1180 tmpBitmap.swap(*dst); | 1201 tmpBitmap.swap(*dst); |
| 1181 return true; | 1202 return true; |
| 1182 } | 1203 } |
| 1183 | 1204 |
| 1184 /////////////////////////////////////////////////////////////////////////////// | 1205 /////////////////////////////////////////////////////////////////////////////// |
| 1185 | 1206 |
| 1186 void SkBitmap::WriteRawPixels(SkWriteBuffer* buffer, const SkBitmap& bitmap) { | 1207 static void write_raw_pixels(SkWriteBuffer* buffer, const SkPixmap& pmap) { |
| 1187 const SkImageInfo info = bitmap.info(); | 1208 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(); | 1209 const size_t snugRB = info.width() * info.bytesPerPixel(); |
| 1195 const char* src = (const char*)bitmap.getPixels(); | 1210 const char* src = (const char*)pmap.addr(); |
| 1196 const size_t ramRB = bitmap.rowBytes(); | 1211 const size_t ramRB = pmap.rowBytes(); |
| 1197 | 1212 |
| 1198 buffer->write32(SkToU32(snugRB)); | 1213 buffer->write32(SkToU32(snugRB)); |
| 1199 info.flatten(*buffer); | 1214 info.flatten(*buffer); |
| 1200 | 1215 |
| 1201 const size_t size = snugRB * info.height(); | 1216 const size_t size = snugRB * info.height(); |
| 1202 SkAutoMalloc storage(size); | 1217 SkAutoMalloc storage(size); |
| 1203 char* dst = (char*)storage.get(); | 1218 char* dst = (char*)storage.get(); |
| 1204 for (int y = 0; y < info.height(); ++y) { | 1219 for (int y = 0; y < info.height(); ++y) { |
| 1205 memcpy(dst, src, snugRB); | 1220 memcpy(dst, src, snugRB); |
| 1206 dst += snugRB; | 1221 dst += snugRB; |
| 1207 src += ramRB; | 1222 src += ramRB; |
| 1208 } | 1223 } |
| 1209 buffer->writeByteArray(storage.get(), size); | 1224 buffer->writeByteArray(storage.get(), size); |
| 1210 | 1225 |
| 1211 SkColorTable* ct = bitmap.getColorTable(); | 1226 const SkColorTable* ct = pmap.ctable(); |
| 1212 if (kIndex_8_SkColorType == info.colorType() && ct) { | 1227 if (kIndex_8_SkColorType == info.colorType() && ct) { |
| 1213 buffer->writeBool(true); | 1228 buffer->writeBool(true); |
| 1214 ct->writeToBuffer(*buffer); | 1229 ct->writeToBuffer(*buffer); |
| 1215 } else { | 1230 } else { |
| 1216 buffer->writeBool(false); | 1231 buffer->writeBool(false); |
| 1217 } | 1232 } |
| 1218 } | 1233 } |
| 1219 | 1234 |
| 1235 void SkBitmap::WriteRawPixels(SkWriteBuffer* buffer, const SkBitmap& bitmap) { |
| 1236 const SkImageInfo info = bitmap.info(); |
| 1237 if (0 == info.width() || 0 == info.height() || NULL == bitmap.pixelRef()) { |
| 1238 buffer->writeUInt(0); // instead of snugRB, signaling no pixels |
| 1239 return; |
| 1240 } |
| 1241 |
| 1242 SkAutoPixmapUnlock result; |
| 1243 if (!bitmap.requestLock(&result)) { |
| 1244 buffer->writeUInt(0); // instead of snugRB, signaling no pixels |
| 1245 return; |
| 1246 } |
| 1247 |
| 1248 write_raw_pixels(buffer, result.pixmap()); |
| 1249 } |
| 1250 |
| 1220 bool SkBitmap::ReadRawPixels(SkReadBuffer* buffer, SkBitmap* bitmap) { | 1251 bool SkBitmap::ReadRawPixels(SkReadBuffer* buffer, SkBitmap* bitmap) { |
| 1221 const size_t snugRB = buffer->readUInt(); | 1252 const size_t snugRB = buffer->readUInt(); |
| 1222 if (0 == snugRB) { // no pixels | 1253 if (0 == snugRB) { // no pixels |
| 1223 return false; | 1254 return false; |
| 1224 } | 1255 } |
| 1225 | 1256 |
| 1226 SkImageInfo info; | 1257 SkImageInfo info; |
| 1227 info.unflatten(*buffer); | 1258 info.unflatten(*buffer); |
| 1228 | 1259 |
| 1229 // If there was an error reading "info", don't use it to compute minRowBytes
() | 1260 // 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); | 1388 str->appendf(" pixelref:%p", pr); |
| 1358 } | 1389 } |
| 1359 } | 1390 } |
| 1360 | 1391 |
| 1361 str->append(")"); | 1392 str->append(")"); |
| 1362 } | 1393 } |
| 1363 #endif | 1394 #endif |
| 1364 | 1395 |
| 1365 /////////////////////////////////////////////////////////////////////////////// | 1396 /////////////////////////////////////////////////////////////////////////////// |
| 1366 | 1397 |
| 1398 bool SkBitmap::requestLock(SkAutoPixmapUnlock* result) const { |
| 1399 SkASSERT(result); |
| 1400 |
| 1401 SkPixelRef* pr = fPixelRef; |
| 1402 if (NULL == pr) { |
| 1403 return false; |
| 1404 } |
| 1405 |
| 1406 SkPixelRef::LockRequest req = { fInfo.dimensions(), kNone_SkFilterQuality }; |
| 1407 SkPixelRef::LockResult res; |
| 1408 if (pr->requestLock(req, &res)) { |
| 1409 // The bitmap may be a subset of the pixelref's dimensions |
| 1410 SkASSERT(fPixelRefOrigin.x() + fInfo.width() <= res.fSize.width()); |
| 1411 SkASSERT(fPixelRefOrigin.y() + fInfo.height() <= res.fSize.height()); |
| 1412 const void* addr = (const char*)res.fPixels + SkColorTypeComputeOffset(f
Info.colorType(), |
| 1413 f
PixelRefOrigin.x(), |
| 1414 f
PixelRefOrigin.y(), |
| 1415 r
es.fRowBytes); |
| 1416 |
| 1417 result->reset(SkPixmap(this->info(), addr, res.fRowBytes, res.fCTable), |
| 1418 res.fUnlockProc, res.fUnlockContext); |
| 1419 return true; |
| 1420 } |
| 1421 return false; |
| 1422 } |
| 1423 |
| 1424 /////////////////////////////////////////////////////////////////////////////// |
| 1425 |
| 1367 #ifdef SK_DEBUG | 1426 #ifdef SK_DEBUG |
| 1368 void SkImageInfo::validate() const { | 1427 void SkImageInfo::validate() const { |
| 1369 SkASSERT(fWidth >= 0); | 1428 SkASSERT(fWidth >= 0); |
| 1370 SkASSERT(fHeight >= 0); | 1429 SkASSERT(fHeight >= 0); |
| 1371 SkASSERT(SkColorTypeIsValid(fColorType)); | 1430 SkASSERT(SkColorTypeIsValid(fColorType)); |
| 1372 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); | 1431 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); |
| 1373 } | 1432 } |
| 1374 #endif | 1433 #endif |
| OLD | NEW |