Revert "SkBitmap now really stores SkImageInfo -- config is just a ruse"

BUG=skia:

Review URL: https://codereview.chromium.org/147733004

git-svn-id: http://skia.googlecode.com/svn/trunk@13395 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
mike@reedtribe.org 2014-02-11 03:24:02 +00:00
parent b53317c6fa
commit 1195a28892
12 changed files with 269 additions and 256 deletions

View File

@ -79,42 +79,10 @@ 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 fInfo.isEmpty(); }
bool empty() const { return 0 == fWidth || 0 == fHeight; }
/** Return true iff the bitmap has no pixelref. Note: this can return true even if the
* dimensions of the bitmap are > 0 (see empty()).
@ -127,14 +95,41 @@ public:
bool drawsNothing() const { return this->empty() || this->isNull(); }
/** Return the config for the bitmap. */
Config config() const;
Config config() const { return (Config)fConfig; }
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
@ -154,19 +149,19 @@ public:
Note this truncates the result to 32bits. Call getSize64() to detect
if the real size exceeds 32bits.
*/
size_t getSize() const { return fInfo.fHeight * fRowBytes; }
size_t getSize() const { return 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 { return fInfo.getSafeSize(fRowBytes); }
size_t getSafeSize() const ;
/**
* Return the full size of the bitmap, in bytes.
*/
int64_t computeSize64() const {
return sk_64_mul(fInfo.fHeight, fRowBytes);
return sk_64_mul(fHeight, fRowBytes);
}
/**
@ -175,7 +170,7 @@ public:
* than computeSize64() if there is any rowbytes padding beyond the width.
*/
int64_t computeSafeSize64() const {
return fInfo.getSafeSize64(fRowBytes);
return ComputeSafeSize64((Config)fConfig, fWidth, fHeight, fRowBytes);
}
/** Returns true if this bitmap is marked as immutable, meaning that the
@ -309,18 +304,11 @@ public:
void* context);
/**
* DEPRECATED: call info().
* 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.
*/
bool asImageInfo(SkImageInfo* info) const {
// compatibility: return false for kUnknown
if (kUnknown_SkColorType == this->colorType()) {
return false;
}
if (info) {
*info = this->info();
}
return true;
}
bool asImageInfo(SkImageInfo* info) const;
/** Use this to assign a new pixel address for an existing bitmap. This
will automatically release any pixelref previously installed. Only call
@ -462,8 +450,8 @@ public:
*/
GrTexture* getTexture() const;
/** Return the bitmap's colortable, if it uses one (i.e. colorType is
Index_8) and the pixels are locked.
/** Return the bitmap's colortable, if it uses one (i.e. fConfig is
kIndex8_Config) and the pixels are locked.
Otherwise returns NULL. Does not affect the colortable's
reference count.
*/
@ -754,11 +742,13 @@ 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;
@ -870,29 +860,29 @@ private:
inline uint32_t* SkBitmap::getAddr32(int x, int y) const {
SkASSERT(fPixels);
SkASSERT(this->config() == kARGB_8888_Config);
SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height());
SkASSERT(fConfig == kARGB_8888_Config);
SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
return (uint32_t*)((char*)fPixels + y * fRowBytes + (x << 2));
}
inline uint16_t* SkBitmap::getAddr16(int x, int y) const {
SkASSERT(fPixels);
SkASSERT(this->config() == kRGB_565_Config || this->config() == kARGB_4444_Config);
SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height());
SkASSERT(fConfig == kRGB_565_Config || fConfig == kARGB_4444_Config);
SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
return (uint16_t*)((char*)fPixels + y * fRowBytes + (x << 1));
}
inline uint8_t* SkBitmap::getAddr8(int x, int y) const {
SkASSERT(fPixels);
SkASSERT(this->config() == kA8_Config || this->config() == kIndex8_Config);
SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height());
SkASSERT(fConfig == kA8_Config || fConfig == kIndex8_Config);
SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
return (uint8_t*)fPixels + y * fRowBytes + x;
}
inline SkPMColor SkBitmap::getIndex8Color(int x, int y) const {
SkASSERT(fPixels);
SkASSERT(this->config() == kIndex8_Config);
SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height());
SkASSERT(fConfig == kIndex8_Config);
SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
SkASSERT(fColorTable);
return (*fColorTable)[*((const uint8_t*)fPixels + y * fRowBytes + x)];
}

