add installPixels

BUG=skia:
R=halcanary@google.com

Review URL: https://codereview.chromium.org/143073008

git-svn-id: http://skia.googlecode.com/svn/trunk@13174 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index 2464d5d..9227906 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -488,13 +488,67 @@
 
 bool SkBitmap::allocPixels(Allocator* allocator, SkColorTable* ctable) {
     HeapAllocator stdalloc;
-
+    
     if (NULL == allocator) {
         allocator = &stdalloc;
     }
     return allocator->allocPixelRef(this, ctable);
 }
 
+///////////////////////////////////////////////////////////////////////////////
+
+static bool reset_return_false(SkBitmap* bm) {
+    bm->reset();
+    return false;
+}
+
+bool SkBitmap::allocPixels(const SkImageInfo& info, SkPixelRefFactory* factory,
+                           SkColorTable* ctable) {
+    if (kIndex_8_SkColorType == info.fColorType && NULL == ctable) {
+        return reset_return_false(this);
+    }
+    if (!this->setConfig(info)) {
+        return reset_return_false(this);
+    }
+
+    SkMallocPixelRef::PRFactory defaultFactory;
+    if (NULL == factory) {
+        factory = &defaultFactory;
+    }
+    
+    SkPixelRef* pr = factory->create(info, ctable);
+    if (NULL == pr) {
+        return reset_return_false(this);
+    }
+    this->setPixelRef(pr)->unref();
+
+    // TODO: lockPixels could/should return bool or void*/NULL
+    this->lockPixels();
+    if (NULL == this->getPixels()) {
+        return reset_return_false(this);
+    }
+    return true;
+}
+
+bool SkBitmap::installPixels(const SkImageInfo& info, void* pixels, size_t rb,
+                             void (*releaseProc)(void* addr, void* context),
+                             void* context) {
+    if (!this->setConfig(info)) {
+        this->reset();
+        return false;
+    }
+
+    SkPixelRef* pr = SkMallocPixelRef::NewWithProc(info, rb, NULL, pixels,
+                                                   releaseProc, context);
+    if (!pr) {
+        this->reset();
+        return false;
+    }
+
+    this->setPixelRef(pr)->unref();
+    return true;
+}
+
 void SkBitmap::freePixels() {
     // if we're gonna free the pixels, we certainly need to free the mipmap
     this->freeMipMap();
diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp
index 0570fd9..4b4f453 100644
--- a/src/core/SkBitmapDevice.cpp
+++ b/src/core/SkBitmapDevice.cpp
@@ -164,10 +164,8 @@
             drawSprite = false;
         } else {
             // we convert to a temporary bitmap and draw that as a sprite
-            dstBmp.setConfig(SkBitmap::kARGB_8888_Config,
-                             spriteRect.width(),
-                             spriteRect.height());
-            if (!dstBmp.allocPixels()) {
+            if (!dstBmp.allocPixels(SkImageInfo::MakeN32Premul(spriteRect.width(),
+                                                               spriteRect.height()))) {
                 return;
             }
             drawSprite = true;
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 0c9e9d6..c08ae26 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -92,9 +92,8 @@
     SkBitmap tmp;
     SkBitmap* bmp;
     if (bitmap->isNull()) {
-        tmp.setConfig(SkBitmap::kARGB_8888_Config, bitmap->width(),
-                                                   bitmap->height());
-        if (!tmp.allocPixels()) {
+        if (!tmp.allocPixels(SkImageInfo::MakeN32Premul(bitmap->width(),
+                                                        bitmap->height()))) {
             return false;
         }
         bmp = &tmp;
diff --git a/src/core/SkMallocPixelRef.cpp b/src/core/SkMallocPixelRef.cpp
index 50357e4..c591ffb 100644
--- a/src/core/SkMallocPixelRef.cpp
+++ b/src/core/SkMallocPixelRef.cpp
@@ -238,3 +238,11 @@
 
     this->setPreLocked(fStorage, fRB, fCTable);
 }
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkPixelRef* SkMallocPixelRef::PRFactory::create(const SkImageInfo& info,
+                                                SkColorTable* ctable) {
+    return SkMallocPixelRef::NewAllocate(info, info.minRowBytes(), ctable);
+}
+
diff --git a/src/core/SkOrderedReadBuffer.cpp b/src/core/SkOrderedReadBuffer.cpp
index 69c60cb..1ebaac4 100644
--- a/src/core/SkOrderedReadBuffer.cpp
+++ b/src/core/SkOrderedReadBuffer.cpp
@@ -252,8 +252,7 @@
         }
     }
     // Could not read the SkBitmap. Use a placeholder bitmap.
-    bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height);
-    bitmap->allocPixels();
+    bitmap->allocPixels(SkImageInfo::MakeN32Premul(width, height));
     bitmap->eraseColor(SK_ColorRED);
 }
 
