Index: src/core/SkBitmap.cpp |
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp |
index f164ca570a46101ae85b673be8daab489ac958bc..07fbe12d2163262c531b35ddca3039bf9bc87602 100644 |
--- a/src/core/SkBitmap.cpp |
+++ b/src/core/SkBitmap.cpp |
@@ -739,11 +739,18 @@ static uint16_t pack_8888_to_4444(unsigned a, unsigned r, unsigned g, unsigned b |
return SkToU16(pixel); |
} |
-void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { |
+void SkBitmap::internalErase(const SkIRect& area, |
+ U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { |
+#ifdef SK_DEBUG |
SkDEBUGCODE(this->validate();) |
+ SkASSERT(!area.isEmpty()); |
+ { |
+ SkIRect total = { 0, 0, fWidth, fHeight }; |
+ SkASSERT(total.contains(area)); |
+ } |
+#endif |
- if (0 == fWidth || 0 == fHeight || |
- kNo_Config == fConfig || kIndex8_Config == fConfig) { |
+ if (kNo_Config == fConfig || kIndex8_Config == fConfig) { |
return; |
} |
@@ -753,8 +760,8 @@ void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { |
return; |
} |
- int height = fHeight; |
- const int width = fWidth; |
+ int height = area.height(); |
+ const int width = area.width(); |
const int rowBytes = fRowBytes; |
// make rgb premultiplied |
@@ -766,18 +773,39 @@ void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { |
switch (fConfig) { |
case kA1_Config: { |
- uint8_t* p = (uint8_t*)fPixels; |
- const int count = (width + 7) >> 3; |
+ uint8_t* p = this->getAddr1(area.fLeft, area.fTop); |
+ const int left = area.fLeft >> 3; |
+ const int right = area.fRight >> 3; |
+ |
+ int middle = right - left - 1; |
+ |
+ uint8_t leftMask = 0xFF >> (area.fLeft & 7); |
+ uint8_t rightMask = ~(0xFF >> (area.fRight & 7)); |
+ if (left == right) { |
+ leftMask &= rightMask; |
+ rightMask = 0; |
+ } |
+ |
a = (a >> 7) ? 0xFF : 0; |
- SkASSERT(count <= rowBytes); |
while (--height >= 0) { |
- memset(p, a, count); |
- p += rowBytes; |
+ uint8_t* startP = p; |
+ |
+ *p = (*p & ~leftMask) | (a & leftMask); |
+ p++; |
+ if (middle > 0) { |
+ memset(p, a, middle); |
+ p += middle; |
+ } |
+ if (rightMask) { |
+ *p = (*p & ~rightMask) | (a & rightMask); |
+ } |
+ |
+ p = startP + rowBytes; |
} |
break; |
} |
case kA8_Config: { |
- uint8_t* p = (uint8_t*)fPixels; |
+ uint8_t* p = this->getAddr8(area.fLeft, area.fTop); |
while (--height >= 0) { |
memset(p, a, width); |
p += rowBytes; |
@@ -786,7 +814,7 @@ void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { |
} |
case kARGB_4444_Config: |
case kRGB_565_Config: { |
- uint16_t* p = (uint16_t*)fPixels; |
+ uint16_t* p = this->getAddr16(area.fLeft, area.fTop);; |
uint16_t v; |
if (kARGB_4444_Config == fConfig) { |
@@ -803,7 +831,7 @@ void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { |
break; |
} |
case kARGB_8888_Config: { |
- uint32_t* p = (uint32_t*)fPixels; |
+ uint32_t* p = this->getAddr32(area.fLeft, area.fTop); |
uint32_t v = SkPackARGB32(a, r, g, b); |
while (--height >= 0) { |
@@ -817,6 +845,21 @@ void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { |
this->notifyPixelsChanged(); |
} |
+void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const { |
+ SkIRect area = { 0, 0, fWidth, fHeight }; |
+ if (!area.isEmpty()) { |
+ this->internalErase(area, a, r, g, b); |
+ } |
+} |
+ |
+void SkBitmap::eraseArea(const SkIRect& rect, SkColor c) const { |
+ SkIRect area = { 0, 0, fWidth, fHeight }; |
+ if (area.intersect(rect)) { |
+ this->internalErase(area, SkColorGetA(c), SkColorGetR(c), |
+ SkColorGetG(c), SkColorGetB(c)); |
+ } |
+} |
+ |
////////////////////////////////////////////////////////////////////////////////////// |
////////////////////////////////////////////////////////////////////////////////////// |