Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Unified Diff: src/core/SkBitmap.cpp

Issue 147733004: Revert "SkBitmap now really stores SkImageInfo -- config is just a ruse" (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « include/core/SkPathRef.h ('k') | src/gpu/GrClipMaskManager.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkBitmap.cpp
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index 96d683c0e2592765351bcf5e9912085b660093a6..6a70c1e089288cf93c99623c88ab6d1dca5b9ecc 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -24,11 +24,6 @@
#include "SkPackBits.h"
#include <new>
-static bool reset_return_false(SkBitmap* bm) {
- bm->reset();
- return false;
-}
-
struct MipLevel {
void* fPixels;
uint32_t fRowBytes;
@@ -130,9 +125,13 @@ 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();)
}
@@ -142,10 +141,6 @@ 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) {
@@ -172,12 +167,39 @@ int SkBitmap::ComputeBytesPerPixel(SkBitmap::Config config) {
}
size_t SkBitmap::ComputeRowBytes(Config c, int width) {
- return SkColorTypeMinRowBytes(SkBitmapConfigToColorType(c), 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;
}
int64_t SkBitmap::ComputeSize64(Config config, int width, int height) {
- SkColorType ct = SkBitmapConfigToColorType(config);
- int64_t rowBytes = sk_64_mul(SkColorTypeBytesPerPixel(ct), width);
+ int64_t rowBytes = sk_64_mul(ComputeBytesPerPixel(config), width);
return rowBytes * height;
}
@@ -190,10 +212,13 @@ int64_t SkBitmap::ComputeSafeSize64(Config config,
uint32_t width,
uint32_t height,
size_t rowBytes) {
- SkImageInfo info = SkImageInfo::Make(width, height,
- SkBitmapConfigToColorType(config),
- kPremul_SkAlphaType);
- return info.getSafeSize64(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;
}
size_t SkBitmap::ComputeSafeSize(Config config,
@@ -212,36 +237,35 @@ size_t SkBitmap::ComputeSafeSize(Config config,
void SkBitmap::getBounds(SkRect* bounds) const {
SkASSERT(bounds);
bounds->set(0, 0,
- SkIntToScalar(fInfo.fWidth), SkIntToScalar(fInfo.fHeight));
+ SkIntToScalar(fWidth), SkIntToScalar(fHeight));
}
void SkBitmap::getBounds(SkIRect* bounds) const {
SkASSERT(bounds);
- bounds->set(0, 0, fInfo.fWidth, fInfo.fHeight);
+ bounds->set(0, 0, fWidth, fHeight);
}
///////////////////////////////////////////////////////////////////////////////
-static bool validate_alphaType(SkColorType colorType, SkAlphaType alphaType,
+static bool validate_alphaType(SkBitmap::Config config, SkAlphaType alphaType,
SkAlphaType* canonical = NULL) {
- switch (colorType) {
- case kUnknown_SkColorType:
+ switch (config) {
+ case SkBitmap::kNo_Config:
alphaType = kIgnore_SkAlphaType;
break;
- case kAlpha_8_SkColorType:
+ case SkBitmap::kA8_Config:
if (kUnpremul_SkAlphaType == alphaType) {
alphaType = kPremul_SkAlphaType;
}
// fall-through
- case kIndex_8_SkColorType:
- case kARGB_4444_SkColorType:
- case kRGBA_8888_SkColorType:
- case kBGRA_8888_SkColorType:
+ case SkBitmap::kIndex8_Config:
+ case SkBitmap::kARGB_4444_Config:
+ case SkBitmap::kARGB_8888_Config:
if (kIgnore_SkAlphaType == alphaType) {
return false;
}
break;
- case kRGB_565_SkColorType:
+ case SkBitmap::kRGB_565_Config:
alphaType = kOpaque_SkAlphaType;
break;
default:
@@ -253,48 +277,52 @@ static bool validate_alphaType(SkColorType colorType, SkAlphaType alphaType,
return true;
}
-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 ((int64_t)rowBytes != (int32_t)rowBytes) {
- return reset_return_false(this);
+bool SkBitmap::setConfig(Config config, int width, int height, size_t rowBytes,
+ SkAlphaType alphaType) {
+ if ((width | height) < 0) {
+ goto BAD_CONFIG;
}
-
- if (info.width() < 0 || info.height() < 0) {
- 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 (kUnknown_SkColorType == info.colorType()) {
- rowBytes = 0;
- } else if (0 == rowBytes) {
- rowBytes = (size_t)mrb;
- } else if (rowBytes < info.minRowBytes()) {
- return reset_return_false(this);
+ if (!validate_alphaType(config, alphaType, &alphaType)) {
+ goto BAD_CONFIG;
}
this->freePixels();
- fInfo = info;
- fRowBytes = SkToU32(rowBytes);
+ fConfig = SkToU8(config);
+ fAlphaType = SkToU8(alphaType);
+ fWidth = width;
+ fHeight = height;
+ fRowBytes = SkToU32(rowBytes);
+
+ fBytesPerPixel = (uint8_t)ComputeBytesPerPixel(config);
+
+ SkDEBUGCODE(this->validate();)
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(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::setConfig(const SkImageInfo& info, size_t rowBytes) {
+ return this->setConfig(SkImageInfoToBitmapConfig(info), info.fWidth,
+ info.fHeight, rowBytes, info.fAlphaType);
}
bool SkBitmap::setAlphaType(SkAlphaType alphaType) {
- if (!validate_alphaType(fInfo.fColorType, alphaType, &alphaType)) {
+ if (!validate_alphaType(this->config(), alphaType, &alphaType)) {
return false;
}
- if (fInfo.fAlphaType != alphaType) {
- fInfo.fAlphaType = alphaType;
+ if (fAlphaType != alphaType) {
+ fAlphaType = SkToU8(alphaType);
if (fPixelRef) {
fPixelRef->changeAlphaType(alphaType);
}
@@ -311,7 +339,7 @@ void SkBitmap::updatePixelsFromRef() const {
if (NULL != p) {
p = (char*)p
+ fPixelRefOrigin.fY * fRowBytes
- + fPixelRefOrigin.fX * fInfo.bytesPerPixel();
+ + fPixelRefOrigin.fX * fBytesPerPixel;
}
fPixels = p;
fColorTable = fPixelRef->colorTable();
@@ -351,6 +379,20 @@ 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) {
@@ -362,7 +404,7 @@ SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, int dx, int dy) {
SkASSERT(info.fColorType == prInfo.fColorType);
switch (prInfo.fAlphaType) {
case kIgnore_SkAlphaType:
- SkASSERT(fInfo.fAlphaType == kIgnore_SkAlphaType);
+ SkASSERT(fAlphaType == kIgnore_SkAlphaType);
break;
case kOpaque_SkAlphaType:
case kPremul_SkAlphaType:
@@ -460,6 +502,11 @@ 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) {
@@ -515,6 +562,10 @@ 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));
}
@@ -586,6 +637,13 @@ 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 {
@@ -593,10 +651,9 @@ bool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize,
dstRowBytes = fRowBytes;
}
- if (dstRowBytes < fInfo.minRowBytes() ||
- dst == NULL || (getPixels() == NULL && pixelRef() == NULL)) {
+ if (dstRowBytes < ComputeRowBytes(this->config(), fWidth) ||
+ dst == NULL || (getPixels() == NULL && pixelRef() == NULL))
return false;
- }
if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == fRowBytes) {
size_t safeSize = this->getSafeSize();
@@ -613,15 +670,16 @@ bool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize,
}
} else {
// If destination has different stride than us, then copy line by line.
- if (fInfo.getSafeSize(dstRowBytes) > dstSize) {
+ if (ComputeSafeSize(this->config(), fWidth, fHeight, dstRowBytes) >
+ dstSize)
return false;
- } else {
+ else {
// Just copy what we need on each line.
- size_t rowBytes = fInfo.minRowBytes();
+ size_t rowBytes = ComputeRowBytes(this->config(), fWidth);
SkAutoLockPixels lock(*this);
const uint8_t* srcP = reinterpret_cast<const uint8_t*>(getPixels());
uint8_t* dstP = reinterpret_cast<uint8_t*>(dst);
- for (int row = 0; row < fInfo.fHeight;
+ for (uint32_t row = 0; row < fHeight;
row++, srcP += fRowBytes, dstP += dstRowBytes) {
memcpy(dstP, srcP, rowBytes);
}
@@ -665,19 +723,19 @@ void* SkBitmap::getAddr(int x, int y) const {
char* base = (char*)this->getPixels();
if (base) {
base += y * this->rowBytes();
- switch (this->colorType()) {
- case kRGBA_8888_SkColorType:
- case kBGRA_8888_SkColorType:
+ switch (this->config()) {
+ case SkBitmap::kARGB_8888_Config:
base += x << 2;
break;
- case kARGB_4444_SkColorType:
- case kRGB_565_SkColorType:
+ case SkBitmap::kARGB_4444_Config:
+ case SkBitmap::kRGB_565_Config:
base += x << 1;
break;
- case kAlpha_8_SkColorType:
- case kIndex_8_SkColorType:
+ case SkBitmap::kA8_Config:
+ case SkBitmap::kIndex8_Config:
base += x;
break;
+ break;
default:
SkDEBUGFAIL("Can't return addr for config");
base = NULL;
@@ -815,12 +873,8 @@ void SkBitmap::internalErase(const SkIRect& area,
}
#endif
- switch (fInfo.colorType()) {
- case kUnknown_SkColorType:
- case kIndex_8_SkColorType:
- return; // can't erase
- default:
- break;
+ if (kNo_Config == fConfig || kIndex8_Config == fConfig) {
+ return;
}
SkAutoLockPixels alp(*this);
@@ -840,8 +894,8 @@ void SkBitmap::internalErase(const SkIRect& area,
b = SkAlphaMul(b, a);
}
- switch (this->colorType()) {
- case kAlpha_8_SkColorType: {
+ switch (fConfig) {
+ case kA8_Config: {
uint8_t* p = this->getAddr8(area.fLeft, area.fTop);
while (--height >= 0) {
memset(p, a, width);
@@ -849,12 +903,12 @@ void SkBitmap::internalErase(const SkIRect& area,
}
break;
}
- case kARGB_4444_SkColorType:
- case kRGB_565_SkColorType: {
+ case kARGB_4444_Config:
+ case kRGB_565_Config: {
uint16_t* p = this->getAddr16(area.fLeft, area.fTop);;
uint16_t v;
- if (kARGB_4444_SkColorType == this->colorType()) {
+ if (kARGB_4444_Config == fConfig) {
v = pack_8888_to_4444(a, r, g, b);
} else {
v = SkPackRGB16(r >> (8 - SK_R16_BITS),
@@ -867,9 +921,7 @@ void SkBitmap::internalErase(const SkIRect& area,
}
break;
}
- case kPMColor_SkColorType: {
- // what to do about BGRA or RGBA (which ever is != PMColor ?
- // for now we don't support them.
+ case kARGB_8888_Config: {
uint32_t* p = this->getAddr32(area.fLeft, area.fTop);
uint32_t v = SkPackARGB32(a, r, g, b);
@@ -879,8 +931,6 @@ void SkBitmap::internalErase(const SkIRect& area,
}
break;
}
- default:
- return; // no change, so don't call notifyPixelsChanged()
}
this->notifyPixelsChanged();
@@ -996,8 +1046,7 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
if (fPixelRef) {
SkIRect subset;
- subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY,
- fInfo.width(), fInfo.height());
+ subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY, fWidth, fHeight);
if (fPixelRef->readPixels(&tmpSrc, &subset)) {
SkASSERT(tmpSrc.width() == this->width());
SkASSERT(tmpSrc.height() == this->height());
@@ -1111,8 +1160,6 @@ 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;
}
@@ -1123,7 +1170,7 @@ bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const {
SkPixelRef* pixelRef = fPixelRef->deepCopy(dstConfig);
if (pixelRef) {
uint32_t rowBytes;
- if (this->colorType() == dstCT) {
+ if (dstConfig == fConfig) {
// Since there is no subset to pass to deepCopy, and deepCopy
// succeeded, the new pixel ref must be identical.
SkASSERT(fPixelRef->info() == pixelRef->info());
@@ -1134,12 +1181,7 @@ bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const {
// With the new config, an appropriate fRowBytes will be computed by setConfig.
rowBytes = 0;
}
-
- SkImageInfo info = fInfo;
- info.fColorType = dstCT;
- if (!dst->setConfig(info, rowBytes)) {
- return false;
- }
+ dst->setConfig(dstConfig, fWidth, fHeight, rowBytes);
dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref();
return true;
}
@@ -1542,8 +1584,11 @@ enum {
};
void SkBitmap::flatten(SkWriteBuffer& buffer) const {
- fInfo.flatten(buffer);
+ buffer.writeInt(fWidth);
+ buffer.writeInt(fHeight);
buffer.writeInt(fRowBytes);
+ buffer.writeInt(fConfig);
+ buffer.writeInt(fAlphaType);
if (fPixelRef) {
if (fPixelRef->getFactory()) {
@@ -1563,17 +1608,19 @@ void SkBitmap::flatten(SkWriteBuffer& buffer) const {
void SkBitmap::unflatten(SkReadBuffer& buffer) {
this->reset();
- 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));
+ 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));
- bool configIsValid = this->setConfig(info, rowBytes);
- buffer.validate(configIsValid);
+ 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));
int reftype = buffer.readInt();
if (buffer.validate((SERIALIZE_PIXELTYPE_REF_DATA == reftype) ||
@@ -1583,7 +1630,7 @@ void SkBitmap::unflatten(SkReadBuffer& buffer) {
SkIPoint origin;
origin.fX = buffer.readInt();
origin.fY = buffer.readInt();
- size_t offset = origin.fY * rowBytes + origin.fX * info.bytesPerPixel();
+ size_t offset = origin.fY * rowBytes + origin.fX * fBytesPerPixel;
SkPixelRef* pr = buffer.readPixelRef();
if (!buffer.validate((NULL == pr) ||
(pr->getAllocatedSizeInBytes() >= (offset + this->getSafeSize())))) {
@@ -1616,14 +1663,15 @@ SkBitmap::RLEPixels::~RLEPixels() {
#ifdef SK_DEBUG
void SkBitmap::validate() const {
- fInfo.validate();
- SkASSERT(fInfo.validRowBytes(fRowBytes));
+ SkASSERT(fConfig < kConfigCount);
+ SkASSERT(fRowBytes >= (unsigned)ComputeRowBytes((Config)fConfig, fWidth));
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);
@@ -1632,9 +1680,9 @@ void SkBitmap::validate() const {
SkASSERT(fPixelRef->rowBytes() == fRowBytes);
SkASSERT(fPixelRefOrigin.fX >= 0);
SkASSERT(fPixelRefOrigin.fY >= 0);
- SkASSERT(fPixelRef->info().width() >= (int)this->width() + fPixelRefOrigin.fX);
- SkASSERT(fPixelRef->info().fHeight >= (int)this->height() + fPixelRefOrigin.fY);
- SkASSERT(fPixelRef->rowBytes() >= fInfo.minRowBytes());
+ SkASSERT(fPixelRef->info().fWidth >= (int)fWidth + fPixelRefOrigin.fX);
+ SkASSERT(fPixelRef->info().fHeight >= (int)fHeight + fPixelRefOrigin.fY);
+ SkASSERT(fPixelRef->rowBytes() >= fWidth * fBytesPerPixel);
} else {
SkASSERT(NULL == fColorTable);
}
@@ -1680,14 +1728,3 @@ 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
« no previous file with comments | « include/core/SkPathRef.h ('k') | src/gpu/GrClipMaskManager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698