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>
This commit is contained in:
Mike Klein 2018-03-06 08:43:22 -05:00 committed by Skia Commit-Bot
parent 94458ee0f2
commit 18e9ba1edd
3 changed files with 98 additions and 5 deletions

View File

@ -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:

View File

@ -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,9 +188,9 @@ 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);
@ -194,6 +198,32 @@ bool SkPixmap::erase(SkColor color, const SkIRect& inArea) const {
}
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;

View File

@ -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);
}
}