diff --git a/src/effects/SkAlphaThresholdFilter.cpp b/src/effects/SkAlphaThresholdFilter.cpp
index f15a13d..4bcb320 100644
--- a/src/effects/SkAlphaThresholdFilter.cpp
+++ b/src/effects/SkAlphaThresholdFilter.cpp
@@ -323,8 +323,7 @@
     }
 
     dst->setConfig(src.config(), src.width(), src.height());
-    dst->allocPixels();
-    if (!dst->getPixels()) {
+    if (!dst->allocPixels()) {
         return false;
     }
 
diff --git a/src/effects/SkBicubicImageFilter.cpp b/src/effects/SkBicubicImageFilter.cpp
index 96d46aa..8b89a34 100644
--- a/src/effects/SkBicubicImageFilter.cpp
+++ b/src/effects/SkBicubicImageFilter.cpp
@@ -108,8 +108,7 @@
         return false;
     }
     result->setConfig(src.config(), dstIRect.width(), dstIRect.height());
-    result->allocPixels();
-    if (!result->getPixels()) {
+    if (!result->allocPixels()) {
         return false;
     }
 
diff --git a/src/effects/SkBlurImageFilter.cpp b/src/effects/SkBlurImageFilter.cpp
index 7f3f532..3e60c9b 100644
--- a/src/effects/SkBlurImageFilter.cpp
+++ b/src/effects/SkBlurImageFilter.cpp
@@ -160,8 +160,7 @@
 
     dst->setConfig(src.config(), srcBounds.width(), srcBounds.height());
     dst->getBounds(&dstBounds);
-    dst->allocPixels();
-    if (!dst->getPixels()) {
+    if (!dst->allocPixels()) {
         return false;
     }
 
diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp
index 8264ec8..6ad46ba 100644
--- a/src/effects/SkDisplacementMapEffect.cpp
+++ b/src/effects/SkDisplacementMapEffect.cpp
@@ -229,8 +229,7 @@
     }
 
     dst->setConfig(color.config(), bounds.width(), bounds.height());
-    dst->allocPixels();
-    if (!dst->getPixels()) {
+    if (!dst->allocPixels()) {
         return false;
     }
 
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index b24a91e..81c62fe 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -952,8 +952,7 @@
     }
 
     dst->setConfig(src.config(), bounds.width(), bounds.height());
-    dst->allocPixels();
-    if (!dst->getPixels()) {
+    if (!dst->allocPixels()) {
         return false;
     }
 
diff --git a/src/effects/SkPerlinNoiseShader.cpp b/src/effects/SkPerlinNoiseShader.cpp
index 77ce9cb..cdf8baf 100644
--- a/src/effects/SkPerlinNoiseShader.cpp
+++ b/src/effects/SkPerlinNoiseShader.cpp
@@ -241,8 +241,7 @@
     {
         if (!fPermutationsBitmap) {
             fPermutationsBitmap = SkNEW(SkBitmap);
-            fPermutationsBitmap->setConfig(SkBitmap::kA8_Config, kBlockSize, 1);
-            fPermutationsBitmap->allocPixels();
+            fPermutationsBitmap->allocPixels(SkImageInfo::MakeA8(kBlockSize, 1));
             uint8_t* bitmapPixels = fPermutationsBitmap->getAddr8(0, 0);
             memcpy(bitmapPixels, fLatticeSelector, sizeof(uint8_t) * kBlockSize);
         }
@@ -253,8 +252,7 @@
     {
         if (!fNoiseBitmap) {
             fNoiseBitmap = SkNEW(SkBitmap);
-            fNoiseBitmap->setConfig(SkBitmap::kARGB_8888_Config, kBlockSize, 4);
-            fNoiseBitmap->allocPixels();
+            fNoiseBitmap->allocPixels(SkImageInfo::MakeN32Premul(kBlockSize, 4));
             uint32_t* bitmapPixels = fNoiseBitmap->getAddr32(0, 0);
             memcpy(bitmapPixels, fNoise[0][0], sizeof(uint16_t) * kBlockSize * 4 * 2);
         }
diff --git a/src/effects/SkTableColorFilter.cpp b/src/effects/SkTableColorFilter.cpp
index 203f058..2872ed1 100644
--- a/src/effects/SkTableColorFilter.cpp
+++ b/src/effects/SkTableColorFilter.cpp
@@ -203,8 +203,7 @@
     if (table) {
         if (NULL == fBitmap) {
             SkBitmap* bmp = SkNEW(SkBitmap);
-            bmp->setConfig(SkBitmap::kA8_Config, 256, 4, 256);
-            bmp->allocPixels();
+            bmp->allocPixels(SkImageInfo::MakeA8(256, 4));
             uint8_t* bitmapPixels = bmp->getAddr8(0, 0);
             int offset = 0;
             static const unsigned kFlags[] = { kA_Flag, kR_Flag, kG_Flag, kB_Flag };
diff --git a/src/gpu/GrSWMaskHelper.cpp b/src/gpu/GrSWMaskHelper.cpp
index eefc951..504f5a0 100644
--- a/src/gpu/GrSWMaskHelper.cpp
+++ b/src/gpu/GrSWMaskHelper.cpp
@@ -99,8 +99,7 @@
     SkIRect bounds = SkIRect::MakeWH(resultBounds.width(),
                                      resultBounds.height());
 
-    fBM.setConfig(SkBitmap::kA8_Config, bounds.fRight, bounds.fBottom);
-    if (!fBM.allocPixels()) {
+    if (!fBM.allocPixels(SkImageInfo::MakeA8(bounds.fRight, bounds.fBottom))) {
         return false;
     }
     sk_bzero(fBM.getPixels(), fBM.getSafeSize());
diff --git a/src/gpu/GrSurface.cpp b/src/gpu/GrSurface.cpp
index 1fcc4ff..66ebe3b 100644
--- a/src/gpu/GrSurface.cpp
+++ b/src/gpu/GrSurface.cpp
@@ -23,8 +23,10 @@
 
 bool GrSurface::savePixels(const char* filename) {
     SkBitmap bm;
-    bm.setConfig(SkBitmap::kARGB_8888_Config, this->width(), this->height());
-    bm.allocPixels();
+    if (!bm.allocPixels(SkImageInfo::MakeN32Premul(this->width(),
+                                                   this->height()))) {
+        return false;
+    }
 
     bool result = readPixels(0, 0, this->width(), this->height(), kSkia8888_GrPixelConfig,
                              bm.getPixels());
diff --git a/src/gpu/SkGrPixelRef.cpp b/src/gpu/SkGrPixelRef.cpp
index 8a16437..fdf9487 100644
--- a/src/gpu/SkGrPixelRef.cpp
+++ b/src/gpu/SkGrPixelRef.cpp
@@ -178,8 +178,7 @@
         top = 0;
         height = fSurface->height();
     }
-    dst->setConfig(SkBitmap::kARGB_8888_Config, width, height);
-    if (!dst->allocPixels()) {
+    if (!dst->allocPixels(SkImageInfo::MakeN32Premul(width, height))) {
         SkDebugf("SkGrPixelRef::onReadPixels failed to alloc bitmap for result!\n");
         return false;
     }
diff --git a/src/images/SkMovie_gif.cpp b/src/images/SkMovie_gif.cpp
index b6d068a..decefd5 100644
--- a/src/images/SkMovie_gif.cpp
+++ b/src/images/SkMovie_gif.cpp
@@ -364,13 +364,11 @@
         startIndex = 0;
 
         // create bitmap
-        bm->setConfig(SkBitmap::kARGB_8888_Config, width, height, 0);
-        if (!bm->allocPixels(NULL)) {
+        if (!bm->allocPixels(SkImageInfo::MakeN32Premul(width, height))) {
             return false;
         }
         // create bitmap for backup
-        fBackup.setConfig(SkBitmap::kARGB_8888_Config, width, height, 0);
-        if (!fBackup.allocPixels(NULL)) {
+        if (!fBackup.allocPixels(SkImageInfo::MakeN32Premul(width, height))) {
             return false;
         }
     } else if (startIndex > fCurrIndex) {
diff --git a/src/lazy/SkDiscardablePixelRef.cpp b/src/lazy/SkDiscardablePixelRef.cpp
index abd80f2..0878d00 100644
--- a/src/lazy/SkDiscardablePixelRef.cpp
+++ b/src/lazy/SkDiscardablePixelRef.cpp
@@ -89,7 +89,7 @@
     }
     SkASSERT(dst->config() != SkBitmap::kNo_Config);
     if (dst->empty()) {  // Use a normal pixelref.
-        return dst->allocPixels(NULL, NULL);
+        return dst->allocPixels();
     }
     SkAutoTUnref<SkDiscardablePixelRef> ref(
         SkNEW_ARGS(SkDiscardablePixelRef,
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index a9ad49e..ff83aad 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -2250,13 +2250,11 @@
         // the image.  Avoiding alpha will reduce the pdf size and generation
         // CPU time some.
 
-        perspectiveBitmap.setConfig(
-                SkBitmap::kARGB_8888_Config,
-                SkScalarCeilToInt(
-                        physicalPerspectiveOutline.getBounds().width()),
-                SkScalarCeilToInt(
-                        physicalPerspectiveOutline.getBounds().height()));
-        perspectiveBitmap.allocPixels();
+        const int w = SkScalarCeilToInt(physicalPerspectiveOutline.getBounds().width());
+        const int h = SkScalarCeilToInt(physicalPerspectiveOutline.getBounds().height());
+        if (!perspectiveBitmap.allocPixels(SkImageInfo::MakeN32Premul(w, h))) {
+            return;
+        }
         perspectiveBitmap.eraseColor(SK_ColorTRANSPARENT);
 
         SkBitmapDevice device(perspectiveBitmap);
diff --git a/src/utils/SkPDFRasterizer.cpp b/src/utils/SkPDFRasterizer.cpp
index 68a3119..6663480 100644
--- a/src/utils/SkPDFRasterizer.cpp
+++ b/src/utils/SkPDFRasterizer.cpp
@@ -50,8 +50,7 @@
   char *imgData = image.data();
 
   SkBitmap bitmap;
-  bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
-  if (!bitmap.allocPixels()) {
+  if (!bitmap.allocPixels(SkImageInfo::MakeN32Premul(width, height))) {
     return false;
   }
   bitmap.eraseColor(SK_ColorWHITE);
diff --git a/src/utils/debugger/SkDebugCanvas.cpp b/src/utils/debugger/SkDebugCanvas.cpp
index e491f3b..1c3e26e 100644
--- a/src/utils/debugger/SkDebugCanvas.cpp
+++ b/src/utils/debugger/SkDebugCanvas.cpp
@@ -74,8 +74,7 @@
 
 int SkDebugCanvas::getCommandAtPoint(int x, int y, int index) {
     SkBitmap bitmap;
-    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
-    bitmap.allocPixels();
+    bitmap.allocPixels(SkImageInfo::MakeN32Premul(1, 1));
 
     SkCanvas canvas(bitmap);
     canvas.translate(SkIntToScalar(-x), SkIntToScalar(-y));
diff --git a/src/utils/mac/SkCreateCGImageRef.cpp b/src/utils/mac/SkCreateCGImageRef.cpp
index 0677b7b..1b52ba3 100644
--- a/src/utils/mac/SkCreateCGImageRef.cpp
+++ b/src/utils/mac/SkCreateCGImageRef.cpp
@@ -209,8 +209,9 @@
     int h = (int)CGRectGetHeight(bounds);
 
     SkBitmap bitmap;
-    bitmap.setConfig(SkBitmap::kARGB_8888_Config, w, h);
-    bitmap.allocPixels();
+    if (!bitmap.allocPixels(SkImageInfo::MakeN32Premul(w, h))) {
+        return false;
+    }
     bitmap.eraseColor(SK_ColorWHITE);
 
     size_t bitsPerComponent;