diff options
author | Mike Klein <mtklein@chromium.org> | 2018-03-06 08:43:22 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-03-06 19:43:46 +0000 |
commit | 18e9ba1eddb09bff6083f9a83dc569d3b3b54fe6 (patch) | |
tree | 7a7808805687ae43f56a678acc57e1b0fae33f5f | |
parent | 94458ee0f2be19392042084f181b41308ae63624 (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.cpp | 3 | ||||
-rw-r--r-- | src/core/SkPixmap.cpp | 69 | ||||
-rw-r--r-- | tests/BitmapTest.cpp | 31 |
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); + } +} |