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 |