Revert "Revert of move erase into SkPixmap (patchset #1 id:1 of https://codereview.chromium.org/1161033005/)"

This reverts commit cca9b3ac908cf3e9a0c5774a5ffd118d8429e08a.

BUG=skia:
TBR=

Review URL: https://codereview.chromium.org/1153473012
diff --git a/include/core/SkBitmap.h b/include/core/SkBitmap.h
index c070203..b13b6f7 100644
--- a/include/core/SkBitmap.h
+++ b/include/core/SkBitmap.h
@@ -473,10 +473,7 @@
      *  of the color is ignored (treated as opaque). If the colortype only supports
      *  alpha (e.g. A1 or A8) then the color's r,g,b components are ignored.
      */
-    void eraseColor(SkColor c) const {
-        this->eraseARGB(SkColorGetA(c), SkColorGetR(c), SkColorGetG(c),
-                        SkColorGetB(c));
-    }
+    void eraseColor(SkColor c) const;
 
     /**
      *  Fill the entire bitmap with the specified color.
@@ -484,7 +481,9 @@
      *  of the color is ignored (treated as opaque). If the colortype only supports
      *  alpha (e.g. A1 or A8) then the color's r,g,b components are ignored.
      */
-    void eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const;
+    void eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
+        this->eraseColor(SkColorSetARGB(a, r, g, b));
+    }
 
     SK_ATTR_DEPRECATED("use eraseARGB or eraseColor")
     void eraseRGB(U8CPU r, U8CPU g, U8CPU b) const {
@@ -497,7 +496,12 @@
      *  of the color is ignored (treated as opaque). If the colortype only supports
      *  alpha (e.g. A1 or A8) then the color's r,g,b components are ignored.
      */
-    void eraseArea(const SkIRect& area, SkColor c) const;
+    void erase(SkColor c, const SkIRect& area) const;
+
+    // DEPRECATED
+    void eraseArea(const SkIRect& area, SkColor c) const {
+        this->erase(c, area);
+    }
 
     /**
      *  Return the SkColor of the specified pixel.  In most cases this will
@@ -736,13 +740,9 @@
     };
 
     SkImageInfo fInfo;
-
     uint32_t    fRowBytes;
-
     uint8_t     fFlags;
 
-    void internalErase(const SkIRect&, U8CPU a, U8CPU r, U8CPU g, U8CPU b)const;
-
     /*  Unreference any pixelrefs or colortables
     */
     void freePixels();
diff --git a/include/core/SkPixmap.h b/include/core/SkPixmap.h
index 913d007..05c7101 100644
--- a/include/core/SkPixmap.h
+++ b/include/core/SkPixmap.h
@@ -8,6 +8,7 @@
 #ifndef SkPixmap_DEFINED
 #define SkPixmap_DEFINED
 
+#include "SkColor.h"
 #include "SkImageInfo.h"
 
 class SkColorTable;
@@ -133,6 +134,14 @@
         return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), 0, 0);
     }
 
+    /**
+     *  Returns true if pixels were written to (e.g. if colorType is kUnknown_SkColorType, this
+     *  will return false). If subset does not intersect the bounds of this pixmap, returns false.
+     */
+    bool erase(SkColor, const SkIRect& subset) const;
+
+    bool erase(SkColor color) const { return this->erase(color, this->bounds()); }
+
 private:
     const void*     fPixels;
     SkColorTable*   fCTable;
@@ -165,8 +174,34 @@
      */
     void alloc(const SkImageInfo&);
 
+    // We wrap these so we can clear our internal storage
+
+    void reset() {
+        this->freeStorage();
+        this->INHERITED::reset();
+    }
+    void reset(const SkImageInfo& info, const void* addr, size_t rb, SkColorTable* ctable = NULL) {
+        this->freeStorage();
+        this->INHERITED::reset(info, addr, rb, ctable);
+    }
+    void reset(const SkImageInfo& info) {
+        this->freeStorage();
+        this->INHERITED::reset(info);
+    }
+    bool SK_WARN_UNUSED_RESULT reset(const SkMask& mask) {
+        this->freeStorage();
+        return this->INHERITED::reset(mask);
+    }
+
 private:
     void*   fStorage;
