aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Mike Klein <mtklein@chromium.org>2018-03-06 08:43:22 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-03-06 19:43:46 +0000
commit18e9ba1eddb09bff6083f9a83dc569d3b3b54fe6 (patch)
tree7a7808805687ae43f56a678acc57e1b0fae33f5f
parent94458ee0f2be19392042084f181b41308ae63624 (diff)
support 888x, 1010102, and 101010x in SkPixmap::erase()
... and a few more methods to make it possible to write the new test. Bug: oss-fuzz:6606 Change-Id: Ie8dd221059579248405f165a93c324c8ba518fd4 Reviewed-on: https://skia-review.googlesource.com/112400 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Mike Klein <mtklein@chromium.org>
-rw-r--r--src/core/SkBitmap.cpp3
-rw-r--r--src/core/SkPixmap.cpp69
-rw-r--r--tests/BitmapTest.cpp31
3 files changed, 98 insertions, 5 deletions
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index 7223fdb828..a9d5fe8963 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -384,8 +384,11 @@ void* SkBitmap::getAddr(int x, int y) const {
case kRGBA_F16_SkColorType:
base += x << 3;
break;
+ case kRGB_888x_SkColorType:
case kRGBA_8888_SkColorType:
case kBGRA_8888_SkColorType:
+ case kRGB_101010x_SkColorType:
+ case kRGBA_1010102_SkColorType:
base += x << 2;
break;
case kARGB_4444_SkColorType:
diff --git a/src/core/SkPixmap.cpp b/src/core/SkPixmap.cpp
index 19d1d65caa..852ffb0b33 100644
--- a/src/core/SkPixmap.cpp
+++ b/src/core/SkPixmap.cpp
@@ -150,6 +150,7 @@ bool SkPixmap::erase(SkColor color, const SkIRect& inArea) const {
}
break;
}
+
case kARGB_4444_SkColorType:
case kRGB_565_SkColorType: {
uint16_t* p = this->writable_addr16(area.fLeft, area.fTop);
@@ -175,8 +176,11 @@ bool SkPixmap::erase(SkColor color, const SkIRect& inArea) const {
}
break;
}
- case kBGRA_8888_SkColorType:
- case kRGBA_8888_SkColorType: {
+
+ case kRGB_888x_SkColorType:
+ a = 255; // then fallthrough to 8888
+ case kRGBA_8888_SkColorType:
+ case kBGRA_8888_SkColorType: {
uint32_t* p = this->writable_addr32(area.fLeft, area.fTop);
if (255 != a && kPremul_SkAlphaType == this->alphaType()) {
@@ -184,16 +188,42 @@ bool SkPixmap::erase(SkColor color, const SkIRect& inArea) const {
g = SkMulDiv255Round(g, a);
b = SkMulDiv255Round(b, a);
}
- uint32_t v = kRGBA_8888_SkColorType == this->colorType()
- ? SkPackARGB_as_RGBA(a, r, g, b)
- : SkPackARGB_as_BGRA(a, r, g, b);
+ uint32_t v = kBGRA_8888_SkColorType == this->colorType()
+ ? SkPackARGB_as_BGRA(a, r, g, b) // bgra 8888
+ : SkPackARGB_as_RGBA(a, r, g, b); // rgba 8888 or rgb 888
+
+ while (--height >= 0) {
+ sk_memset32(p, v, width);
+ p = (uint32_t*)((char*)p + rowBytes);
+ }
+ break;
+ }
+ case kRGB_101010x_SkColorType:
+ a = 255; // then fallthrough to 1010102
+ case kRGBA_1010102_SkColorType: {
+ uint32_t* p = this->writable_addr32(area.fLeft, area.fTop);
+
+ float R = r * (1/255.0f),
+ G = g * (1/255.0f),
+ B = b * (1/255.0f),
+ A = a * (1/255.0f);
+ if (a != 255 && this->alphaType() == kPremul_SkAlphaType) {
+ R *= A;
+ G *= A;
+ B *= A;
+ }
+ uint32_t v = (uint32_t)(R * 1023.0f) << 0
+ | (uint32_t)(G * 1023.0f) << 10
+ | (uint32_t)(B * 1023.0f) << 20
+ | (uint32_t)(A * 3.0f) << 30;
while (--height >= 0) {
sk_memset32(p, v, width);
p = (uint32_t*)((char*)p + rowBytes);
}
break;
}
+
case kRGBA_F16_SkColorType:
// The colorspace is unspecified, so assume linear just like getColor().
this->erase(SkColor4f{(1 / 255.0f) * r,
@@ -321,6 +351,10 @@ SkColor SkPixmap::getColor(int x, int y) const {
SkPMColor c = SkPixel4444ToPixel32(value);
return toColor(c);
}
+ case kRGB_888x_SkColorType: {
+ uint32_t value = *this->addr32(x, y);
+ return SkSwizzle_RB(value | 0xff000000);
+ }
case kBGRA_8888_SkColorType: {
uint32_t value = *this->addr32(x, y);
SkPMColor c = SkSwizzle_BGRA_to_PMColor(value);
@@ -331,6 +365,31 @@ SkColor SkPixmap::getColor(int x, int y) const {
SkPMColor c = SkSwizzle_RGBA_to_PMColor(value);
return toColor(c);
}
+ case kRGB_101010x_SkColorType: {
+ uint32_t value = *this->addr32(x, y);
+ // Convert 10-bit rgb to 8-bit bgr, and mask in 0xff alpha at the top.
+ return (uint32_t)( ((value >> 0) & 0x3ff) * (255/1023.0f) ) << 16
+ | (uint32_t)( ((value >> 10) & 0x3ff) * (255/1023.0f) ) << 8
+ | (uint32_t)( ((value >> 20) & 0x3ff) * (255/1023.0f) ) << 0
+ | 0xff000000;
+ }
+ case kRGBA_1010102_SkColorType: {
+ uint32_t value = *this->addr32(x, y);
+
+ float r = ((value >> 0) & 0x3ff) * (1/1023.0f),
+ g = ((value >> 10) & 0x3ff) * (1/1023.0f),
+ b = ((value >> 20) & 0x3ff) * (1/1023.0f),
+ a = ((value >> 30) & 0x3 ) * (1/ 3.0f);
+ if (a != 0 && needsUnpremul) {
+ r *= (1.0f/a);
+ g *= (1.0f/a);
+ b *= (1.0f/a);
+ }
+ return (uint32_t)( r * 255.0f ) << 16
+ | (uint32_t)( g * 255.0f ) << 8
+ | (uint32_t)( b * 255.0f ) << 0
+ | (uint32_t)( a * 255.0f ) << 24;
+ }
case kRGBA_F16_SkColorType: {
const uint64_t* addr =
(const uint64_t*)fPixels + y * (fRowBytes >> 3) + x;
diff --git a/tests/BitmapTest.cpp b/tests/BitmapTest.cpp
index f62288cd22..b4049387ff 100644
--- a/tests/BitmapTest.cpp
+++ b/tests/BitmapTest.cpp
@@ -226,3 +226,34 @@ DEF_TEST(Bitmap_clear_pixelref_keep_info, r) {
SkDEBUGCODE(bm.validate();)
}
+// At the time of writing, SkBitmap::erase() works when the color is zero for all formats,
+// but some formats failed when the color is non-zero!
+DEF_TEST(Bitmap_erase, r) {
+ SkColorType colorTypes[] = {
+ kRGB_565_SkColorType,
+ kARGB_4444_SkColorType,
+ kRGB_888x_SkColorType,
+ kRGBA_8888_SkColorType,
+ kBGRA_8888_SkColorType,
+ kRGB_101010x_SkColorType,
+ kRGBA_1010102_SkColorType,
+ };
+
+ for (SkColorType ct : colorTypes) {
+ SkImageInfo info = SkImageInfo::Make(1,1, (SkColorType)ct, kPremul_SkAlphaType);
+
+ SkBitmap bm;
+ bm.allocPixels(info);
+
+ bm.eraseColor(0x00000000);
+ if (SkColorTypeIsAlwaysOpaque(ct)) {
+ REPORTER_ASSERT(r, bm.getColor(0,0) == 0xff000000);
+ } else {
+ REPORTER_ASSERT(r, bm.getColor(0,0) == 0x00000000);
+ }
+
+ bm.eraseColor(0xaabbccdd);
+ REPORTER_ASSERT(r, bm.getColor(0,0) != 0xff000000);
+ REPORTER_ASSERT(r, bm.getColor(0,0) != 0x00000000);
+ }
+}