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 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
261 SkIntToScalar(fWidth), SkIntToScalar(fHeight)); | 261 SkIntToScalar(fWidth), SkIntToScalar(fHeight)); |
262 } | 262 } |
263 | 263 |
264 void SkBitmap::getBounds(SkIRect* bounds) const { | 264 void SkBitmap::getBounds(SkIRect* bounds) const { |
265 SkASSERT(bounds); | 265 SkASSERT(bounds); |
266 bounds->set(0, 0, fWidth, fHeight); | 266 bounds->set(0, 0, fWidth, fHeight); |
267 } | 267 } |
268 | 268 |
269 /////////////////////////////////////////////////////////////////////////////// | 269 /////////////////////////////////////////////////////////////////////////////// |
270 | 270 |
271 void SkBitmap::setConfig(Config c, int width, int height, size_t rowBytes) { | 271 void SkBitmap::setConfig(Config c, int width, int height, size_t rowBytes, |
| 272 bool premul) { |
272 this->freePixels(); | 273 this->freePixels(); |
273 | 274 |
274 if ((width | height) < 0) { | 275 if ((width | height) < 0) { |
275 goto err; | 276 goto err; |
276 } | 277 } |
277 | 278 |
278 if (rowBytes == 0) { | 279 if (rowBytes == 0) { |
279 rowBytes = SkBitmap::ComputeRowBytes(c, width); | 280 rowBytes = SkBitmap::ComputeRowBytes(c, width); |
280 if (0 == rowBytes && kNo_Config != c) { | 281 if (0 == rowBytes && kNo_Config != c) { |
281 goto err; | 282 goto err; |
282 } | 283 } |
283 } | 284 } |
284 | 285 |
285 fConfig = SkToU8(c); | 286 fConfig = SkToU8(c); |
286 fWidth = width; | 287 fWidth = width; |
287 fHeight = height; | 288 fHeight = height; |
288 fRowBytes = SkToU32(rowBytes); | 289 fRowBytes = SkToU32(rowBytes); |
| 290 if (premul) { |
| 291 fFlags &= ~kColorsAreNotPremultiplied_Flag; |
| 292 } else { |
| 293 if (c != kARGB_8888_Config) { |
| 294 goto err; |
| 295 } |
| 296 fFlags |= kColorsAreNotPremultiplied_Flag; |
| 297 } |
289 | 298 |
290 fBytesPerPixel = (uint8_t)ComputeBytesPerPixel(c); | 299 fBytesPerPixel = (uint8_t)ComputeBytesPerPixel(c); |
291 | 300 |
292 SkDEBUGCODE(this->validate();) | 301 SkDEBUGCODE(this->validate();) |
293 return; | 302 return; |
294 | 303 |
295 // if we got here, we had an error, so we reset the bitmap to empty | 304 // if we got here, we had an error, so we reset the bitmap to empty |
296 err: | 305 err: |
297 this->reset(); | 306 this->reset(); |
298 } | 307 } |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
644 case SkBitmap::kRGB_565_Config: { | 653 case SkBitmap::kRGB_565_Config: { |
645 uint16_t* addr = this->getAddr16(x, y); | 654 uint16_t* addr = this->getAddr16(x, y); |
646 return SkPixel16ToColor(addr[0]); | 655 return SkPixel16ToColor(addr[0]); |
647 } | 656 } |
648 case SkBitmap::kARGB_4444_Config: { | 657 case SkBitmap::kARGB_4444_Config: { |
649 uint16_t* addr = this->getAddr16(x, y); | 658 uint16_t* addr = this->getAddr16(x, y); |
650 SkPMColor c = SkPixel4444ToPixel32(addr[0]); | 659 SkPMColor c = SkPixel4444ToPixel32(addr[0]); |
651 return SkUnPreMultiply::PMColorToColor(c); | 660 return SkUnPreMultiply::PMColorToColor(c); |
652 } | 661 } |
653 case SkBitmap::kARGB_8888_Config: { | 662 case SkBitmap::kARGB_8888_Config: { |
654 uint32_t* addr = this->getAddr32(x, y); | 663 if (this->premultiplied()) { |
655 return SkUnPreMultiply::PMColorToColor(addr[0]); | 664 uint32_t* addr = this->getAddr32(x, y); |
| 665 return SkUnPreMultiply::PMColorToColor(addr[0]); |
| 666 } else { |
| 667 SkUnPMColor* addr = this->getAddr32(x, y); |
| 668 SkUnPMColor c = *addr; |
| 669 U8CPU a = SkGetPackedA32(c); |
| 670 U8CPU r = SkGetPackedR32(c); |
| 671 U8CPU g = SkGetPackedG32(c); |
| 672 U8CPU b = SkGetPackedB32(c); |
| 673 return SkColorSetARGB(a, r, g, b); |
| 674 } |
656 } | 675 } |
657 case kRLE_Index8_Config: { | 676 case kRLE_Index8_Config: { |
658 uint8_t dst; | 677 uint8_t dst; |
659 const SkBitmap::RLEPixels* rle = | 678 const SkBitmap::RLEPixels* rle = |
660 (const SkBitmap::RLEPixels*)this->getPixels(); | 679 (const SkBitmap::RLEPixels*)this->getPixels(); |
661 SkPackBits::Unpack8(&dst, x, 1, rle->packedAtY(y)); | 680 SkPackBits::Unpack8(&dst, x, 1, rle->packedAtY(y)); |
662 return SkUnPreMultiply::PMColorToColor((*fColorTable)[dst]); | 681 return SkUnPreMultiply::PMColorToColor((*fColorTable)[dst]); |
663 } | 682 } |
664 case kNo_Config: | 683 case kNo_Config: |
665 case kConfigCount: | 684 case kConfigCount: |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
761 if (!this->readyToDraw()) { | 780 if (!this->readyToDraw()) { |
762 return; | 781 return; |
763 } | 782 } |
764 | 783 |
765 int height = fHeight; | 784 int height = fHeight; |
766 const int width = fWidth; | 785 const int width = fWidth; |
767 const int rowBytes = fRowBytes; | 786 const int rowBytes = fRowBytes; |
768 | 787 |
769 // make rgb premultiplied | 788 // make rgb premultiplied |
770 if (255 != a) { | 789 if (255 != a) { |
| 790 // Unpremultiplied exits above at readyToDraw. |
| 791 SkASSERT(this->premultiplied()); |
771 r = SkAlphaMul(r, a); | 792 r = SkAlphaMul(r, a); |
772 g = SkAlphaMul(g, a); | 793 g = SkAlphaMul(g, a); |
773 b = SkAlphaMul(b, a); | 794 b = SkAlphaMul(b, a); |
774 } | 795 } |
775 | 796 |
776 switch (fConfig) { | 797 switch (fConfig) { |
777 case kA1_Config: { | 798 case kA1_Config: { |
778 uint8_t* p = (uint8_t*)fPixels; | 799 uint8_t* p = (uint8_t*)fPixels; |
779 const int count = (width + 7) >> 3; | 800 const int count = (width + 7) >> 3; |
780 a = (a >> 7) ? 0xFF : 0; | 801 a = (a >> 7) ? 0xFF : 0; |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
921 srcRect.set(0, 0, this->width(), this->height()); | 942 srcRect.set(0, 0, this->width(), this->height()); |
922 if (!r.intersect(srcRect, subset)) { | 943 if (!r.intersect(srcRect, subset)) { |
923 return false; // r is empty (i.e. no intersection) | 944 return false; // r is empty (i.e. no intersection) |
924 } | 945 } |
925 | 946 |
926 if (fPixelRef->getTexture() != NULL) { | 947 if (fPixelRef->getTexture() != NULL) { |
927 // Do a deep copy | 948 // Do a deep copy |
928 SkPixelRef* pixelRef = fPixelRef->deepCopy(this->config(), &subset); | 949 SkPixelRef* pixelRef = fPixelRef->deepCopy(this->config(), &subset); |
929 if (pixelRef != NULL) { | 950 if (pixelRef != NULL) { |
930 SkBitmap dst; | 951 SkBitmap dst; |
931 dst.setConfig(this->config(), subset.width(), subset.height()); | 952 dst.setConfig(this->config(), subset.width(), subset.height(), 0, |
| 953 this->premultiplied()); |
932 dst.setIsVolatile(this->isVolatile()); | 954 dst.setIsVolatile(this->isVolatile()); |
933 dst.setIsOpaque(this->isOpaque()); | 955 dst.setIsOpaque(this->isOpaque()); |
934 dst.setPixelRef(pixelRef)->unref(); | 956 dst.setPixelRef(pixelRef)->unref(); |
935 SkDEBUGCODE(dst.validate()); | 957 SkDEBUGCODE(dst.validate()); |
936 result->swap(dst); | 958 result->swap(dst); |
937 return true; | 959 return true; |
938 } | 960 } |
939 } | 961 } |
940 | 962 |
941 if (kRLE_Index8_Config == fConfig) { | 963 if (kRLE_Index8_Config == fConfig) { |
942 SkAutoLockPixels alp(*this); | 964 SkAutoLockPixels alp(*this); |
943 // don't call readyToDraw(), since we can operate w/o a colortable | 965 // don't call readyToDraw(), since we can operate w/o a colortable |
944 // at this stage | 966 // at this stage |
945 if (this->getPixels() == NULL) { | 967 if (this->getPixels() == NULL) { |
946 return false; | 968 return false; |
947 } | 969 } |
948 SkBitmap bm; | 970 SkBitmap bm; |
949 | 971 |
| 972 // kRLE_Index8_Config is not compatible with unpremultiplied. |
| 973 SkASSERT(this->premultiplied()); |
950 bm.setConfig(kIndex8_Config, r.width(), r.height()); | 974 bm.setConfig(kIndex8_Config, r.width(), r.height()); |
951 bm.allocPixels(this->getColorTable()); | 975 bm.allocPixels(this->getColorTable()); |
952 if (NULL == bm.getPixels()) { | 976 if (NULL == bm.getPixels()) { |
953 return false; | 977 return false; |
954 } | 978 } |
955 | 979 |
956 const RLEPixels* rle = (const RLEPixels*)this->getPixels(); | 980 const RLEPixels* rle = (const RLEPixels*)this->getPixels(); |
957 uint8_t* dst = bm.getAddr8(0, 0); | 981 uint8_t* dst = bm.getAddr8(0, 0); |
958 const int width = bm.width(); | 982 const int width = bm.width(); |
959 const size_t rowBytes = bm.rowBytes(); | 983 const size_t rowBytes = bm.rowBytes(); |
(...skipping 10 matching lines...) Expand all Loading... |
970 // exited above. | 994 // exited above. |
971 SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width(
))); | 995 SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width(
))); |
972 SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height(
))); | 996 SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height(
))); |
973 | 997 |
974 size_t offset = get_sub_offset(*this, r.fLeft, r.fTop); | 998 size_t offset = get_sub_offset(*this, r.fLeft, r.fTop); |
975 if (SUB_OFFSET_FAILURE == offset) { | 999 if (SUB_OFFSET_FAILURE == offset) { |
976 return false; // config not supported | 1000 return false; // config not supported |
977 } | 1001 } |
978 | 1002 |
979 SkBitmap dst; | 1003 SkBitmap dst; |
980 dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes()); | 1004 dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes(), this-
>premultiplied()); |
981 dst.setIsVolatile(this->isVolatile()); | 1005 dst.setIsVolatile(this->isVolatile()); |
982 dst.setIsOpaque(this->isOpaque()); | 1006 dst.setIsOpaque(this->isOpaque()); |
983 | 1007 |
984 if (fPixelRef) { | 1008 if (fPixelRef) { |
985 // share the pixelref with a custom offset | 1009 // share the pixelref with a custom offset |
986 dst.setPixelRef(fPixelRef, fPixelRefOffset + offset); | 1010 dst.setPixelRef(fPixelRef, fPixelRefOffset + offset); |
987 } | 1011 } |
988 SkDEBUGCODE(dst.validate();) | 1012 SkDEBUGCODE(dst.validate();) |
989 | 1013 |
990 // we know we're good, so commit to result | 1014 // we know we're good, so commit to result |
(...skipping 26 matching lines...) Expand all Loading... |
1017 break; | 1041 break; |
1018 default: | 1042 default: |
1019 return false; | 1043 return false; |
1020 } | 1044 } |
1021 | 1045 |
1022 // do not copy src if srcConfig == kA1_Config while dstConfig != kA1_Config | 1046 // do not copy src if srcConfig == kA1_Config while dstConfig != kA1_Config |
1023 if (this->getConfig() == kA1_Config && !sameConfigs) { | 1047 if (this->getConfig() == kA1_Config && !sameConfigs) { |
1024 return false; | 1048 return false; |
1025 } | 1049 } |
1026 | 1050 |
| 1051 if (!this->premultiplied()) { |
| 1052 // Cannot copy unpremultiplied, which returns false for readyToDraw. |
| 1053 SkASSERT(kARGB_8888_Config == this->config()); |
| 1054 return false; |
| 1055 } |
| 1056 |
1027 return true; | 1057 return true; |
1028 } | 1058 } |
1029 | 1059 |
1030 bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const { | 1060 bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const { |
1031 if (!this->canCopyTo(dstConfig)) { | 1061 if (!this->canCopyTo(dstConfig)) { |
1032 return false; | 1062 return false; |
1033 } | 1063 } |
| 1064 // Cannot copy an unpremultiplied bitmap. |
| 1065 // canCopyTo should have returned false. |
| 1066 SkASSERT(this->premultiplied()); |
1034 | 1067 |
1035 // if we have a texture, first get those pixels | 1068 // if we have a texture, first get those pixels |
1036 SkBitmap tmpSrc; | 1069 SkBitmap tmpSrc; |
1037 const SkBitmap* src = this; | 1070 const SkBitmap* src = this; |
1038 | 1071 |
1039 if (fPixelRef) { | 1072 if (fPixelRef) { |
1040 SkIRect subset; | 1073 SkIRect subset; |
1041 if (get_upper_left_from_offset(*this, &subset.fLeft, &subset.fTop)) { | 1074 if (get_upper_left_from_offset(*this, &subset.fLeft, &subset.fTop)) { |
1042 subset.fRight = subset.fLeft + fWidth; | 1075 subset.fRight = subset.fLeft + fWidth; |
1043 subset.fBottom = subset.fTop + fHeight; | 1076 subset.fBottom = subset.fTop + fHeight; |
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1557 enum { | 1590 enum { |
1558 SERIALIZE_PIXELTYPE_NONE, | 1591 SERIALIZE_PIXELTYPE_NONE, |
1559 SERIALIZE_PIXELTYPE_REF_DATA | 1592 SERIALIZE_PIXELTYPE_REF_DATA |
1560 }; | 1593 }; |
1561 | 1594 |
1562 void SkBitmap::flatten(SkFlattenableWriteBuffer& buffer) const { | 1595 void SkBitmap::flatten(SkFlattenableWriteBuffer& buffer) const { |
1563 buffer.writeInt(fWidth); | 1596 buffer.writeInt(fWidth); |
1564 buffer.writeInt(fHeight); | 1597 buffer.writeInt(fHeight); |
1565 buffer.writeInt(fRowBytes); | 1598 buffer.writeInt(fRowBytes); |
1566 buffer.writeInt(fConfig); | 1599 buffer.writeInt(fConfig); |
| 1600 #ifdef BUMP_PICTURE_VERSION |
| 1601 // FIXME: Storing whether the colors are premultiplied |
| 1602 // should be written to the stream, but breaks picture |
| 1603 // serialization without changing PICTURE_VERSION |
| 1604 buffer.writeBool(this->premultiplied()); |
| 1605 #endif |
1567 buffer.writeBool(this->isOpaque()); | 1606 buffer.writeBool(this->isOpaque()); |
1568 | 1607 |
1569 if (fPixelRef) { | 1608 if (fPixelRef) { |
1570 if (fPixelRef->getFactory()) { | 1609 if (fPixelRef->getFactory()) { |
1571 buffer.writeInt(SERIALIZE_PIXELTYPE_REF_DATA); | 1610 buffer.writeInt(SERIALIZE_PIXELTYPE_REF_DATA); |
1572 buffer.writeUInt(SkToU32(fPixelRefOffset)); | 1611 buffer.writeUInt(SkToU32(fPixelRefOffset)); |
1573 buffer.writeFlattenable(fPixelRef); | 1612 buffer.writeFlattenable(fPixelRef); |
1574 return; | 1613 return; |
1575 } | 1614 } |
1576 // if we get here, we can't record the pixels | 1615 // if we get here, we can't record the pixels |
1577 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE); | 1616 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE); |
1578 } else { | 1617 } else { |
1579 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE); | 1618 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE); |
1580 } | 1619 } |
1581 } | 1620 } |
1582 | 1621 |
1583 void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) { | 1622 void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) { |
1584 this->reset(); | 1623 this->reset(); |
1585 | 1624 |
1586 int width = buffer.readInt(); | 1625 int width = buffer.readInt(); |
1587 int height = buffer.readInt(); | 1626 int height = buffer.readInt(); |
1588 int rowBytes = buffer.readInt(); | 1627 int rowBytes = buffer.readInt(); |
1589 int config = buffer.readInt(); | 1628 int config = buffer.readInt(); |
| 1629 #ifdef BUMP_PICTURE_VERSION |
| 1630 bool premul = buffer.readBool(); |
| 1631 #else |
| 1632 bool premul = true; |
| 1633 #endif |
1590 | 1634 |
1591 this->setConfig((Config)config, width, height, rowBytes); | 1635 this->setConfig((Config)config, width, height, rowBytes, premul); |
1592 this->setIsOpaque(buffer.readBool()); | 1636 this->setIsOpaque(buffer.readBool()); |
1593 | 1637 |
1594 int reftype = buffer.readInt(); | 1638 int reftype = buffer.readInt(); |
1595 switch (reftype) { | 1639 switch (reftype) { |
1596 case SERIALIZE_PIXELTYPE_REF_DATA: { | 1640 case SERIALIZE_PIXELTYPE_REF_DATA: { |
1597 size_t offset = buffer.readUInt(); | 1641 size_t offset = buffer.readUInt(); |
1598 SkPixelRef* pr = buffer.readFlattenableT<SkPixelRef>(); | 1642 SkPixelRef* pr = buffer.readFlattenableT<SkPixelRef>(); |
1599 SkSafeUnref(this->setPixelRef(pr, offset)); | 1643 SkSafeUnref(this->setPixelRef(pr, offset)); |
1600 break; | 1644 break; |
1601 } | 1645 } |
(...skipping 16 matching lines...) Expand all Loading... |
1618 SkBitmap::RLEPixels::~RLEPixels() { | 1662 SkBitmap::RLEPixels::~RLEPixels() { |
1619 sk_free(fYPtrs); | 1663 sk_free(fYPtrs); |
1620 } | 1664 } |
1621 | 1665 |
1622 /////////////////////////////////////////////////////////////////////////////// | 1666 /////////////////////////////////////////////////////////////////////////////// |
1623 | 1667 |
1624 #ifdef SK_DEBUG | 1668 #ifdef SK_DEBUG |
1625 void SkBitmap::validate() const { | 1669 void SkBitmap::validate() const { |
1626 SkASSERT(fConfig < kConfigCount); | 1670 SkASSERT(fConfig < kConfigCount); |
1627 SkASSERT(fRowBytes >= (unsigned)ComputeRowBytes((Config)fConfig, fWidth)); | 1671 SkASSERT(fRowBytes >= (unsigned)ComputeRowBytes((Config)fConfig, fWidth)); |
1628 SkASSERT(fFlags <= (kImageIsOpaque_Flag | kImageIsVolatile_Flag | kImageIsIm
mutable_Flag)); | 1672 int8_t allFlags = kImageIsOpaque_Flag | kImageIsVolatile_Flag | kImageIsImmu
table_Flag |
| 1673 | kColorsAreNotPremultiplied_Flag; |
| 1674 #ifdef SK_BUILD_FOR_ANDROID |
| 1675 allFlags |= kHasHardwareMipMap_Flag; |
| 1676 #endif |
| 1677 SkASSERT(fFlags <= allFlags); |
1629 SkASSERT(fPixelLockCount >= 0); | 1678 SkASSERT(fPixelLockCount >= 0); |
1630 SkASSERT(NULL == fColorTable || (unsigned)fColorTable->getRefCnt() < 10000); | 1679 SkASSERT(NULL == fColorTable || (unsigned)fColorTable->getRefCnt() < 10000); |
1631 SkASSERT((uint8_t)ComputeBytesPerPixel((Config)fConfig) == fBytesPerPixel); | 1680 SkASSERT((uint8_t)ComputeBytesPerPixel((Config)fConfig) == fBytesPerPixel); |
1632 | 1681 |
1633 #if 0 // these asserts are not thread-correct, so disable for now | 1682 #if 0 // these asserts are not thread-correct, so disable for now |
1634 if (fPixelRef) { | 1683 if (fPixelRef) { |
1635 if (fPixelLockCount > 0) { | 1684 if (fPixelLockCount > 0) { |
1636 SkASSERT(fPixelRef->isLocked()); | 1685 SkASSERT(fPixelRef->isLocked()); |
1637 } else { | 1686 } else { |
1638 SkASSERT(NULL == fPixels); | 1687 SkASSERT(NULL == fPixels); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1675 if (NULL != uri) { | 1724 if (NULL != uri) { |
1676 str->appendf(" uri:\"%s\"", uri); | 1725 str->appendf(" uri:\"%s\"", uri); |
1677 } else { | 1726 } else { |
1678 str->appendf(" pixelref:%p", pr); | 1727 str->appendf(" pixelref:%p", pr); |
1679 } | 1728 } |
1680 } | 1729 } |
1681 | 1730 |
1682 str->append(")"); | 1731 str->append(")"); |
1683 } | 1732 } |
1684 #endif | 1733 #endif |
OLD | NEW |