View File

@ -8,7 +8,7 @@
#ifndef SkImageInfo_DEFINED
#define SkImageInfo_DEFINED
#include "SkMath.h"
#include "SkTypes.h"
#include "SkSize.h"
class SkWriteBuffer;
@ -59,17 +59,12 @@ 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,
@ -90,7 +85,6 @@ enum SkColorType {
static int SkColorTypeBytesPerPixel(SkColorType ct) {
static const uint8_t gSize[] = {
0, // Unknown
1, // Alpha_8
2, // RGB_565
2, // ARGB_4444
@ -105,14 +99,6 @@ 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;
}
///////////////////////////////////////////////////////////////////////////////
/**
@ -173,29 +159,16 @@ 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 (size_t)this->minRowBytes64();
return fWidth * this->bytesPerPixel();
}
bool operator==(const SkImageInfo& other) const {
@ -208,23 +181,12 @@ struct SkImageInfo {
void unflatten(SkReadBuffer&);
void flatten(SkWriteBuffer&) const;
int64_t getSafeSize64(size_t rowBytes) const {
size_t getSafeSize(size_t rowBytes) const {
if (0 == fHeight) {
return 0;
}
return sk_64_mul(fHeight - 1, rowBytes) + fWidth * this->bytesPerPixel();
return (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

View File

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

View File

@ -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);
bool SkBitmap::setConfig(Config config, int width, int height, size_t rowBytes,
SkAlphaType alphaType) {
if ((width | height) < 0) {
goto BAD_CONFIG;
}
if ((int64_t)rowBytes != (int32_t)rowBytes) {
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 (info.width() < 0 || info.height() < 0) {
return reset_return_false(this);
}
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

View File

@ -70,7 +70,7 @@ static bool path_needs_SW_renderer(GrContext* context,
SkPath::FillType fillType = SkPath::ConvertToNonInverseFillType(origPath.getFillType());
// the 'false' parameter disallows use of the SW path renderer
GrPathRenderer::AutoClearPath acp(context->getPathRenderer(origPath, stroke, gpu,
GrPathRenderer::AutoClearPath acp(context->getPathRenderer(origPath, stroke, gpu,
false, type, fillType));
return NULL == acp.renderer();
}
@ -310,7 +310,7 @@ void setup_boolean_blendcoeffs(GrDrawState* drawState, SkRegion::Op op) {
////////////////////////////////////////////////////////////////////////////////
bool GrClipMaskManager::drawFilledPath(GrTexture* target,
GrPathRenderer* pathRenderer,
GrPathRenderer* pathRenderer,
bool isAA) {
GrDrawState* drawState = fGpu->drawState();
@ -349,7 +349,7 @@ bool GrClipMaskManager::drawElement(GrTexture* target,
GrPathRendererChain::kColor_DrawType;
SkPath::FillType fillType = element->getPath().getFillType();
GrPathRenderer::AutoClearPath acp(this->getContext()->getPathRenderer(
element->getPath(),
element->getPath(),
stroke, fGpu, false, type,
SkPath::ConvertToNonInverseFillType(fillType)));
if (NULL == acp.renderer()) {
@ -381,9 +381,9 @@ bool GrClipMaskManager::canStencilAndDrawElement(GrTexture* target,
GrPathRendererChain::kStencilAndColorAntiAlias_DrawType :
GrPathRendererChain::kStencilAndColor_DrawType;
SkPath::FillType fillType = element->getPath().getFillType();
acp->set(this->getContext()->getPathRenderer(element->getPath(),
acp->set(this->getContext()->getPathRenderer(element->getPath(),
stroke, fGpu, false, type,
SkPath::ConvertToNonInverseFillType(fillType)));
SkPath::ConvertToNonInverseFillType(fillType)));
return NULL != acp->renderer();
}
default:

View File

@ -141,7 +141,7 @@ private:
// Determines whether it is possible to draw the element to both the stencil buffer and the
// alpha mask simultaneously. If so and the element is a path a compatible path renderer is
// also returned.
bool canStencilAndDrawElement(GrTexture* target, const SkClipStack::Element*,
bool canStencilAndDrawElement(GrTexture* target, const SkClipStack::Element*,
GrPathRenderer::AutoClearPath* pr);
void mergeMask(GrTexture* dstMask,

View File

@ -1155,7 +1155,7 @@ void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath&
SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke);
// Try a 1st time without stroking the path and without allowing the SW renderer
GrPathRenderer::AutoClearPath acp(this->getPathRenderer(*pathPtr, *stroke,
GrPathRenderer::AutoClearPath acp(this->getPathRenderer(*pathPtr, *stroke,
target, false, type,
pathPtr->getFillType()));

View File

@ -100,8 +100,8 @@ public:
}
/**
* Returns true if this path renderer is able to render the current path. Returning false
* allows the caller to fallback to another path renderer This function is called when
* Returns true if this path renderer is able to render the current path. Returning false
* allows the caller to fallback to another path renderer This function is called when
* searching for a path renderer capable of rendering a path.
*
* @param stroke The stroke information (width, join, cap)
@ -114,8 +114,8 @@ public:
const GrDrawTarget* target,
bool antiAlias) const = 0;
/**
* Draws the current path into the draw target. If getStencilSupport() would return
* kNoRestriction then the subclass must respect the stencil settings of the
* Draws the current path into the draw target. If getStencilSupport() would return
* kNoRestriction then the subclass must respect the stencil settings of the
* target's draw state.
*
* @param stroke the stroke information (width, join, cap)
@ -134,7 +134,7 @@ public:
/**
* Draws the current path to the stencil buffer. Assume the writable stencil bits are already
* initialized to zero. The pixels inside the path will have non-zero stencil values
* initialized to zero. The pixels inside the path will have non-zero stencil values
* afterwards.
*
* @param stroke the stroke information (width, join, cap)

View File

@ -37,19 +37,35 @@ SkBitmap::Config SkImageInfoToBitmapConfig(const SkImageInfo& info) {
return SkColorTypeToBitmapConfig(info.fColorType);
}
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];
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;
}
SkImage* SkNewImageFromBitmap(const SkBitmap& bm, bool canSharePixelRef) {
SkImageInfo info;
if (!bm.asImageInfo(&info)) {

View File

@ -15,7 +15,7 @@ class SkPicture;
extern SkBitmap::Config SkImageInfoToBitmapConfig(const SkImageInfo&);
extern SkBitmap::Config SkColorTypeToBitmapConfig(SkColorType);
extern SkColorType SkBitmapConfigToColorType(SkBitmap::Config);
extern bool SkBitmapConfigToColorType(SkBitmap::Config, SkColorType* ctOut);
// Call this if you explicitly want to use/share this pixelRef in the image
extern SkImage* SkNewImageFromPixelRef(const SkImageInfo&, SkPixelRef*,

View File

@ -275,6 +275,11 @@ 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,

View File

@ -333,7 +333,10 @@ static SkPixelRef* install_pixel_ref(SkBitmap* bitmap,
SkASSERT(stream != NULL);
SkASSERT(stream->rewind());
SkASSERT(stream->unique());
SkColorType colorType = bitmap->colorType();
SkColorType colorType;
if (!SkBitmapConfigToColorType(bitmap->config(), &colorType)) {
return NULL;
}
SkDecodingImageGenerator::Options opts(sampleSize, ditherImage, colorType);
SkAutoTDelete<SkImageGenerator> gen(
SkDecodingImageGenerator::Create(stream, opts));