add new copyTo version to SkBitmap, which takes SkColorType
BUG=skia:
R=scroggo@google.com, halcanary@google.com, bsalomon@google.com
Author: reed@google.com
Review URL: https://codereview.chromium.org/171723007
git-svn-id: http://skia.googlecode.com/svn/trunk@13553 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index 520ccd3..32cb7b2 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -982,32 +982,43 @@
#include "SkCanvas.h"
#include "SkPaint.h"
-bool SkBitmap::canCopyTo(Config dstConfig) const {
- if (this->config() == kNo_Config) {
+#ifdef SK_SUPPORT_LEGACY_COPYTO_CONFIG
+bool SkBitmap::copyTo(SkBitmap* dst, Config c, Allocator* allocator) const {
+ return this->copyTo(dst, SkBitmapConfigToSkColorType(c), allocator);
+}
+
+bool SkBitmap::canCopyTo(Config newConfig) const {
+ return this->canCopyTo(SkBitmapConfigToSkColorType(c));
+}
+#endif
+
+bool SkBitmap::canCopyTo(SkColorType dstColorType) const {
+ if (this->colorType() == kUnknown_SkColorType) {
return false;
}
- bool sameConfigs = (this->config() == dstConfig);
- switch (dstConfig) {
- case kA8_Config:
- case kRGB_565_Config:
- case kARGB_8888_Config:
+ bool sameConfigs = (this->colorType() == dstColorType);
+ switch (dstColorType) {
+ case kAlpha_8_SkColorType:
+ case kRGB_565_SkColorType:
+ case kPMColor_SkColorType:
break;
- case kIndex8_Config:
+ case kIndex_8_SkColorType:
if (!sameConfigs) {
return false;
}
break;
- case kARGB_4444_Config:
- return sameConfigs || kARGB_8888_Config == this->config();
+ case kARGB_4444_SkColorType:
+ return sameConfigs || kPMColor_SkColorType == this->colorType();
default:
return false;
}
return true;
}
-bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
- if (!this->canCopyTo(dstConfig)) {
+bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType,
+ Allocator* alloc) const {
+ if (!this->canCopyTo(dstColorType)) {
return false;
}
@@ -1024,7 +1035,7 @@
SkASSERT(tmpSrc.height() == this->height());
// did we get lucky and we can just return tmpSrc?
- if (tmpSrc.config() == dstConfig && NULL == alloc) {
+ if (tmpSrc.colorType() == dstColorType && NULL == alloc) {
dst->swap(tmpSrc);
// If the result is an exact copy, clone the gen ID.
if (dst->pixelRef() && dst->pixelRef()->info() == fPixelRef->info()) {
@@ -1047,14 +1058,20 @@
// The only way to be readyToDraw is if fPixelRef is non NULL.
SkASSERT(fPixelRef != NULL);
+ SkImageInfo dstInfo = src->info();
+ dstInfo.fColorType = dstColorType;
+
SkBitmap tmpDst;
- tmpDst.setConfig(dstConfig, src->width(), src->height(), 0,
- src->alphaType());
+ if (!tmpDst.setConfig(dstInfo)) {
+ return false;
+ }
// allocate colortable if srcConfig == kIndex8_Config
- SkColorTable* ctable = (dstConfig == kIndex8_Config) ?
- new SkColorTable(*src->getColorTable()) : NULL;
- SkAutoUnref au(ctable);
+ SkAutoTUnref<SkColorTable> ctable;
+ if (dstColorType == kIndex_8_SkColorType) {
+ // TODO: can we just ref() the src colortable? Is it reentrant-safe?
+ ctable.reset(SkNEW_ARGS(SkColorTable, (*src->getColorTable())));
+ }
if (!tmpDst.allocPixels(alloc, ctable)) {
return false;
}
@@ -1070,7 +1087,7 @@
/* do memcpy for the same configs cases, else use drawing
*/
- if (src->config() == dstConfig) {
+ if (src->colorType() == dstColorType) {
if (tmpDst.getSize() == src->getSize()) {
memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize());
SkPixelRef* pixelRef = tmpDst.pixelRef();
@@ -1102,8 +1119,8 @@
dstP += tmpDst.rowBytes();
}
}
- } else if (SkBitmap::kARGB_4444_Config == dstConfig
- && SkBitmap::kARGB_8888_Config == src->config()) {
+ } else if (kARGB_4444_SkColorType == dstColorType
+ && kPMColor_SkColorType == src->colorType()) {
SkASSERT(src->height() == tmpDst.height());
SkASSERT(src->width() == tmpDst.width());
for (int y = 0; y < src->height(); ++y) {
@@ -1134,7 +1151,7 @@
bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const {
const SkColorType dstCT = SkBitmapConfigToColorType(dstConfig);
- if (!this->canCopyTo(dstConfig)) {
+ if (!this->canCopyTo(dstCT)) {
return false;
}
@@ -1169,7 +1186,7 @@
if (this->getTexture()) {
return false;
} else {
- return this->copyTo(dst, dstConfig, NULL);
+ return this->copyTo(dst, dstCT, NULL);
}
}
diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp
index 07ae3df..7ed8058 100644
--- a/src/core/SkBitmapDevice.cpp
+++ b/src/core/SkBitmapDevice.cpp
@@ -189,9 +189,9 @@
if (!src.extractSubset(&subset, srcRect)) {
return false;
}
- if (SkBitmap::kARGB_8888_Config != subset.config()) {
+ if (kPMColor_SkColorType != subset.colorType()) {
// It'd be preferable to do this directly to bitmap.
- subset.copyTo(&subset, SkBitmap::kARGB_8888_Config);
+ subset.copyTo(&subset, kPMColor_SkColorType);
}
SkAutoLockPixels alp(bitmap);
uint32_t* bmpPixels = reinterpret_cast<uint32_t*>(bitmap.getPixels());
diff --git a/src/effects/SkBlurImageFilter.cpp b/src/effects/SkBlurImageFilter.cpp
index f946f87..4d23658 100644
--- a/src/effects/SkBlurImageFilter.cpp
+++ b/src/effects/SkBlurImageFilter.cpp
@@ -178,7 +178,7 @@
}
if (kernelSizeX == 0 && kernelSizeY == 0) {
- src.copyTo(dst, dst->config());
+ src.copyTo(dst, dst->colorType());
offset->fX = srcBounds.fLeft;
offset->fY = srcBounds.fTop;
return true;
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index c053e8b..94e4c8c 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -155,7 +155,7 @@
return result;
}
} else {
- origBitmap.copyTo(&tmpBitmap, SkBitmap::kARGB_8888_Config);
+ origBitmap.copyTo(&tmpBitmap, kPMColor_SkColorType);
// now bitmap points to our temp, which has been promoted to 32bits
bitmap = &tmpBitmap;
desc.fConfig = SkBitmapConfig2GrPixelConfig(bitmap->config());
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index 0d8ddaa..475f50e 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -59,7 +59,7 @@
}
bool SkImage_Gpu::getROPixels(SkBitmap* dst) const {
- return fBitmap.copyTo(dst, SkBitmap::kARGB_8888_Config);
+ return fBitmap.copyTo(dst, kPMColor_SkColorType);
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/src/image/SkImage_Raster.cpp b/src/image/SkImage_Raster.cpp
index 504943e..abf6dc8 100644
--- a/src/image/SkImage_Raster.cpp
+++ b/src/image/SkImage_Raster.cpp
@@ -127,7 +127,7 @@
if (!fBitmap.extractSubset(&src, subset)) {
return false;
}
- return src.copyTo(dst, src.config());
+ return src.copyTo(dst, src.colorType());
}
}
diff --git a/src/images/SkDecodingImageGenerator.cpp b/src/images/SkDecodingImageGenerator.cpp
index 1e28136..7e3bb9b 100644
--- a/src/images/SkDecodingImageGenerator.cpp
+++ b/src/images/SkDecodingImageGenerator.cpp
@@ -14,60 +14,50 @@
#include "SkStream.h"
#include "SkUtils.h"
+static bool equal_modulo_alpha(const SkImageInfo& a, const SkImageInfo& b) {
+ return a.width() == b.width() && a.height() == b.height() &&
+ a.colorType() == b.colorType();
+}
+
namespace {
/**
* Special allocator used by getPixels(). Uses preallocated memory
- * provided.
+ * provided if possible, else fall-back on the default allocator
*/
class TargetAllocator : public SkBitmap::Allocator {
public:
- TargetAllocator(void* target,
- size_t rowBytes,
- int width,
- int height,
- SkBitmap::Config config)
- : fTarget(target)
+ TargetAllocator(const SkImageInfo& info,
+ void* target,
+ size_t rowBytes)
+ : fInfo(info)
+ , fTarget(target)
, fRowBytes(rowBytes)
- , fWidth(width)
- , fHeight(height)
- , fConfig(config) { }
+ {}
bool isReady() { return (fTarget != NULL); }
virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) {
- if ((NULL == fTarget)
- || (fConfig != bm->config())
- || (fWidth != bm->width())
- || (fHeight != bm->height())
- || (ct != NULL)) {
+ if (NULL == fTarget || !equal_modulo_alpha(fInfo, bm->info())) {
// Call default allocator.
return bm->allocPixels(NULL, ct);
}
- // make sure fRowBytes is correct.
- bm->setConfig(fConfig, fWidth, fHeight, fRowBytes, bm->alphaType());
+
// TODO(halcanary): verify that all callers of this function
// will respect new RowBytes. Will be moot once rowbytes belongs
// to PixelRef.
- bm->setPixels(fTarget, NULL);
+ bm->installPixels(fInfo, fTarget, fRowBytes, NULL, NULL);
+
fTarget = NULL; // never alloc same pixels twice!
return true;
}
private:
+ const SkImageInfo fInfo;
void* fTarget; // Block of memory to be supplied as pixel memory
// in allocPixelRef. Must be large enough to hold
- // a bitmap described by fWidth, fHeight, and
- // fRowBytes.
- size_t fRowBytes; // rowbytes for the destination bitmap
- int fWidth; // Along with fHeight and fConfig, the information
- int fHeight; // about the bitmap whose pixels this allocator is
- // expected to allocate. If they do not match the
- // bitmap passed to allocPixelRef, it is assumed
- // that the bitmap will be copied to a bitmap with
- // the correct info using this allocator, so the
- // default allocator will be used instead of
- // fTarget.
- SkBitmap::Config fConfig;
+ // a bitmap described by fInfo and fRowBytes
+ const size_t fRowBytes; // rowbytes for the destination bitmap
+
typedef SkBitmap::Allocator INHERITED;
};
@@ -94,14 +84,13 @@
SkStreamRewindable* stream,
const SkImageInfo& info,
int sampleSize,
- bool ditherImage,
- SkBitmap::Config requestedConfig)
+ bool ditherImage)
: fData(data)
, fStream(stream)
, fInfo(info)
, fSampleSize(sampleSize)
, fDitherImage(ditherImage)
- , fRequestedConfig(requestedConfig) {
+{
SkASSERT(stream != NULL);
SkSafeRef(fData); // may be NULL.
}
@@ -151,8 +140,7 @@
// to change the settings.
return false;
}
- int bpp = SkBitmap::ComputeBytesPerPixel(fRequestedConfig);
- if (static_cast<size_t>(bpp * info.fWidth) > rowBytes) {
+ if (info.minRowBytes() > rowBytes) {
// The caller has specified a bad rowBytes.
return false;
}
@@ -166,10 +154,11 @@
decoder->setSampleSize(fSampleSize);
SkBitmap bitmap;
- TargetAllocator allocator(pixels, rowBytes, info.fWidth,
- info.fHeight, fRequestedConfig);
+ TargetAllocator allocator(fInfo, pixels, rowBytes);
decoder->setAllocator(&allocator);
- bool success = decoder->decode(fStream, &bitmap, fRequestedConfig,
+ // TODO: need to be able to pass colortype directly to decoder
+ SkBitmap::Config legacyConfig = SkColorTypeToBitmapConfig(info.colorType());
+ bool success = decoder->decode(fStream, &bitmap, legacyConfig,
SkImageDecoder::kDecodePixels_Mode);
decoder->setAllocator(NULL);
if (!success) {
@@ -177,16 +166,16 @@
}
if (allocator.isReady()) { // Did not use pixels!
SkBitmap bm;
- SkASSERT(bitmap.canCopyTo(fRequestedConfig));
- if (!bitmap.copyTo(&bm, fRequestedConfig, &allocator)
- || allocator.isReady()) {
+ SkASSERT(bitmap.canCopyTo(info.colorType()));
+ bool copySuccess = bitmap.copyTo(&bm, info.colorType(), &allocator);
+ if (!copySuccess || allocator.isReady()) {
SkDEBUGFAIL("bitmap.copyTo(requestedConfig) failed.");
// Earlier we checked canCopyto(); we expect consistency.
return false;
}
- SkASSERT(check_alpha(fInfo.fAlphaType, bm.alphaType()));
+ SkASSERT(check_alpha(info.alphaType(), bm.alphaType()));
} else {
- SkASSERT(check_alpha(fInfo.fAlphaType, bitmap.alphaType()));
+ SkASSERT(check_alpha(info.alphaType(), bitmap.alphaType()));
}
return true;
}
@@ -245,38 +234,23 @@
return NULL;
}
- SkImageInfo info;
- SkBitmap::Config config;
+ SkImageInfo info = bitmap.info();
if (!opts.fUseRequestedColorType) {
- // Use default config.
- if (SkBitmap::kIndex8_Config == bitmap.config()) {
+ // Use default
+ if (kIndex_8_SkColorType == bitmap.colorType()) {
// We don't support kIndex8 because we don't support
// colortables in this workflow.
- config = SkBitmap::kARGB_8888_Config;
- info.fWidth = bitmap.width();
- info.fHeight = bitmap.height();
info.fColorType = kPMColor_SkColorType;
- info.fAlphaType = bitmap.alphaType();
- } else {
- config = bitmap.config(); // Save for later!
- if (!bitmap.asImageInfo(&info)) {
- SkDEBUGFAIL("Getting SkImageInfo from bitmap failed.");
- return NULL;
- }
}
} else {
- config = SkColorTypeToBitmapConfig(opts.fRequestedColorType);
- if (!bitmap.canCopyTo(config)) {
- SkASSERT(bitmap.config() != config);
+ if (!bitmap.canCopyTo(opts.fRequestedColorType)) {
+ SkASSERT(bitmap.colorType() != opts.fRequestedColorType);
return NULL; // Can not translate to needed config.
}
- info.fWidth = bitmap.width();
- info.fHeight = bitmap.height();
info.fColorType = opts.fRequestedColorType;
- info.fAlphaType = bitmap.alphaType();
}
return SkNEW_ARGS(SkDecodingImageGenerator,
(data, autoStream.detach(), info,
- opts.fSampleSize, opts.fDitherImage, config));
+ opts.fSampleSize, opts.fDitherImage));
}
diff --git a/src/images/SkDecodingImageGenerator.h b/src/images/SkDecodingImageGenerator.h
index 12a49d5..fef7c6c 100644
--- a/src/images/SkDecodingImageGenerator.h
+++ b/src/images/SkDecodingImageGenerator.h
@@ -113,13 +113,12 @@
const SkImageInfo fInfo;
const int fSampleSize;
const bool fDitherImage;
- const SkBitmap::Config fRequestedConfig;
+
SkDecodingImageGenerator(SkData* data,
SkStreamRewindable* stream,
const SkImageInfo& info,
int sampleSize,
- bool ditherImage,
- SkBitmap::Config requestedConfig);
+ bool ditherImage);
static SkImageGenerator* Create(SkData*, SkStreamRewindable*,
const Options&);
typedef SkImageGenerator INHERITED;
diff --git a/src/ports/SkImageDecoder_CG.cpp b/src/ports/SkImageDecoder_CG.cpp
index 90c282d..c61ce98 100644
--- a/src/ports/SkImageDecoder_CG.cpp
+++ b/src/ports/SkImageDecoder_CG.cpp
@@ -208,8 +208,8 @@
// format.
// <Error>: CGImageDestinationFinalize image destination does not have enough images
// So instead we copy to 8888.
- if (bm.config() == SkBitmap::kARGB_4444_Config) {
- bm.copyTo(&bitmap8888, SkBitmap::kARGB_8888_Config);
+ if (bm.colorType() == kARGB_4444_SkColorType) {
+ bm.copyTo(&bitmap8888, kPMColor_SkColorType);
bmPtr = &bitmap8888;
}
type = kUTTypePNG;
diff --git a/src/utils/SkBitmapHasher.cpp b/src/utils/SkBitmapHasher.cpp
index 9f0affd..6c861cd 100644
--- a/src/utils/SkBitmapHasher.cpp
+++ b/src/utils/SkBitmapHasher.cpp
@@ -57,7 +57,7 @@
// Hmm, that didn't work. Maybe if we create a new
// kARGB_8888_Config version of the bitmap it will work better?
SkBitmap copyBitmap;
- if (!bitmap.copyTo(©Bitmap, SkBitmap::kARGB_8888_Config)) {
+ if (!bitmap.copyTo(©Bitmap, kPMColor_SkColorType)) {
return false;
}
return ComputeDigestInternal(copyBitmap, result);
diff --git a/src/utils/mac/SkCreateCGImageRef.cpp b/src/utils/mac/SkCreateCGImageRef.cpp
index 01f2dac..7687c3c 100644
--- a/src/utils/mac/SkCreateCGImageRef.cpp
+++ b/src/utils/mac/SkCreateCGImageRef.cpp
@@ -94,7 +94,7 @@
copy = new SkBitmap;
// here we make a ceep copy of the pixels, since CG won't take our
// 565 directly
- bm.copyTo(copy, SkBitmap::kARGB_8888_Config);
+ bm.copyTo(copy, kPMColor_SkColorType);
} else {
copy = new SkBitmap(bm);
}