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());