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 |