+
+    void freeStorage() {
+        sk_free(fStorage);
+        fStorage = NULL;
+    }
+
+    typedef SkPixmap INHERITED;
 };
 
 /////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index f2668f0..49e2c04 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -666,101 +666,8 @@
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
-static uint16_t pack_8888_to_4444(unsigned a, unsigned r, unsigned g, unsigned b) {
-    unsigned pixel = (SkA32To4444(a) << SK_A4444_SHIFT) |
-                     (SkR32To4444(r) << SK_R4444_SHIFT) |
-                     (SkG32To4444(g) << SK_G4444_SHIFT) |
-                     (SkB32To4444(b) << SK_B4444_SHIFT);
-    return SkToU16(pixel);
-}
-
-static bool internal_erase(const SkPixmap& pmap, const SkIRect& area,
-                           U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
-    int height = area.height();
-    const int width = area.width();
-    const int rowBytes = pmap.rowBytes();
-
-    switch (pmap.colorType()) {
-        case kGray_8_SkColorType: {
-            if (255 != a) {
-                r = SkMulDiv255Round(r, a);
-                g = SkMulDiv255Round(g, a);
-                b = SkMulDiv255Round(b, a);
-            }
-            int gray = SkComputeLuminance(r, g, b);
-            uint8_t* p = pmap.writable_addr8(area.fLeft, area.fTop);
-            while (--height >= 0) {
-                memset(p, gray, width);
-                p += rowBytes;
-            }
-            break;
-        }
-        case kAlpha_8_SkColorType: {
-            uint8_t* p = pmap.writable_addr8(area.fLeft, area.fTop);
-            while (--height >= 0) {
-                memset(p, a, width);
-                p += rowBytes;
-            }
-            break;
-        }
-        case kARGB_4444_SkColorType:
-        case kRGB_565_SkColorType: {
-            uint16_t* p = pmap.writable_addr16(area.fLeft, area.fTop);
-            uint16_t v;
-
-            // make rgb premultiplied
-            if (255 != a) {
-                r = SkAlphaMul(r, a);
-                g = SkAlphaMul(g, a);
-                b = SkAlphaMul(b, a);
-            }
-
-            if (kARGB_4444_SkColorType == pmap.colorType()) {
-                v = pack_8888_to_4444(a, r, g, b);
-            } else {
-                v = SkPackRGB16(r >> (8 - SK_R16_BITS),
-                                g >> (8 - SK_G16_BITS),
-                                b >> (8 - SK_B16_BITS));
-            }
-            while (--height >= 0) {
-                sk_memset16(p, v, width);
-                p = (uint16_t*)((char*)p + rowBytes);
-            }
-            break;
-        }
-        case kBGRA_8888_SkColorType:
-        case kRGBA_8888_SkColorType: {
-            uint32_t* p = pmap.writable_addr32(area.fLeft, area.fTop);
-
-            if (255 != a && kPremul_SkAlphaType == pmap.alphaType()) {
-                r = SkAlphaMul(r, a);
-                g = SkAlphaMul(g, a);
-                b = SkAlphaMul(b, a);
-            }
-            uint32_t v = kRGBA_8888_SkColorType == pmap.colorType() ?
-            SkPackARGB_as_RGBA(a, r, g, b) : SkPackARGB_as_BGRA(a, r, g, b);
-
-            while (--height >= 0) {
-                sk_memset32(p, v, width);
-                p = (uint32_t*)((char*)p + rowBytes);
-            }
-            break;
-        }
-        default:
-            return false; // no change, so don't call notifyPixelsChanged()
-    }
-    return true;
-}
-
-void SkBitmap::internalErase(const SkIRect& area, U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
-#ifdef SK_DEBUG
+void SkBitmap::erase(SkColor c, const SkIRect& area) const {
     SkDEBUGCODE(this->validate();)
-    SkASSERT(!area.isEmpty());
-    {
-        SkIRect total = { 0, 0, this->width(), this->height() };
-        SkASSERT(total.contains(area));
-    }
-#endif
 
     switch (fInfo.colorType()) {
         case kUnknown_SkColorType:
@@ -776,24 +683,13 @@
         return;
     }
 
-    if (internal_erase(result.pixmap(), area, a, r, g, b)) {
+    if (result.pixmap().erase(c, area)) {
         this->notifyPixelsChanged();
     }
 }
 
-void SkBitmap::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
-    SkIRect area = { 0, 0, this->width(), this->height() };
-    if (!area.isEmpty()) {
-        this->internalErase(area, a, r, g, b);
-    }
-}
-
-void SkBitmap::eraseArea(const SkIRect& rect, SkColor c) const {
-    SkIRect area = { 0, 0, this->width(), this->height() };
-    if (area.intersect(rect)) {
-        this->internalErase(area, SkColorGetA(c), SkColorGetR(c),
-                            SkColorGetG(c), SkColorGetB(c));
-    }
+void SkBitmap::eraseColor(SkColor c) const {
+    this->erase(c, SkIRect::MakeWH(this->width(), this->height()));
 }
 
 //////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/SkPixmap.cpp b/src/core/SkPixmap.cpp
index 9b7f993..339dea0 100644
--- a/src/core/SkPixmap.cpp
+++ b/src/core/SkPixmap.cpp
@@ -5,9 +5,11 @@
  * found in the LICENSE file.
  */
 
+#include "SkColorPriv.h"
 #include "SkConfig8888.h"
 #include "SkMask.h"
 #include "SkPixmap.h"
+#include "SkUtils.h"
 
 void SkAutoPixmapUnlock::reset(const SkPixmap& pm, void (*unlock)(void*), void* ctx) {
     SkASSERT(pm.addr() != NULL);
@@ -105,30 +107,126 @@
                                    srcInfo, srcPixels, this->rowBytes(), this->ctable());
 }
 
+static uint16_t pack_8888_to_4444(unsigned a, unsigned r, unsigned g, unsigned b) {
+    unsigned pixel = (SkA32To4444(a) << SK_A4444_SHIFT) |
+    (SkR32To4444(r) << SK_R4444_SHIFT) |
+    (SkG32To4444(g) << SK_G4444_SHIFT) |
+    (SkB32To4444(b) << SK_B4444_SHIFT);
+    return SkToU16(pixel);
+}
+
+bool SkPixmap::erase(SkColor color, const SkIRect& inArea) const {
+    if (NULL == fPixels) {
+        return false;
+    }
+    SkIRect area;
+    if (!area.intersect(this->bounds(), inArea)) {
+        return false;
+    }
+
+    U8CPU a = SkColorGetA(color);
+    U8CPU r = SkColorGetR(color);
+    U8CPU g = SkColorGetG(color);
+    U8CPU b = SkColorGetB(color);
+
+    int height = area.height();
+    const int width = area.width();
+    const int rowBytes = this->rowBytes();
+    
+    switch (this->colorType()) {
+        case kGray_8_SkColorType: {
+            if (255 != a) {
+                r = SkMulDiv255Round(r, a);
+                g = SkMulDiv255Round(g, a);
+                b = SkMulDiv255Round(b, a);
+            }
+            int gray = SkComputeLuminance(r, g, b);
+            uint8_t* p = this->writable_addr8(area.fLeft, area.fTop);
+            while (--height >= 0) {
+                memset(p, gray, width);
+                p += rowBytes;
+            }
+            break;
+        }
+        case kAlpha_8_SkColorType: {
+            uint8_t* p = this->writable_addr8(area.fLeft, area.fTop);
+            while (--height >= 0) {
+                memset(p, a, width);
+                p += rowBytes;
+            }
+            break;
+        }
+        case kARGB_4444_SkColorType:
+        case kRGB_565_SkColorType: {
+            uint16_t* p = this->writable_addr16(area.fLeft, area.fTop);
+            uint16_t v;
+            
+            // make rgb premultiplied
+            if (255 != a) {
+                r = SkAlphaMul(r, a);
+                g = SkAlphaMul(g, a);
+                b = SkAlphaMul(b, a);
+            }
+            
+            if (kARGB_4444_SkColorType == this->colorType()) {
+                v = pack_8888_to_4444(a, r, g, b);
+            } else {
+                v = SkPackRGB16(r >> (8 - SK_R16_BITS),
+                                g >> (8 - SK_G16_BITS),
+                                b >> (8 - SK_B16_BITS));
+            }
+            while (--height >= 0) {
+                sk_memset16(p, v, width);
+                p = (uint16_t*)((char*)p + rowBytes);
+            }
+            break;
+        }
+        case kBGRA_8888_SkColorType:
+        case kRGBA_8888_SkColorType: {
+            uint32_t* p = this->writable_addr32(area.fLeft, area.fTop);
+            
+            if (255 != a && kPremul_SkAlphaType == this->alphaType()) {
+                r = SkAlphaMul(r, a);
+                g = SkAlphaMul(g, a);
+                b = SkAlphaMul(b, a);
+            }
+            uint32_t v = kRGBA_8888_SkColorType == this->colorType() ?
+            SkPackARGB_as_RGBA(a, r, g, b) : SkPackARGB_as_BGRA(a, r, g, b);
+            
+            while (--height >= 0) {
+                sk_memset32(p, v, width);
+                p = (uint32_t*)((char*)p + rowBytes);
+            }
+            break;
+        }
+        default:
+            return false; // no change, so don't call notifyPixelsChanged()
+    }
+    return true;
+}
+
 //////////////////////////////////////////////////////////////////////////////////////////////////
 
 SkAutoPixmapStorage::SkAutoPixmapStorage() : fStorage(NULL) {}
 
 SkAutoPixmapStorage::~SkAutoPixmapStorage() {
-    sk_free(fStorage);
+    this->freeStorage();
 }
 
 bool SkAutoPixmapStorage::tryAlloc(const SkImageInfo& info) {
-    if (fStorage) {
-        sk_free(fStorage);
-        fStorage = NULL;
-    }
+    this->freeStorage();
     
     size_t rb = info.minRowBytes();
     size_t size = info.getSafeSize(rb);
     if (0 == size) {
         return false;
     }
-    fStorage = sk_malloc_flags(size, 0);
-    if (NULL == fStorage) {
+    void* pixels = sk_malloc_flags(size, 0);
+    if (NULL == pixels) {
         return false;
     }
-    this->reset(info, fStorage, rb);
+    this->reset(info, pixels, rb);
+    fStorage = pixels;
     return true;
 }