add canCopyTo(), to preflight if copyTo can succeed. update unittests for it



git-svn-id: http://skia.googlecode.com/svn/trunk@169 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/core/SkBitmap.h b/include/core/SkBitmap.h
index 48055d0..83baa01 100644
--- a/include/core/SkBitmap.h
+++ b/include/core/SkBitmap.h
@@ -367,12 +367,11 @@
     */
     bool extractSubset(SkBitmap* dst, const SkIRect& subset) const;
 
-    /** Tries to make a new bitmap based on the dimensions of this bitmap,
-        setting the new bitmap's config to the one specified, and then copying
-        this bitmap's pixels into the new bitmap. If the conversion is not
-        supported, or the allocator fails, then this method returns false and
-        dst is left unchanged.
-        @param dst  The bitmap to be sized and allocated
+    /** Makes a deep copy of this bitmap, respecting the requested config.
+        Returns false if either there is an error (i.e. the src does not have
+        pixels) or the request cannot be satisfied (e.g. the src has per-pixel
+        alpha, and the requested config does not support alpha).
+        @param dst The bitmap to be sized and allocated
         @param c The desired config for dst
         @param allocator Allocator used to allocate the pixelref for the dst
                          bitmap. If this is null, the standard HeapAllocator
@@ -380,6 +379,11 @@
         @return true if the copy could be made.
     */
     bool copyTo(SkBitmap* dst, Config c, Allocator* allocator = NULL) const;
+    
+    /** Returns true if this bitmap can be deep copied into the requested config
+        by calling copyTo().
+     */
+    bool canCopyTo(Config newConfig) const;
 
     bool hasMipMap() const;
     void buildMipMap(bool forceRebuild = false);
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index 2765fab..0d47508 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -682,13 +682,12 @@
 #include "SkCanvas.h"
 #include "SkPaint.h"
 
-bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
-    if (NULL == dst || this->getConfig() == kNo_Config
-            || this->width() == 0 || this->height() == 0) {
+bool SkBitmap::canCopyTo(Config dstConfig) const {
+    if (this->getConfig() == kNo_Config) {
         return false;
     }
 
-    bool sameConfigs = (dstConfig == this->config());
+    bool sameConfigs = (this->config() == dstConfig);
     switch (dstConfig) {
         case kA8_Config:
         case kARGB_4444_Config:
@@ -710,8 +709,19 @@
         return false;
     }
 
+    return true;
+}
+
+bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
+    if (!this->canCopyTo(dstConfig)) {
+        return false;
+    }
+
     // we lock this now, since we may need its colortable
     SkAutoLockPixels srclock(*this);
+    if (!this->readyToDraw()) {
+        return false;
+    }
 
     SkBitmap tmp;
     tmp.setConfig(dstConfig, this->width(), this->height());
@@ -725,16 +735,14 @@
     }
 
     SkAutoLockPixels dstlock(tmp);
-
-    if (!this->readyToDraw() || !tmp.readyToDraw()) {
+    if (!tmp.readyToDraw()) {
         // allocator/lock failed
         return false;
     }
 
-    /* do memcpy for the sameConfigs cases and
-       re-draw for the !sameConfigs cases
+    /* do memcpy for the same configs cases, else use drawing
     */
-    if (sameConfigs) {
+    if (this->config() == dstConfig) {
         if (tmp.getSize() == this->getSize()) {
             memcpy(tmp.getPixels(), this->getPixels(), this->getSize());
         } else {
diff --git a/tests/BitmapCopyTest.cpp b/tests/BitmapCopyTest.cpp
index 95b49ce..e54cde3 100644
--- a/tests/BitmapCopyTest.cpp
+++ b/tests/BitmapCopyTest.cpp
@@ -39,7 +39,8 @@
         { SkBitmap::kRGB_565_Config,    "00101110"  },
         { SkBitmap::kARGB_4444_Config,  "00101110"  },
         { SkBitmap::kARGB_8888_Config,  "00101110"  },
-        { SkBitmap::kRLE_Index8_Config, "00000000"  }
+// TODO: create valid RLE bitmap to test with
+ //       { SkBitmap::kRLE_Index8_Config, "00101111"  }
     };
 
     const int W = 20;
@@ -51,7 +52,8 @@
             SkColorTable* ct = NULL;
 
             src.setConfig(gPairs[i].fConfig, W, H);
-            if (SkBitmap::kIndex8_Config == src.config()) {
+            if (SkBitmap::kIndex8_Config == src.config() ||
+                    SkBitmap::kRLE_Index8_Config == src.config()) {
                 ct = init_ctable();
             }
             src.allocPixels(ct);
@@ -67,6 +69,15 @@
                            boolStr(success));
                 reporter->reportFailed(str);
             }
+            
+            bool canSucceed = src.canCopyTo(gPairs[j].fConfig);
+            if (success != canSucceed) {
+                SkString str;
+                str.printf("SkBitmap::copyTo from %s to %s. returned %s canCopyTo %s",
+                           gConfigName[i], gConfigName[j], boolStr(success),
+                           boolStr(canSucceed));
+                reporter->reportFailed(str);
+            }
 
             if (success) {
                 REPORTER_ASSERT(reporter, src.width() == dst.width());