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 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 | 154 |
155 void SkBitmap::reset() { | 155 void SkBitmap::reset() { |
156 this->freePixels(); | 156 this->freePixels(); |
157 sk_bzero(this, sizeof(*this)); | 157 sk_bzero(this, sizeof(*this)); |
158 } | 158 } |
159 | 159 |
160 int SkBitmap::ComputeBytesPerPixel(SkBitmap::Config config) { | 160 int SkBitmap::ComputeBytesPerPixel(SkBitmap::Config config) { |
161 int bpp; | 161 int bpp; |
162 switch (config) { | 162 switch (config) { |
163 case kNo_Config: | 163 case kNo_Config: |
164 case kA1_Config: | |
165 bpp = 0; // not applicable | 164 bpp = 0; // not applicable |
166 break; | 165 break; |
167 case kA8_Config: | 166 case kA8_Config: |
168 case kIndex8_Config: | 167 case kIndex8_Config: |
169 bpp = 1; | 168 bpp = 1; |
170 break; | 169 break; |
171 case kRGB_565_Config: | 170 case kRGB_565_Config: |
172 case kARGB_4444_Config: | 171 case kARGB_4444_Config: |
173 bpp = 2; | 172 bpp = 2; |
174 break; | 173 break; |
(...skipping 12 matching lines...) Expand all Loading... |
187 if (width < 0) { | 186 if (width < 0) { |
188 return 0; | 187 return 0; |
189 } | 188 } |
190 | 189 |
191 Sk64 rowBytes; | 190 Sk64 rowBytes; |
192 rowBytes.setZero(); | 191 rowBytes.setZero(); |
193 | 192 |
194 switch (c) { | 193 switch (c) { |
195 case kNo_Config: | 194 case kNo_Config: |
196 break; | 195 break; |
197 case kA1_Config: | |
198 rowBytes.set(width); | |
199 rowBytes.add(7); | |
200 rowBytes.shiftRight(3); | |
201 break; | |
202 case kA8_Config: | 196 case kA8_Config: |
203 case kIndex8_Config: | 197 case kIndex8_Config: |
204 rowBytes.set(width); | 198 rowBytes.set(width); |
205 break; | 199 break; |
206 case kRGB_565_Config: | 200 case kRGB_565_Config: |
207 case kARGB_4444_Config: | 201 case kARGB_4444_Config: |
208 rowBytes.set(width); | 202 rowBytes.set(width); |
209 rowBytes.shiftLeft(1); | 203 rowBytes.shiftLeft(1); |
210 break; | 204 break; |
211 case kARGB_8888_Config: | 205 case kARGB_8888_Config: |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 } | 262 } |
269 | 263 |
270 /////////////////////////////////////////////////////////////////////////////// | 264 /////////////////////////////////////////////////////////////////////////////// |
271 | 265 |
272 static bool validate_alphaType(SkBitmap::Config config, SkAlphaType alphaType, | 266 static bool validate_alphaType(SkBitmap::Config config, SkAlphaType alphaType, |
273 SkAlphaType* canonical = NULL) { | 267 SkAlphaType* canonical = NULL) { |
274 switch (config) { | 268 switch (config) { |
275 case SkBitmap::kNo_Config: | 269 case SkBitmap::kNo_Config: |
276 alphaType = kIgnore_SkAlphaType; | 270 alphaType = kIgnore_SkAlphaType; |
277 break; | 271 break; |
278 case SkBitmap::kA1_Config: | |
279 case SkBitmap::kA8_Config: | 272 case SkBitmap::kA8_Config: |
280 if (kUnpremul_SkAlphaType == alphaType) { | 273 if (kUnpremul_SkAlphaType == alphaType) { |
281 alphaType = kPremul_SkAlphaType; | 274 alphaType = kPremul_SkAlphaType; |
282 } | 275 } |
283 // fall-through | 276 // fall-through |
284 case SkBitmap::kIndex8_Config: | 277 case SkBitmap::kIndex8_Config: |
285 case SkBitmap::kARGB_4444_Config: | 278 case SkBitmap::kARGB_4444_Config: |
286 case SkBitmap::kARGB_8888_Config: | 279 case SkBitmap::kARGB_8888_Config: |
287 if (kIgnore_SkAlphaType == alphaType) { | 280 if (kIgnore_SkAlphaType == alphaType) { |
288 return false; | 281 return false; |
289 } | 282 } |
290 break; | 283 break; |
291 case SkBitmap::kRGB_565_Config: | 284 case SkBitmap::kRGB_565_Config: |
292 alphaType = kOpaque_SkAlphaType; | 285 alphaType = kOpaque_SkAlphaType; |
293 break; | 286 break; |
| 287 default: |
| 288 return false; |
294 } | 289 } |
295 if (canonical) { | 290 if (canonical) { |
296 *canonical = alphaType; | 291 *canonical = alphaType; |
297 } | 292 } |
298 return true; | 293 return true; |
299 } | 294 } |
300 | 295 |
301 bool SkBitmap::setConfig(Config config, int width, int height, size_t rowBytes, | 296 bool SkBitmap::setConfig(Config config, int width, int height, size_t rowBytes, |
302 SkAlphaType alphaType) { | 297 SkAlphaType alphaType) { |
303 if ((width | height) < 0) { | 298 if ((width | height) < 0) { |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 base += x << 2; | 594 base += x << 2; |
600 break; | 595 break; |
601 case SkBitmap::kARGB_4444_Config: | 596 case SkBitmap::kARGB_4444_Config: |
602 case SkBitmap::kRGB_565_Config: | 597 case SkBitmap::kRGB_565_Config: |
603 base += x << 1; | 598 base += x << 1; |
604 break; | 599 break; |
605 case SkBitmap::kA8_Config: | 600 case SkBitmap::kA8_Config: |
606 case SkBitmap::kIndex8_Config: | 601 case SkBitmap::kIndex8_Config: |
607 base += x; | 602 base += x; |
608 break; | 603 break; |
609 case SkBitmap::kA1_Config: | |
610 base += x >> 3; | |
611 break; | 604 break; |
612 default: | 605 default: |
613 SkDEBUGFAIL("Can't return addr for config"); | 606 SkDEBUGFAIL("Can't return addr for config"); |
614 base = NULL; | 607 base = NULL; |
615 break; | 608 break; |
616 } | 609 } |
617 } | 610 } |
618 return base; | 611 return base; |
619 } | 612 } |
620 | 613 |
621 SkColor SkBitmap::getColor(int x, int y) const { | 614 SkColor SkBitmap::getColor(int x, int y) const { |
622 SkASSERT((unsigned)x < (unsigned)this->width()); | 615 SkASSERT((unsigned)x < (unsigned)this->width()); |
623 SkASSERT((unsigned)y < (unsigned)this->height()); | 616 SkASSERT((unsigned)y < (unsigned)this->height()); |
624 | 617 |
625 switch (this->config()) { | 618 switch (this->config()) { |
626 case SkBitmap::kA1_Config: { | |
627 uint8_t* addr = this->getAddr1(x, y); | |
628 uint8_t mask = 1 << (7 - (x % 8)); | |
629 if (addr[0] & mask) { | |
630 return SK_ColorBLACK; | |
631 } else { | |
632 return 0; | |
633 } | |
634 } | |
635 case SkBitmap::kA8_Config: { | 619 case SkBitmap::kA8_Config: { |
636 uint8_t* addr = this->getAddr8(x, y); | 620 uint8_t* addr = this->getAddr8(x, y); |
637 return SkColorSetA(0, addr[0]); | 621 return SkColorSetA(0, addr[0]); |
638 } | 622 } |
639 case SkBitmap::kIndex8_Config: { | 623 case SkBitmap::kIndex8_Config: { |
640 SkPMColor c = this->getIndex8Color(x, y); | 624 SkPMColor c = this->getIndex8Color(x, y); |
641 return SkUnPreMultiply::PMColorToColor(c); | 625 return SkUnPreMultiply::PMColorToColor(c); |
642 } | 626 } |
643 case SkBitmap::kRGB_565_Config: { | 627 case SkBitmap::kRGB_565_Config: { |
644 uint16_t* addr = this->getAddr16(x, y); | 628 uint16_t* addr = this->getAddr16(x, y); |
645 return SkPixel16ToColor(addr[0]); | 629 return SkPixel16ToColor(addr[0]); |
646 } | 630 } |
647 case SkBitmap::kARGB_4444_Config: { | 631 case SkBitmap::kARGB_4444_Config: { |
648 uint16_t* addr = this->getAddr16(x, y); | 632 uint16_t* addr = this->getAddr16(x, y); |
649 SkPMColor c = SkPixel4444ToPixel32(addr[0]); | 633 SkPMColor c = SkPixel4444ToPixel32(addr[0]); |
650 return SkUnPreMultiply::PMColorToColor(c); | 634 return SkUnPreMultiply::PMColorToColor(c); |
651 } | 635 } |
652 case SkBitmap::kARGB_8888_Config: { | 636 case SkBitmap::kARGB_8888_Config: { |
653 uint32_t* addr = this->getAddr32(x, y); | 637 uint32_t* addr = this->getAddr32(x, y); |
654 return SkUnPreMultiply::PMColorToColor(addr[0]); | 638 return SkUnPreMultiply::PMColorToColor(addr[0]); |
655 } | 639 } |
656 case kNo_Config: | 640 case kNo_Config: |
| 641 default: |
657 SkASSERT(false); | 642 SkASSERT(false); |
658 return 0; | 643 return 0; |
659 } | 644 } |
660 SkASSERT(false); // Not reached. | 645 SkASSERT(false); // Not reached. |
661 return 0; | 646 return 0; |
662 } | 647 } |
663 | 648 |
664 bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) { | 649 bool SkBitmap::ComputeIsOpaque(const SkBitmap& bm) { |
665 SkAutoLockPixels alp(bm); | 650 SkAutoLockPixels alp(bm); |
666 if (!bm.getPixels()) { | 651 if (!bm.getPixels()) { |
667 return false; | 652 return false; |
668 } | 653 } |
669 | 654 |
670 const int height = bm.height(); | 655 const int height = bm.height(); |
671 const int width = bm.width(); | 656 const int width = bm.width(); |
672 | 657 |
673 switch (bm.config()) { | 658 switch (bm.config()) { |
674 case SkBitmap::kA1_Config: { | |
675 // TODO | |
676 } break; | |
677 case SkBitmap::kA8_Config: { | 659 case SkBitmap::kA8_Config: { |
678 unsigned a = 0xFF; | 660 unsigned a = 0xFF; |
679 for (int y = 0; y < height; ++y) { | 661 for (int y = 0; y < height; ++y) { |
680 const uint8_t* row = bm.getAddr8(0, y); | 662 const uint8_t* row = bm.getAddr8(0, y); |
681 for (int x = 0; x < width; ++x) { | 663 for (int x = 0; x < width; ++x) { |
682 a &= row[x]; | 664 a &= row[x]; |
683 } | 665 } |
684 if (0xFF != a) { | 666 if (0xFF != a) { |
685 return false; | 667 return false; |
686 } | 668 } |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
772 const int rowBytes = fRowBytes; | 754 const int rowBytes = fRowBytes; |
773 | 755 |
774 // make rgb premultiplied | 756 // make rgb premultiplied |
775 if (255 != a) { | 757 if (255 != a) { |
776 r = SkAlphaMul(r, a); | 758 r = SkAlphaMul(r, a); |
777 g = SkAlphaMul(g, a); | 759 g = SkAlphaMul(g, a); |
778 b = SkAlphaMul(b, a); | 760 b = SkAlphaMul(b, a); |
779 } | 761 } |
780 | 762 |
781 switch (fConfig) { | 763 switch (fConfig) { |
782 case kA1_Config: { | |
783 uint8_t* p = this->getAddr1(area.fLeft, area.fTop); | |
784 const int left = area.fLeft >> 3; | |
785 const int right = area.fRight >> 3; | |
786 | |
787 int middle = right - left - 1; | |
788 | |
789 uint8_t leftMask = 0xFF >> (area.fLeft & 7); | |
790 uint8_t rightMask = ~(0xFF >> (area.fRight & 7)); | |
791 if (left == right) { | |
792 leftMask &= rightMask; | |
793 rightMask = 0; | |
794 } | |
795 | |
796 a = (a >> 7) ? 0xFF : 0; | |
797 while (--height >= 0) { | |
798 uint8_t* startP = p; | |
799 | |
800 *p = (*p & ~leftMask) | (a & leftMask); | |
801 p++; | |
802 if (middle > 0) { | |
803 memset(p, a, middle); | |
804 p += middle; | |
805 } | |
806 if (rightMask) { | |
807 *p = (*p & ~rightMask) | (a & rightMask); | |
808 } | |
809 | |
810 p = startP + rowBytes; | |
811 } | |
812 break; | |
813 } | |
814 case kA8_Config: { | 764 case kA8_Config: { |
815 uint8_t* p = this->getAddr8(area.fLeft, area.fTop); | 765 uint8_t* p = this->getAddr8(area.fLeft, area.fTop); |
816 while (--height >= 0) { | 766 while (--height >= 0) { |
817 memset(p, a, width); | 767 memset(p, a, width); |
818 p += rowBytes; | 768 p += rowBytes; |
819 } | 769 } |
820 break; | 770 break; |
821 } | 771 } |
822 case kARGB_4444_Config: | 772 case kARGB_4444_Config: |
823 case kRGB_565_Config: { | 773 case kRGB_565_Config: { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
889 case SkBitmap::kRGB_565_Config: | 839 case SkBitmap::kRGB_565_Config: |
890 case SkBitmap::kARGB_4444_Config: | 840 case SkBitmap::kARGB_4444_Config: |
891 x <<= 1; | 841 x <<= 1; |
892 break; | 842 break; |
893 | 843 |
894 case SkBitmap::kARGB_8888_Config: | 844 case SkBitmap::kARGB_8888_Config: |
895 x <<= 2; | 845 x <<= 2; |
896 break; | 846 break; |
897 | 847 |
898 case SkBitmap::kNo_Config: | 848 case SkBitmap::kNo_Config: |
899 case SkBitmap::kA1_Config: | |
900 default: | 849 default: |
901 return SUB_OFFSET_FAILURE; | 850 return SUB_OFFSET_FAILURE; |
902 } | 851 } |
903 return y * bm.rowBytes() + x; | 852 return y * bm.rowBytes() + x; |
904 } | 853 } |
905 | 854 |
906 /** | 855 /** |
907 * Using the pixelRefOffset(), rowBytes(), and Config of bm, determine the (x,
y) coordinate of the | 856 * Using the pixelRefOffset(), rowBytes(), and Config of bm, determine the (x,
y) coordinate of the |
908 * upper left corner of bm relative to its SkPixelRef. | 857 * upper left corner of bm relative to its SkPixelRef. |
909 * x and y must be non-NULL. | 858 * x and y must be non-NULL. |
(...skipping 22 matching lines...) Expand all Loading... |
932 case SkBitmap::kARGB_4444_Config: | 881 case SkBitmap::kARGB_4444_Config: |
933 *x >>= 1; | 882 *x >>= 1; |
934 break; | 883 break; |
935 | 884 |
936 case SkBitmap::kARGB_8888_Config: | 885 case SkBitmap::kARGB_8888_Config: |
937 *x >>= 2; | 886 *x >>= 2; |
938 break; | 887 break; |
939 | 888 |
940 case SkBitmap::kNo_Config: | 889 case SkBitmap::kNo_Config: |
941 // Fall through. | 890 // Fall through. |
942 case SkBitmap::kA1_Config: | |
943 // Fall through. | |
944 default: | 891 default: |
945 return false; | 892 return false; |
946 } | 893 } |
947 return true; | 894 return true; |
948 } | 895 } |
949 | 896 |
950 static bool get_upper_left_from_offset(const SkBitmap& bm, int32_t* x, int32_t*
y) { | 897 static bool get_upper_left_from_offset(const SkBitmap& bm, int32_t* x, int32_t*
y) { |
951 return get_upper_left_from_offset(bm.config(), bm.pixelRefOffset(), bm.rowBy
tes(), x, y); | 898 return get_upper_left_from_offset(bm.config(), bm.pixelRefOffset(), bm.rowBy
tes(), x, y); |
952 } | 899 } |
953 | 900 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1014 if (this->config() == kNo_Config) { | 961 if (this->config() == kNo_Config) { |
1015 return false; | 962 return false; |
1016 } | 963 } |
1017 | 964 |
1018 bool sameConfigs = (this->config() == dstConfig); | 965 bool sameConfigs = (this->config() == dstConfig); |
1019 switch (dstConfig) { | 966 switch (dstConfig) { |
1020 case kA8_Config: | 967 case kA8_Config: |
1021 case kRGB_565_Config: | 968 case kRGB_565_Config: |
1022 case kARGB_8888_Config: | 969 case kARGB_8888_Config: |
1023 break; | 970 break; |
1024 case kA1_Config: | |
1025 case kIndex8_Config: | 971 case kIndex8_Config: |
1026 if (!sameConfigs) { | 972 if (!sameConfigs) { |
1027 return false; | 973 return false; |
1028 } | 974 } |
1029 break; | 975 break; |
1030 case kARGB_4444_Config: | 976 case kARGB_4444_Config: |
1031 return sameConfigs || kARGB_8888_Config == this->config(); | 977 return sameConfigs || kARGB_8888_Config == this->config(); |
1032 default: | 978 default: |
1033 return false; | 979 return false; |
1034 } | 980 } |
1035 | |
1036 // do not copy src if srcConfig == kA1_Config while dstConfig != kA1_Config | |
1037 if (this->config() == kA1_Config && !sameConfigs) { | |
1038 return false; | |
1039 } | |
1040 | |
1041 return true; | 981 return true; |
1042 } | 982 } |
1043 | 983 |
1044 bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const { | 984 bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const { |
1045 if (!this->canCopyTo(dstConfig)) { | 985 if (!this->canCopyTo(dstConfig)) { |
1046 return false; | 986 return false; |
1047 } | 987 } |
1048 | 988 |
1049 // if we have a texture, first get those pixels | 989 // if we have a texture, first get those pixels |
1050 SkBitmap tmpSrc; | 990 SkBitmap tmpSrc; |
(...skipping 623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1674 } | 1614 } |
1675 } | 1615 } |
1676 #endif | 1616 #endif |
1677 } | 1617 } |
1678 #endif | 1618 #endif |
1679 | 1619 |
1680 #ifdef SK_DEVELOPER | 1620 #ifdef SK_DEVELOPER |
1681 void SkBitmap::toString(SkString* str) const { | 1621 void SkBitmap::toString(SkString* str) const { |
1682 | 1622 |
1683 static const char* gConfigNames[kConfigCount] = { | 1623 static const char* gConfigNames[kConfigCount] = { |
1684 "NONE", "A1", "A8", "INDEX8", "565", "4444", "8888" | 1624 "NONE", "A8", "INDEX8", "565", "4444", "8888" |
1685 }; | 1625 }; |
1686 | 1626 |
1687 str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(), | 1627 str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(), |
1688 gConfigNames[this->config()]); | 1628 gConfigNames[this->config()]); |
1689 | 1629 |
1690 str->append(" ("); | 1630 str->append(" ("); |
1691 if (this->isOpaque()) { | 1631 if (this->isOpaque()) { |
1692 str->append("opaque"); | 1632 str->append("opaque"); |
1693 } else { | 1633 } else { |
1694 str->append("transparent"); | 1634 str->append("transparent"); |
(...skipping 14 matching lines...) Expand all Loading... |
1709 if (NULL != uri) { | 1649 if (NULL != uri) { |
1710 str->appendf(" uri:\"%s\"", uri); | 1650 str->appendf(" uri:\"%s\"", uri); |
1711 } else { | 1651 } else { |
1712 str->appendf(" pixelref:%p", pr); | 1652 str->appendf(" pixelref:%p", pr); |
1713 } | 1653 } |
1714 } | 1654 } |
1715 | 1655 |
1716 str->append(")"); | 1656 str->append(")"); |
1717 } | 1657 } |
1718 #endif | 1658 #endif |
OLD | NEW |