Index: src/core/SkBitmap.cpp |
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp |
index c0d93957aca11292e2f6e52b17e9f7aa92783de7..cb8ac7231b29a9728dcf0d4804c6660c40291a04 100644 |
--- a/src/core/SkBitmap.cpp |
+++ b/src/core/SkBitmap.cpp |
@@ -129,7 +129,7 @@ SkBitmap& SkBitmap::operator=(const SkBitmap& src) { |
void SkBitmap::swap(SkBitmap& other) { |
SkTSwap(fColorTable, other.fColorTable); |
SkTSwap(fPixelRef, other.fPixelRef); |
- SkTSwap(fPixelRefOffset, other.fPixelRefOffset); |
+ SkTSwap(fPixelRefOrigin, other.fPixelRefOrigin); |
SkTSwap(fPixelLockCount, other.fPixelLockCount); |
SkTSwap(fMipMap, other.fMipMap); |
SkTSwap(fPixels, other.fPixels); |
@@ -340,7 +340,9 @@ void SkBitmap::updatePixelsFromRef() const { |
void* p = fPixelRef->pixels(); |
if (NULL != p) { |
- p = (char*)p + fPixelRefOffset; |
+ p = (char*)p |
+ + fPixelRef->rowBytes() * fPixelRefOrigin.fY |
+ + fPixelRefOrigin.fX * fBytesPerPixel; |
} |
fPixels = p; |
SkRefCnt_SafeAssign(fColorTable, fPixelRef->colorTable()); |
@@ -397,13 +399,9 @@ bool SkBitmap::asImageInfo(SkImageInfo* info) const { |
return true; |
} |
-SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, size_t offset) { |
- // do this first, we that we never have a non-zero offset with a null ref |
- if (NULL == pr) { |
- offset = 0; |
- } |
+SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, int dx, int dy) { |
#ifdef SK_DEBUG |
- else { |
+ if (pr) { |
SkImageInfo info; |
if (this->asImageInfo(&info)) { |
const SkImageInfo& prInfo = pr->info(); |
@@ -428,7 +426,16 @@ SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, size_t offset) { |
} |
#endif |
- if (fPixelRef != pr || fPixelRefOffset != offset) { |
+ if (pr) { |
+ const SkImageInfo& info = pr->info(); |
+ fPixelRefOrigin.set(SkPin32(dx, 0, info.fWidth), |
+ SkPin32(dy, 0, info.fHeight)); |
+ } else { |
+ // ignore dx,dy if there is no pixelref |
+ fPixelRefOrigin.setZero(); |
+ } |
+ |
+ if (fPixelRef != pr) { |
if (fPixelRef != pr) { |
this->freePixels(); |
SkASSERT(NULL == fPixelRef); |
@@ -436,7 +443,6 @@ SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, size_t offset) { |
SkSafeRef(pr); |
fPixelRef = pr; |
} |
- fPixelRefOffset = offset; |
this->updatePixelsFromRef(); |
} |
@@ -468,19 +474,19 @@ bool SkBitmap::lockPixelsAreWritable() const { |
void SkBitmap::setPixels(void* p, SkColorTable* ctable) { |
if (NULL == p) { |
- this->setPixelRef(NULL, 0); |
+ this->setPixelRef(NULL); |
return; |
} |
SkImageInfo info; |
if (!this->asImageInfo(&info)) { |
- this->setPixelRef(NULL, 0); |
+ this->setPixelRef(NULL); |
return; |
} |
SkPixelRef* pr = SkMallocPixelRef::NewDirect(info, p, fRowBytes, ctable); |
if (NULL == pr) { |
- this->setPixelRef(NULL, 0); |
+ this->setPixelRef(NULL); |
return; |
} |
@@ -515,7 +521,7 @@ void SkBitmap::freePixels() { |
} |
fPixelRef->unref(); |
fPixelRef = NULL; |
- fPixelRefOffset = 0; |
+ fPixelRefOrigin.setZero(); |
} |
fPixelLockCount = 0; |
fPixels = NULL; |
@@ -562,7 +568,7 @@ bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst, |
return false; |
} |
- dst->setPixelRef(pr, 0)->unref(); |
+ dst->setPixelRef(pr)->unref(); |
// since we're already allocated, we lockPixels right away |
dst->lockPixels(); |
return true; |
@@ -887,84 +893,6 @@ void SkBitmap::eraseArea(const SkIRect& rect, SkColor c) const { |
////////////////////////////////////////////////////////////////////////////////////// |
////////////////////////////////////////////////////////////////////////////////////// |
-#define SUB_OFFSET_FAILURE ((size_t)-1) |
- |
-/** |
- * Based on the Config and rowBytes() of bm, return the offset into an SkPixelRef of the pixel at |
- * (x, y). |
- * Note that the SkPixelRef does not need to be set yet. deepCopyTo takes advantage of this fact. |
- * Also note that (x, y) may be outside the range of (0 - width(), 0 - height()), so long as it is |
- * within the bounds of the SkPixelRef being used. |
- */ |
-static size_t get_sub_offset(const SkBitmap& bm, int x, int y) { |
- switch (bm.config()) { |
- case SkBitmap::kA8_Config: |
- case SkBitmap:: kIndex8_Config: |
- // x is fine as is for the calculation |
- break; |
- |
- case SkBitmap::kRGB_565_Config: |
- case SkBitmap::kARGB_4444_Config: |
- x <<= 1; |
- break; |
- |
- case SkBitmap::kARGB_8888_Config: |
- x <<= 2; |
- break; |
- |
- case SkBitmap::kNo_Config: |
- default: |
- return SUB_OFFSET_FAILURE; |
- } |
- return y * bm.rowBytes() + x; |
-} |
- |
-/** |
- * Using the pixelRefOffset(), rowBytes(), and Config of bm, determine the (x, y) coordinate of the |
- * upper left corner of bm relative to its SkPixelRef. |
- * x and y must be non-NULL. |
- */ |
-bool get_upper_left_from_offset(SkBitmap::Config config, size_t offset, size_t rowBytes, |
- int32_t* x, int32_t* y); |
-bool get_upper_left_from_offset(SkBitmap::Config config, size_t offset, size_t rowBytes, |
- int32_t* x, int32_t* y) { |
- SkASSERT(x != NULL && y != NULL); |
- if (0 == offset) { |
- *x = *y = 0; |
- return true; |
- } |
- // Use integer division to find the correct y position. |
- // The remainder will be the x position, after we reverse get_sub_offset. |
- SkTDivMod(offset, rowBytes, y, x); |
- switch (config) { |
- case SkBitmap::kA8_Config: |
- // Fall through. |
- case SkBitmap::kIndex8_Config: |
- // x is unmodified |
- break; |
- |
- case SkBitmap::kRGB_565_Config: |
- // Fall through. |
- case SkBitmap::kARGB_4444_Config: |
- *x >>= 1; |
- break; |
- |
- case SkBitmap::kARGB_8888_Config: |
- *x >>= 2; |
- break; |
- |
- case SkBitmap::kNo_Config: |
- // Fall through. |
- default: |
- return false; |
- } |
- return true; |
-} |
- |
-static bool get_upper_left_from_offset(const SkBitmap& bm, int32_t* x, int32_t* y) { |
- return get_upper_left_from_offset(bm.config(), bm.pixelRefOffset(), bm.rowBytes(), x, y); |
-} |
- |
bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const { |
SkDEBUGCODE(this->validate();) |
@@ -998,19 +926,17 @@ bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const { |
SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width())); |
SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height())); |
- size_t offset = get_sub_offset(*this, r.fLeft, r.fTop); |
- if (SUB_OFFSET_FAILURE == offset) { |
- return false; // config not supported |
- } |
- |
SkBitmap dst; |
dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes(), |
this->alphaType()); |
dst.setIsVolatile(this->isVolatile()); |
if (fPixelRef) { |
+ SkIPoint origin = fPixelRefOrigin; |
+ origin.fX += r.fLeft; |
+ origin.fY += r.fTop; |
// share the pixelref with a custom offset |
- dst.setPixelRef(fPixelRef, fPixelRefOffset + offset); |
+ dst.setPixelRef(fPixelRef, origin); |
} |
SkDEBUGCODE(dst.validate();) |
@@ -1059,26 +985,23 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const { |
if (fPixelRef) { |
SkIRect subset; |
- if (get_upper_left_from_offset(*this, &subset.fLeft, &subset.fTop)) { |
- subset.fRight = subset.fLeft + fWidth; |
- subset.fBottom = subset.fTop + fHeight; |
- if (fPixelRef->readPixels(&tmpSrc, &subset)) { |
- SkASSERT(tmpSrc.width() == this->width()); |
- SkASSERT(tmpSrc.height() == this->height()); |
- |
- // did we get lucky and we can just return tmpSrc? |
- if (tmpSrc.config() == dstConfig && NULL == alloc) { |
- dst->swap(tmpSrc); |
- if (dst->pixelRef() && this->config() == dstConfig) { |
- // TODO(scroggo): fix issue 1742 |
- dst->pixelRef()->cloneGenID(*fPixelRef); |
- } |
- return true; |
+ subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY, fWidth, fHeight); |
+ if (fPixelRef->readPixels(&tmpSrc, &subset)) { |
+ SkASSERT(tmpSrc.width() == this->width()); |
+ SkASSERT(tmpSrc.height() == this->height()); |
+ |
+ // did we get lucky and we can just return tmpSrc? |
+ if (tmpSrc.config() == dstConfig && NULL == alloc) { |
+ dst->swap(tmpSrc); |
+ if (dst->pixelRef() && this->config() == dstConfig) { |
+ // TODO(scroggo): fix issue 1742 |
+ dst->pixelRef()->cloneGenID(*fPixelRef); |
} |
- |
- // fall through to the raster case |
- src = &tmpSrc; |
+ return true; |
} |
+ |
+ // fall through to the raster case |
+ src = &tmpSrc; |
} |
} |
@@ -1176,24 +1099,7 @@ bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const { |
rowBytes = 0; |
} |
dst->setConfig(dstConfig, fWidth, fHeight, rowBytes); |
- |
- size_t pixelRefOffset; |
- if (0 == fPixelRefOffset || dstConfig == fConfig) { |
- // Use the same offset as the original. |
- pixelRefOffset = fPixelRefOffset; |
- } else { |
- // Find the correct offset in the new config. This needs to be done after calling |
- // setConfig so dst's fConfig and fRowBytes have been set properly. |
- int32_t x, y; |
- if (!get_upper_left_from_offset(*this, &x, &y)) { |
- return false; |
- } |
- pixelRefOffset = get_sub_offset(*dst, x, y); |
- if (SUB_OFFSET_FAILURE == pixelRefOffset) { |
- return false; |
- } |
- } |
- dst->setPixelRef(pixelRef, pixelRefOffset)->unref(); |
+ dst->setPixelRef(pixelRef, fPixelRefOrigin)->unref(); |
return true; |
} |
} |
@@ -1604,7 +1510,8 @@ void SkBitmap::flatten(SkFlattenableWriteBuffer& buffer) const { |
if (fPixelRef) { |
if (fPixelRef->getFactory()) { |
buffer.writeInt(SERIALIZE_PIXELTYPE_REF_DATA); |
- buffer.writeUInt(SkToU32(fPixelRefOffset)); |
+ buffer.writeInt(fPixelRefOrigin.fX); |
+ buffer.writeInt(fPixelRefOrigin.fY); |
buffer.writeFlattenable(fPixelRef); |
return; |
} |
@@ -1637,13 +1544,16 @@ void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) { |
(SERIALIZE_PIXELTYPE_NONE == reftype))) { |
switch (reftype) { |
case SERIALIZE_PIXELTYPE_REF_DATA: { |
- size_t offset = buffer.readUInt(); |
+ SkIPoint origin; |
+ origin.fX = buffer.readInt(); |
+ origin.fY = buffer.readInt(); |
+ size_t offset = origin.fY * rowBytes + origin.fX * fBytesPerPixel; |
SkPixelRef* pr = buffer.readPixelRef(); |
if (!buffer.validate((NULL == pr) || |
(pr->getAllocatedSizeInBytes() >= (offset + this->getSafeSize())))) { |
- offset = 0; |
+ origin.setZero(); |
} |
- SkSafeUnref(this->setPixelRef(pr, offset)); |
+ SkSafeUnref(this->setPixelRef(pr, origin)); |
break; |
} |
case SERIALIZE_PIXELTYPE_NONE: |