aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-02-11 18:21:45 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-02-11 18:21:45 +0000
commit61e96cd44624c9faceb625519c1b29775b161f45 (patch)
tree8df9411f754568cfa13f4b9b63fcb626da13f2fc
parent44546f85d9170d9dbbb0423813c339c1def30074 (diff)
SkBitmap now really stores SkImageInfo -- config is just a ruse
BUG=skia: R=scroggo@google.com Author: reed@google.com Review URL: https://codereview.chromium.org/159653004 git-svn-id: http://skia.googlecode.com/svn/trunk@13411 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--include/core/SkBitmap.h114
-rw-r--r--include/core/SkImageInfo.h46
-rw-r--r--include/core/SkPathRef.h2
-rw-r--r--src/core/SkBitmap.cpp289
-rw-r--r--src/image/SkImagePriv.cpp38
-rw-r--r--src/image/SkImagePriv.h2
-rw-r--r--src/images/SkDecodingImageGenerator.cpp5
-rw-r--r--tests/ImageDecodingTest.cpp5
-rw-r--r--tests/PixelRefTest.cpp2
9 files changed, 245 insertions, 258 deletions
diff --git a/include/core/SkBitmap.h b/include/core/SkBitmap.h
index 87d4649228..42ef8778bf 100644
--- a/include/core/SkBitmap.h
+++ b/include/core/SkBitmap.h
@@ -79,10 +79,42 @@ public:
// This method is not exported to java.
void swap(SkBitmap& other);
+ ///////////////////////////////////////////////////////////////////////////
+
+ const SkImageInfo& info() const { return fInfo; }
+
+ int width() const { return fInfo.fWidth; }
+ int height() const { return fInfo.fHeight; }
+ SkColorType colorType() const { return fInfo.fColorType; }
+ SkAlphaType alphaType() const { return fInfo.fAlphaType; }
+
+ /** Return the number of bytes per pixel based on the config. If the config
+ does not have at least 1 byte per (e.g. kA1_Config) then 0 is returned.
+ */
+ int bytesPerPixel() const { return fInfo.bytesPerPixel(); }
+
+ /** Return the rowbytes expressed as a number of pixels (like width and
+ height). Note, for 1-byte per pixel configs like kA8_Config, this will
+ return the same as rowBytes(). Is undefined for configs that are less
+ than 1-byte per pixel (e.g. kA1_Config)
+ */
+ int rowBytesAsPixels() const {
+ return fRowBytes >> this->shiftPerPixel();
+ }
+
+ /** Return the shift amount per pixel (i.e. 0 for 1-byte per pixel, 1 for
+ 2-bytes per pixel configs, 2 for 4-bytes per pixel configs). Return 0
+ for configs that are not at least 1-byte per pixel (e.g. kA1_Config
+ or kNo_Config)
+ */
+ int shiftPerPixel() const { return this->bytesPerPixel() >> 1; }
+
+ ///////////////////////////////////////////////////////////////////////////
+
/** Return true iff the bitmap has empty dimensions.
* Hey! Before you use this, see if you really want to know drawsNothing() instead.
*/
- bool empty() const { return 0 == fWidth || 0 == fHeight; }
+ bool empty() const { return fInfo.isEmpty(); }
/** Return true iff the bitmap has no pixelref. Note: this can return true even if the
* dimensions of the bitmap are > 0 (see empty()).
@@ -95,41 +127,14 @@ public:
bool drawsNothing() const { return this->empty() || this->isNull(); }
/** Return the config for the bitmap. */
- Config config() const { return (Config)fConfig; }
+ Config config() const;
SK_ATTR_DEPRECATED("use config()")
Config getConfig() const { return this->config(); }
- /** Return the bitmap's width, in pixels. */
- int width() const { return fWidth; }
-
- /** Return the bitmap's height, in pixels. */
- int height() const { return fHeight; }
-
/** Return the number of bytes between subsequent rows of the bitmap. */
size_t rowBytes() const { return fRowBytes; }
- /** Return the shift amount per pixel (i.e. 0 for 1-byte per pixel, 1 for
- 2-bytes per pixel configs, 2 for 4-bytes per pixel configs). Return 0
- for configs that are not at least 1-byte per pixel (e.g. kA1_Config
- or kNo_Config)
- */
- int shiftPerPixel() const { return fBytesPerPixel >> 1; }
-
- /** Return the number of bytes per pixel based on the config. If the config
- does not have at least 1 byte per (e.g. kA1_Config) then 0 is returned.
- */
- int bytesPerPixel() const { return fBytesPerPixel; }
-
- /** Return the rowbytes expressed as a number of pixels (like width and
- height). Note, for 1-byte per pixel configs like kA8_Config, this will
- return the same as rowBytes(). Is undefined for configs that are less
- than 1-byte per pixel (e.g. kA1_Config)
- */
- int rowBytesAsPixels() const { return fRowBytes >> (fBytesPerPixel >> 1); }
-
- SkAlphaType alphaType() const { return (SkAlphaType)fAlphaType; }
-
/**
* Set the bitmap's alphaType, returning true on success. If false is
* returned, then the specified new alphaType is incompatible with the
@@ -149,19 +154,19 @@ public:
Note this truncates the result to 32bits. Call getSize64() to detect
if the real size exceeds 32bits.
*/
- size_t getSize() const { return fHeight * fRowBytes; }
+ size_t getSize() const { return fInfo.fHeight * fRowBytes; }
/** Return the number of bytes from the pointer returned by getPixels()
to the end of the allocated space in the buffer. Required in
cases where extractSubset has been called.
*/
- size_t getSafeSize() const ;
+ size_t getSafeSize() const { return fInfo.getSafeSize(fRowBytes); }
/**
* Return the full size of the bitmap, in bytes.
*/
int64_t computeSize64() const {
- return sk_64_mul(fHeight, fRowBytes);
+ return sk_64_mul(fInfo.fHeight, fRowBytes);
}
/**
@@ -170,7 +175,7 @@ public:
* than computeSize64() if there is any rowbytes padding beyond the width.
*/
int64_t computeSafeSize64() const {
- return ComputeSafeSize64((Config)fConfig, fWidth, fHeight, fRowBytes);
+ return fInfo.getSafeSize64(fRowBytes);
}
/** Returns true if this bitmap is marked as immutable, meaning that the
@@ -304,11 +309,18 @@ public:
void* context);
/**
- * If the bitmap's config can be represented as SkImageInfo, return true,
- * and if info is not-null, set it to the bitmap's info. If it cannot be
- * represented as SkImageInfo, return false and ignore the info parameter.
+ * DEPRECATED: call info().
*/
- bool asImageInfo(SkImageInfo* info) const;
+ bool asImageInfo(SkImageInfo* info) const {
+ // compatibility: return false for kUnknown
+ if (kUnknown_SkColorType == this->colorType()) {
+ return false;
+ }
+ if (info) {
+ *info = this->info();
+ }
+ return true;
+ }
/** Use this to assign a new pixel address for an existing bitmap. This
will automatically release any pixelref previously installed. Only call
@@ -450,8 +462,8 @@ public:
*/
GrTexture* getTexture() const;
- /** Return the bitmap's colortable, if it uses one (i.e. fConfig is
- kIndex8_Config) and the pixels are locked.
+ /** Return the bitmap's colortable, if it uses one (i.e. colorType is
+ Index_8) and the pixels are locked.
Otherwise returns NULL. Does not affect the colortable's
reference count.
*/
@@ -742,13 +754,11 @@ private:
#endif
};
+ SkImageInfo fInfo;
+
uint32_t fRowBytes;
- uint32_t fWidth;
- uint32_t fHeight;
- uint8_t fConfig;
- uint8_t fAlphaType;
+
uint8_t fFlags;
- uint8_t fBytesPerPixel; // based on config
void internalErase(const SkIRect&, U8CPU a, U8CPU r, U8CPU g, U8CPU b)const;
@@ -860,29 +870,29 @@ private:
inline uint32_t* SkBitmap::getAddr32(int x, int y) const {
SkASSERT(fPixels);
- SkASSERT(fConfig == kARGB_8888_Config);
- SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
+ SkASSERT(this->config() == kARGB_8888_Config);
+ SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height());
return (uint32_t*)((char*)fPixels + y * fRowBytes + (x << 2));
}
inline uint16_t* SkBitmap::getAddr16(int x, int y) const {
SkASSERT(fPixels);
- SkASSERT(fConfig == kRGB_565_Config || fConfig == kARGB_4444_Config);
- SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
+ SkASSERT(this->config() == kRGB_565_Config || this->config() == kARGB_4444_Config);
+ SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height());
return (uint16_t*)((char*)fPixels + y * fRowBytes + (x << 1));
}
inline uint8_t* SkBitmap::getAddr8(int x, int y) const {
SkASSERT(fPixels);
- SkASSERT(fConfig == kA8_Config || fConfig == kIndex8_Config);
- SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
+ SkASSERT(this->config() == kA8_Config || this->config() == kIndex8_Config);
+ SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height());
return (uint8_t*)fPixels + y * fRowBytes + x;
}
inline SkPMColor SkBitmap::getIndex8Color(int x, int y) const {
SkASSERT(fPixels);
- SkASSERT(fConfig == kIndex8_Config);
- SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
+ SkASSERT(this->config() == kIndex8_Config);
+ SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height());
SkASSERT(fColorTable);
return (*fColorTable)[*((const uint8_t*)fPixels + y * fRowBytes + x)];
}
diff --git a/include/core/SkImageInfo.h b/include/core/SkImageInfo.h
index 722ff27437..8ca87eba7a 100644
--- a/include/core/SkImageInfo.h
+++ b/include/core/SkImageInfo.h
@@ -8,7 +8,7 @@
#ifndef SkImageInfo_DEFINED
#define SkImageInfo_DEFINED
-#include "SkTypes.h"
+#include "SkMath.h"
#include "SkSize.h"
class SkWriteBuffer;
@@ -59,12 +59,17 @@ static inline bool SkAlphaTypeIsOpaque(SkAlphaType at) {
return (unsigned)at <= kOpaque_SkAlphaType;
}
+static inline bool SkAlphaTypeIsValid(unsigned value) {
+ return value <= kLastEnum_SkAlphaType;
+}
+
///////////////////////////////////////////////////////////////////////////////
/**
* Describes how to interpret the components of a pixel.
*/
enum SkColorType {
+ kUnknown_SkColorType,
kAlpha_8_SkColorType,
kRGB_565_SkColorType,
kARGB_4444_SkColorType,
@@ -85,6 +90,7 @@ enum SkColorType {
static int SkColorTypeBytesPerPixel(SkColorType ct) {
static const uint8_t gSize[] = {
+ 0, // Unknown
1, // Alpha_8
2, // RGB_565
2, // ARGB_4444
@@ -99,6 +105,14 @@ static int SkColorTypeBytesPerPixel(SkColorType ct) {
return gSize[ct];
}
+static inline size_t SkColorTypeMinRowBytes(SkColorType ct, int width) {
+ return width * SkColorTypeBytesPerPixel(ct);
+}
+
+static inline bool SkColorTypeIsValid(unsigned value) {
+ return value <= kLastEnum_SkColorType;
+}
+
///////////////////////////////////////////////////////////////////////////////
/**
@@ -159,16 +173,29 @@ struct SkImageInfo {
return info;
}
+ int width() const { return fWidth; }
+ int height() const { return fHeight; }
+ SkColorType colorType() const { return fColorType; }
+ SkAlphaType alphaType() const { return fAlphaType; }
+
+ bool isEmpty() const { return fWidth <= 0 || fHeight <= 0; }
+
bool isOpaque() const {
return SkAlphaTypeIsOpaque(fAlphaType);
}
+ SkISize dimensions() const { return SkISize::Make(fWidth, fHeight); }
+
int bytesPerPixel() const {
return SkColorTypeBytesPerPixel(fColorType);
}
+ uint64_t minRowBytes64() const {
+ return sk_64_mul(fWidth, this->bytesPerPixel());
+ }
+
size_t minRowBytes() const {
- return fWidth * this->bytesPerPixel();
+ return (size_t)this->minRowBytes64();
}
bool operator==(const SkImageInfo& other) const {
@@ -181,12 +208,23 @@ struct SkImageInfo {
void unflatten(SkReadBuffer&);
void flatten(SkWriteBuffer&) const;
- size_t getSafeSize(size_t rowBytes) const {
+ int64_t getSafeSize64(size_t rowBytes) const {
if (0 == fHeight) {
return 0;
}
- return (fHeight - 1) * rowBytes + fWidth * this->bytesPerPixel();
+ return sk_64_mul(fHeight - 1, rowBytes) + fWidth * this->bytesPerPixel();
}
+
+ size_t getSafeSize(size_t rowBytes) const {
+ return (size_t)this->getSafeSize64(rowBytes);
+ }
+
+ bool validRowBytes(size_t rowBytes) const {
+ uint64_t rb = sk_64_mul(fWidth, this->bytesPerPixel());
+ return rowBytes >= rb;
+ }
+
+ SkDEBUGCODE(void validate() const;)
};
#endif
diff --git a/include/core/SkPathRef.h b/include/core/SkPathRef.h
index 3c663f7f7d..2e8c5474fa 100644
--- a/include/core/SkPathRef.h
+++ b/include/core/SkPathRef.h
@@ -106,7 +106,7 @@ public:
// In some cases we need to inject a leading moveTo before we add points
// for lineTo, quadTo, conicTo, cubicTo
- //
+ //
// SkPath path; path.lineTo(...); <--- need a leading moveTo(0, 0)
// SkPath path; ... path.close(); path.lineTo(...) <-- need a moveTo(previous moveTo)
void injectMoveToIfNeeded() { fPathRef->injectMoveToIfNeeded(); }
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index 6a70c1e089..96d683c0e2 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -24,6 +24,11 @@
#include "SkPackBits.h"
#include <new>
+static bool reset_return_false(SkBitmap* bm) {
+ bm->reset();
+ return false;
+}
+
struct MipLevel {
void* fPixels;
uint32_t fRowBytes;
@@ -125,13 +130,9 @@ void SkBitmap::swap(SkBitmap& other) {
SkTSwap(fPixelLockCount, other.fPixelLockCount);
SkTSwap(fMipMap, other.fMipMap);
SkTSwap(fPixels, other.fPixels);
+ SkTSwap(fInfo, other.fInfo);
SkTSwap(fRowBytes, other.fRowBytes);
- SkTSwap(fWidth, other.fWidth);
- SkTSwap(fHeight, other.fHeight);
- SkTSwap(fConfig, other.fConfig);
- SkTSwap(fAlphaType, other.fAlphaType);
SkTSwap(fFlags, other.fFlags);
- SkTSwap(fBytesPerPixel, other.fBytesPerPixel);
SkDEBUGCODE(this->validate();)
}
@@ -141,6 +142,10 @@ void SkBitmap::reset() {
sk_bzero(this, sizeof(*this));
}
+SkBitmap::Config SkBitmap::config() const {
+ return SkColorTypeToBitmapConfig(fInfo.colorType());
+}
+
int SkBitmap::ComputeBytesPerPixel(SkBitmap::Config config) {
int bpp;
switch (config) {
@@ -167,39 +172,12 @@ int SkBitmap::ComputeBytesPerPixel(SkBitmap::Config config) {
}
size_t SkBitmap::ComputeRowBytes(Config c, int width) {
- if (width < 0) {
- return 0;
- }
-
- int64_t rowBytes = 0;
-
- switch (c) {
- case kNo_Config:
- break;
- case kA8_Config:
- case kIndex8_Config:
- rowBytes = width;
- break;
- case kRGB_565_Config:
- case kARGB_4444_Config:
- // assign and then shift, so we don't overflow int
- rowBytes = width;
- rowBytes <<= 1;
- break;
- case kARGB_8888_Config:
- // assign and then shift, so we don't overflow int
- rowBytes = width;
- rowBytes <<= 2;
- break;
- default:
- SkDEBUGFAIL("unknown config");
- break;
- }
- return sk_64_isS32(rowBytes) ? sk_64_asS32(rowBytes) : 0;
+ return SkColorTypeMinRowBytes(SkBitmapConfigToColorType(c), width);
}
int64_t SkBitmap::ComputeSize64(Config config, int width, int height) {
- int64_t rowBytes = sk_64_mul(ComputeBytesPerPixel(config), width);
+ SkColorType ct = SkBitmapConfigToColorType(config);
+ int64_t rowBytes = sk_64_mul(SkColorTypeBytesPerPixel(ct), width);
return rowBytes * height;
}
@@ -212,13 +190,10 @@ int64_t SkBitmap::ComputeSafeSize64(Config config,
uint32_t width,
uint32_t height,
size_t rowBytes) {
- int64_t safeSize = 0;
- if (height > 0) {
- int64_t lastRow = sk_64_mul(ComputeBytesPerPixel(config), width);
- safeSize = sk_64_mul(height - 1, rowBytes) + lastRow;
- }
- SkASSERT(safeSize >= 0);
- return safeSize;
+ SkImageInfo info = SkImageInfo::Make(width, height,
+ SkBitmapConfigToColorType(config),
+ kPremul_SkAlphaType);
+ return info.getSafeSize64(rowBytes);
}
size_t SkBitmap::ComputeSafeSize(Config config,
@@ -237,35 +212,36 @@ size_t SkBitmap::ComputeSafeSize(Config config,
void SkBitmap::getBounds(SkRect* bounds) const {
SkASSERT(bounds);
bounds->set(0, 0,
- SkIntToScalar(fWidth), SkIntToScalar(fHeight));
+ SkIntToScalar(fInfo.fWidth), SkIntToScalar(fInfo.fHeight));
}
void SkBitmap::getBounds(SkIRect* bounds) const {
SkASSERT(bounds);
- bounds->set(0, 0, fWidth, fHeight);
+ bounds->set(0, 0, fInfo.fWidth, fInfo.fHeight);
}
///////////////////////////////////////////////////////////////////////////////
-static bool validate_alphaType(SkBitmap::Config config, SkAlphaType alphaType,
+static bool validate_alphaType(SkColorType colorType, SkAlphaType alphaType,
SkAlphaType* canonical = NULL) {
- switch (config) {
- case SkBitmap::kNo_Config:
+ switch (colorType) {
+ case kUnknown_SkColorType:
alphaType = kIgnore_SkAlphaType;
break;
- case SkBitmap::kA8_Config:
+ case kAlpha_8_SkColorType:
if (kUnpremul_SkAlphaType == alphaType) {
alphaType = kPremul_SkAlphaType;
}
// fall-through
- case SkBitmap::kIndex8_Config:
- case SkBitmap::kARGB_4444_Config:
- case SkBitmap::kARGB_8888_Config:
+ case kIndex_8_SkColorType:
+ case kARGB_4444_SkColorType:
+ case kRGBA_8888_SkColorType:
+ case kBGRA_8888_SkColorType:
if (kIgnore_SkAlphaType == alphaType) {
return false;
}
break;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
alphaType = kOpaque_SkAlphaType;
break;
default:
@@ -277,52 +253,48 @@ static bool validate_alphaType(SkBitmap::Config config, SkAlphaType alphaType,
return true;
}
-bool SkBitmap::setConfig(Config config, int width, int height, size_t rowBytes,
- SkAlphaType alphaType) {
- if ((width | height) < 0) {
- goto BAD_CONFIG;
+bool SkBitmap::setConfig(const SkImageInfo& info, size_t rowBytes) {
+ // require that rowBytes fit in 31bits
+ int64_t mrb = info.minRowBytes64();
+ if ((int32_t)mrb != mrb) {
+ return reset_return_false(this);
}
- if (rowBytes == 0) {
- rowBytes = SkBitmap::ComputeRowBytes(config, width);
- if (0 == rowBytes && kNo_Config != config && width > 0) {
- goto BAD_CONFIG;
- }
+ if ((int64_t)rowBytes != (int32_t)rowBytes) {
+ return reset_return_false(this);
}
- if (!validate_alphaType(config, alphaType, &alphaType)) {
- goto BAD_CONFIG;
+ if (info.width() < 0 || info.height() < 0) {
+ return reset_return_false(this);
}
- this->freePixels();
-
- fConfig = SkToU8(config);
- fAlphaType = SkToU8(alphaType);
- fWidth = width;
- fHeight = height;
- fRowBytes = SkToU32(rowBytes);
+ if (kUnknown_SkColorType == info.colorType()) {
+ rowBytes = 0;
+ } else if (0 == rowBytes) {
+ rowBytes = (size_t)mrb;
+ } else if (rowBytes < info.minRowBytes()) {
+ return reset_return_false(this);
+ }
- fBytesPerPixel = (uint8_t)ComputeBytesPerPixel(config);
+ this->freePixels();
- SkDEBUGCODE(this->validate();)
+ fInfo = info;
+ fRowBytes = SkToU32(rowBytes);
return true;
-
- // if we got here, we had an error, so we reset the bitmap to empty
-BAD_CONFIG:
- this->reset();
- return false;
}
-bool SkBitmap::setConfig(const SkImageInfo& info, size_t rowBytes) {
- return this->setConfig(SkImageInfoToBitmapConfig(info), info.fWidth,
- info.fHeight, rowBytes, info.fAlphaType);
+bool SkBitmap::setConfig(Config config, int width, int height, size_t rowBytes,
+ SkAlphaType alphaType) {
+ SkColorType ct = SkBitmapConfigToColorType(config);
+ return this->setConfig(SkImageInfo::Make(width, height, ct, alphaType),
+ rowBytes);
}
bool SkBitmap::setAlphaType(SkAlphaType alphaType) {
- if (!validate_alphaType(this->config(), alphaType, &alphaType)) {
+ if (!validate_alphaType(fInfo.fColorType, alphaType, &alphaType)) {
return false;
}
- if (fAlphaType != alphaType) {
- fAlphaType = SkToU8(alphaType);
+ if (fInfo.fAlphaType != alphaType) {
+ fInfo.fAlphaType = alphaType;
if (fPixelRef) {
fPixelRef->changeAlphaType(alphaType);
}
@@ -339,7 +311,7 @@ void SkBitmap::updatePixelsFromRef() const {
if (NULL != p) {
p = (char*)p
+ fPixelRefOrigin.fY * fRowBytes
- + fPixelRefOrigin.fX * fBytesPerPixel;
+ + fPixelRefOrigin.fX * fInfo.bytesPerPixel();
}
fPixels = p;
fColorTable = fPixelRef->colorTable();
@@ -379,20 +351,6 @@ static bool config_to_colorType(SkBitmap::Config config, SkColorType* ctOut) {
return true;
}
-bool SkBitmap::asImageInfo(SkImageInfo* info) const {
- SkColorType ct;
- if (!config_to_colorType(this->config(), &ct)) {
- return false;
- }
- if (info) {
- info->fWidth = fWidth;
- info->fHeight = fHeight;
- info->fAlphaType = this->alphaType();
- info->fColorType = ct;
- }
- return true;
-}
-
SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, int dx, int dy) {
#ifdef SK_DEBUG
if (pr) {
@@ -404,7 +362,7 @@ SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, int dx, int dy) {
SkASSERT(info.fColorType == prInfo.fColorType);
switch (prInfo.fAlphaType) {
case kIgnore_SkAlphaType:
- SkASSERT(fAlphaType == kIgnore_SkAlphaType);
+ SkASSERT(fInfo.fAlphaType == kIgnore_SkAlphaType);
break;
case kOpaque_SkAlphaType:
case kPremul_SkAlphaType:
@@ -502,11 +460,6 @@ bool SkBitmap::allocPixels(Allocator* allocator, SkColorTable* 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) {
@@ -562,10 +515,6 @@ bool SkBitmap::allocConfigPixels(Config config, int width, int height,
}
SkAlphaType at = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
- if (!validate_alphaType(config, at, &at)) {
- return false;
- }
-
return this->allocPixels(SkImageInfo::Make(width, height, ct, at));
}
@@ -637,13 +586,6 @@ bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst,
///////////////////////////////////////////////////////////////////////////////
-size_t SkBitmap::getSafeSize() const {
- // This is intended to be a size_t version of ComputeSafeSize64(), just
- // faster. The computation is meant to be identical.
- return (fHeight ? ((fHeight - 1) * fRowBytes) +
- ComputeRowBytes(this->config(), fWidth): 0);
-}
-
bool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize,
size_t dstRowBytes, bool preserveDstPad) const {
@@ -651,9 +593,10 @@ bool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize,
dstRowBytes = fRowBytes;
}
- if (dstRowBytes < ComputeRowBytes(this->config(), fWidth) ||
- dst == NULL || (getPixels() == NULL && pixelRef() == NULL))
+ if (dstRowBytes < fInfo.minRowBytes() ||
+ dst == NULL || (getPixels() == NULL && pixelRef() == NULL)) {
return false;
+ }
if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == fRowBytes) {
size_t safeSize = this->getSafeSize();
@@ -670,16 +613,15 @@ bool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize,
}
} else {
// If destination has different stride than us, then copy line by line.
- if (ComputeSafeSize(this->config(), fWidth, fHeight, dstRowBytes) >
- dstSize)
+ if (fInfo.getSafeSize(dstRowBytes) > dstSize) {
return false;
- else {
+ } else {
// Just copy what we need on each line.
- size_t rowBytes = ComputeRowBytes(this->config(), fWidth);
+ size_t rowBytes = fInfo.minRowBytes();
SkAutoLockPixels lock(*this);
const uint8_t* srcP = reinterpret_cast<const uint8_t*>(getPixels());
uint8_t* dstP = reinterpret_cast<uint8_t*>(dst);
- for (uint32_t row = 0; row < fHeight;
+ for (int row = 0; row < fInfo.fHeight;
row++, srcP += fRowBytes, dstP += dstRowBytes) {
memcpy(dstP, srcP, rowBytes);
}
@@ -723,19 +665,19 @@ void* SkBitmap::getAddr(int x, int y) const {
char* base = (char*)this->getPixels();
if (base) {
base += y * this->rowBytes();
- switch (this->config()) {
- case SkBitmap::kARGB_8888_Config:
+ switch (this->colorType()) {
+ case kRGBA_8888_SkColorType:
+ case kBGRA_8888_SkColorType:
base += x << 2;
break;
- case SkBitmap::kARGB_4444_Config:
- case SkBitmap::kRGB_565_Config:
+ case kARGB_4444_SkColorType:
+ case kRGB_565_SkColorType:
base += x << 1;
break;
- case SkBitmap::kA8_Config:
- case SkBitmap::kIndex8_Config:
+ case kAlpha_8_SkColorType:
+ case kIndex_8_SkColorType:
base += x;
break;
- break;
default:
SkDEBUGFAIL("Can't return addr for config");
base = NULL;
@@ -873,8 +815,12 @@ void SkBitmap::internalErase(const SkIRect& area,
}
#endif
- if (kNo_Config == fConfig || kIndex8_Config == fConfig) {
- return;
+ switch (fInfo.colorType()) {
+ case kUnknown_SkColorType:
+ case kIndex_8_SkColorType:
+ return; // can't erase
+ default:
+ break;
}
SkAutoLockPixels alp(*this);
@@ -894,8 +840,8 @@ void SkBitmap::internalErase(const SkIRect& area,
b = SkAlphaMul(b, a);
}
- switch (fConfig) {
- case kA8_Config: {
+ switch (this->colorType()) {
+ case kAlpha_8_SkColorType: {
uint8_t* p = this->getAddr8(area.fLeft, area.fTop);
while (--height >= 0) {
memset(p, a, width);
@@ -903,12 +849,12 @@ void SkBitmap::internalErase(const SkIRect& area,
}
break;
}
- case kARGB_4444_Config:
- case kRGB_565_Config: {
+ case kARGB_4444_SkColorType:
+ case kRGB_565_SkColorType: {
uint16_t* p = this->getAddr16(area.fLeft, area.fTop);;
uint16_t v;
- if (kARGB_4444_Config == fConfig) {
+ if (kARGB_4444_SkColorType == this->colorType()) {
v = pack_8888_to_4444(a, r, g, b);
} else {
v = SkPackRGB16(r >> (8 - SK_R16_BITS),
@@ -921,7 +867,9 @@ void SkBitmap::internalErase(const SkIRect& area,
}
break;
}
- case kARGB_8888_Config: {
+ case kPMColor_SkColorType: {
+ // what to do about BGRA or RGBA (which ever is != PMColor ?
+ // for now we don't support them.
uint32_t* p = this->getAddr32(area.fLeft, area.fTop);
uint32_t v = SkPackARGB32(a, r, g, b);
@@ -931,6 +879,8 @@ void SkBitmap::internalErase(const SkIRect& area,
}
break;
}
+ default:
+ return; // no change, so don't call notifyPixelsChanged()
}
this->notifyPixelsChanged();
@@ -1046,7 +996,8 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
if (fPixelRef) {
SkIRect subset;
- subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY, fWidth, fHeight);
+ subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY,
+ fInfo.width(), fInfo.height());
if (fPixelRef->readPixels(&tmpSrc, &subset)) {
SkASSERT(tmpSrc.width() == this->width());
SkASSERT(tmpSrc.height() == this->height());
@@ -1160,6 +1111,8 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
}
bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const {
+ const SkColorType dstCT = SkBitmapConfigToColorType(dstConfig);
+
if (!this->canCopyTo(dstConfig)) {
return false;
}
@@ -1170,7 +1123,7 @@ bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const {
SkPixelRef* pixelRef = fPixelRef->deepCopy(dstConfig);
if (pixelRef) {
uint32_t rowBytes;
- if (dstConfig == fConfig) {
+ if (this->colorType() == dstCT) {
// Since there is no subset to pass to deepCopy, and deepCopy
// succeeded, the new pixel ref must be identical.
SkASSERT(fPixelRef->info() == pixelRef->info());
@@ -1181,7 +1134,12 @@ bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const {
// With the new config, an appropriate fRowBytes will be computed by setConfig.
rowBytes = 0;
}
- dst->setConfig(dstConfig, fWidth, fHeight, rowBytes);
+
+ SkImageInfo info = fInfo;
+ info.fColorType = dstCT;
+ if (!dst->setConfig(info, rowBytes)) {
+ return false;
+ }
dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref();
return true;
}
@@ -1584,11 +1542,8 @@ enum {
};
void SkBitmap::flatten(SkWriteBuffer& buffer) const {
- buffer.writeInt(fWidth);
- buffer.writeInt(fHeight);
+ fInfo.flatten(buffer);
buffer.writeInt(fRowBytes);
- buffer.writeInt(fConfig);
- buffer.writeInt(fAlphaType);
if (fPixelRef) {
if (fPixelRef->getFactory()) {
@@ -1608,19 +1563,17 @@ void SkBitmap::flatten(SkWriteBuffer& buffer) const {
void SkBitmap::unflatten(SkReadBuffer& buffer) {
this->reset();
- int width = buffer.readInt();
- int height = buffer.readInt();
- int rowBytes = buffer.readInt();
- Config config = (Config)buffer.readInt();
- SkAlphaType alphaType = (SkAlphaType)buffer.readInt();
- buffer.validate((width >= 0) && (height >= 0) && (rowBytes >= 0) &&
- SkIsValidConfig(config) && validate_alphaType(config, alphaType));
+ SkImageInfo info;
+ info.unflatten(buffer);
+ size_t rowBytes = buffer.readInt();
+ buffer.validate((info.width() >= 0) && (info.height() >= 0) &&
+ SkColorTypeIsValid(info.fColorType) &&
+ SkAlphaTypeIsValid(info.fAlphaType) &&
+ validate_alphaType(info.fColorType, info.fAlphaType) &&
+ info.validRowBytes(rowBytes));
- bool configIsValid = this->setConfig(config, width, height, rowBytes, alphaType);
- // Note : Using (fRowBytes >= (fWidth * fBytesPerPixel)) in the following test can create false
- // positives if the multiplication causes an integer overflow. Use the division instead.
- buffer.validate(configIsValid && (fBytesPerPixel > 0) &&
- ((fRowBytes / fBytesPerPixel) >= fWidth));
+ bool configIsValid = this->setConfig(info, rowBytes);
+ buffer.validate(configIsValid);
int reftype = buffer.readInt();
if (buffer.validate((SERIALIZE_PIXELTYPE_REF_DATA == reftype) ||
@@ -1630,7 +1583,7 @@ void SkBitmap::unflatten(SkReadBuffer& buffer) {
SkIPoint origin;
origin.fX = buffer.readInt();
origin.fY = buffer.readInt();
- size_t offset = origin.fY * rowBytes + origin.fX * fBytesPerPixel;
+ size_t offset = origin.fY * rowBytes + origin.fX * info.bytesPerPixel();
SkPixelRef* pr = buffer.readPixelRef();
if (!buffer.validate((NULL == pr) ||
(pr->getAllocatedSizeInBytes() >= (offset + this->getSafeSize())))) {
@@ -1663,15 +1616,14 @@ SkBitmap::RLEPixels::~RLEPixels() {
#ifdef SK_DEBUG
void SkBitmap::validate() const {
- SkASSERT(fConfig < kConfigCount);
- SkASSERT(fRowBytes >= (unsigned)ComputeRowBytes((Config)fConfig, fWidth));
+ fInfo.validate();
+ SkASSERT(fInfo.validRowBytes(fRowBytes));
uint8_t allFlags = kImageIsOpaque_Flag | kImageIsVolatile_Flag | kImageIsImmutable_Flag;
#ifdef SK_BUILD_FOR_ANDROID
allFlags |= kHasHardwareMipMap_Flag;
#endif
SkASSERT(fFlags <= allFlags);
SkASSERT(fPixelLockCount >= 0);
- SkASSERT((uint8_t)ComputeBytesPerPixel((Config)fConfig) == fBytesPerPixel);
if (fPixels) {
SkASSERT(fPixelRef);
@@ -1680,9 +1632,9 @@ void SkBitmap::validate() const {
SkASSERT(fPixelRef->rowBytes() == fRowBytes);
SkASSERT(fPixelRefOrigin.fX >= 0);
SkASSERT(fPixelRefOrigin.fY >= 0);
- SkASSERT(fPixelRef->info().fWidth >= (int)fWidth + fPixelRefOrigin.fX);
- SkASSERT(fPixelRef->info().fHeight >= (int)fHeight + fPixelRefOrigin.fY);
- SkASSERT(fPixelRef->rowBytes() >= fWidth * fBytesPerPixel);
+ SkASSERT(fPixelRef->info().width() >= (int)this->width() + fPixelRefOrigin.fX);
+ SkASSERT(fPixelRef->info().fHeight >= (int)this->height() + fPixelRefOrigin.fY);
+ SkASSERT(fPixelRef->rowBytes() >= fInfo.minRowBytes());
} else {
SkASSERT(NULL == fColorTable);
}
@@ -1728,3 +1680,14 @@ void SkBitmap::toString(SkString* str) const {
str->append(")");
}
#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef SK_DEBUG
+void SkImageInfo::validate() const {
+ SkASSERT(fWidth >= 0);
+ SkASSERT(fHeight >= 0);
+ SkASSERT(SkColorTypeIsValid(fColorType));
+ SkASSERT(SkAlphaTypeIsValid(fAlphaType));
+}
+#endif
diff --git a/src/image/SkImagePriv.cpp b/src/image/SkImagePriv.cpp
index 43cc44b2fa..a044aad0a0 100644
--- a/src/image/SkImagePriv.cpp
+++ b/src/image/SkImagePriv.cpp
@@ -37,35 +37,19 @@ SkBitmap::Config SkImageInfoToBitmapConfig(const SkImageInfo& info) {
return SkColorTypeToBitmapConfig(info.fColorType);
}
-bool SkBitmapConfigToColorType(SkBitmap::Config config, SkColorType* ctOut) {
- SkColorType ct;
- switch (config) {
- case SkBitmap::kA8_Config:
- ct = kAlpha_8_SkColorType;
- break;
- case SkBitmap::kIndex8_Config:
- ct = kIndex_8_SkColorType;
- break;
- case SkBitmap::kRGB_565_Config:
- ct = kRGB_565_SkColorType;
- break;
- case SkBitmap::kARGB_4444_Config:
- ct = kARGB_4444_SkColorType;
- break;
- case SkBitmap::kARGB_8888_Config:
- ct = kPMColor_SkColorType;
- break;
- case SkBitmap::kNo_Config:
- default:
- return false;
- }
- if (ctOut) {
- *ctOut = ct;
- }
- return true;
+SkColorType SkBitmapConfigToColorType(SkBitmap::Config config) {
+ static const SkColorType gCT[] = {
+ kUnknown_SkColorType, // kNo_Config
+ kAlpha_8_SkColorType, // kA8_Config
+ kIndex_8_SkColorType, // kIndex8_Config
+ kRGB_565_SkColorType, // kRGB_565_Config
+ kARGB_4444_SkColorType, // kARGB_4444_Config
+ kPMColor_SkColorType, // kARGB_8888_Config
+ };
+ SkASSERT((unsigned)config < SK_ARRAY_COUNT(gCT));
+ return gCT[config];
}
-
SkImage* SkNewImageFromBitmap(const SkBitmap& bm, bool canSharePixelRef) {
SkImageInfo info;
if (!bm.asImageInfo(&info)) {
diff --git a/src/image/SkImagePriv.h b/src/image/SkImagePriv.h
index 7c19c734c2..8883e2c070 100644
--- a/src/image/SkImagePriv.h
+++ b/src/image/SkImagePriv.h
@@ -15,7 +15,7 @@ class SkPicture;
extern SkBitmap::Config SkImageInfoToBitmapConfig(const SkImageInfo&);
extern SkBitmap::Config SkColorTypeToBitmapConfig(SkColorType);
-extern bool SkBitmapConfigToColorType(SkBitmap::Config, SkColorType* ctOut);
+extern SkColorType SkBitmapConfigToColorType(SkBitmap::Config);
// Call this if you explicitly want to use/share this pixelRef in the image
extern SkImage* SkNewImageFromPixelRef(const SkImageInfo&, SkPixelRef*,
diff --git a/src/images/SkDecodingImageGenerator.cpp b/src/images/SkDecodingImageGenerator.cpp
index 153d1e220b..1e28136603 100644
--- a/src/images/SkDecodingImageGenerator.cpp
+++ b/src/images/SkDecodingImageGenerator.cpp
@@ -275,11 +275,6 @@ SkImageGenerator* SkDecodingImageGenerator::Create(
info.fHeight = bitmap.height();
info.fColorType = opts.fRequestedColorType;
info.fAlphaType = bitmap.alphaType();
-
- // Sanity check.
- SkDEBUGCODE(SkColorType tmp;)
- SkASSERT(SkBitmapConfigToColorType(config, &tmp));
- SkASSERT(tmp == opts.fRequestedColorType);
}
return SkNEW_ARGS(SkDecodingImageGenerator,
(data, autoStream.detach(), info,
diff --git a/tests/ImageDecodingTest.cpp b/tests/ImageDecodingTest.cpp
index 81f900660d..2e0225a261 100644
--- a/tests/ImageDecodingTest.cpp
+++ b/tests/ImageDecodingTest.cpp
@@ -333,10 +333,7 @@ static SkPixelRef* install_pixel_ref(SkBitmap* bitmap,
SkASSERT(stream != NULL);
SkASSERT(stream->rewind());
SkASSERT(stream->unique());
- SkColorType colorType;
- if (!SkBitmapConfigToColorType(bitmap->config(), &colorType)) {
- return NULL;
- }
+ SkColorType colorType = bitmap->colorType();
SkDecodingImageGenerator::Options opts(sampleSize, ditherImage, colorType);
SkAutoTDelete<SkImageGenerator> gen(
SkDecodingImageGenerator::Create(stream, opts));
diff --git a/tests/PixelRefTest.cpp b/tests/PixelRefTest.cpp
index c0bdf54c25..aeb3070eac 100644
--- a/tests/PixelRefTest.cpp
+++ b/tests/PixelRefTest.cpp
@@ -30,7 +30,7 @@ static void test_info(skiatest::Reporter* reporter) {
REPORTER_ASSERT(reporter, success);
success = bitmap.asImageInfo(&info);
REPORTER_ASSERT(reporter, success == gRec[i].fExpectedSuccess);
- if (gRec[i].fExpectedSuccess) {
+ if (success && gRec[i].fExpectedSuccess) {
REPORTER_ASSERT(reporter, info.fAlphaType == gRec[i].fAlphaType);
REPORTER_ASSERT(reporter, info.fColorType == gRec[i].fExpectedColorType);
}