diff options
author | Lucas Crowthers <lucasc@codeaurora.org> | 2012-12-03 17:21:30 -0500 |
---|---|---|
committer | Steve Kondik <shade@chemlab.org> | 2013-03-04 15:46:32 -0800 |
commit | 705eb622415dc3db0d1740ff29aa0fbf4e8aafa5 (patch) | |
tree | b2c036b96b9eb54bc9d35aa46e0cbf893afe86f0 /src | |
parent | 425325c48d72df437bd734ba0820403204fa79ae (diff) | |
download | external_skia-705eb622415dc3db0d1740ff29aa0fbf4e8aafa5.zip external_skia-705eb622415dc3db0d1740ff29aa0fbf4e8aafa5.tar.gz external_skia-705eb622415dc3db0d1740ff29aa0fbf4e8aafa5.tar.bz2 |
Skia: Introduce caching of unscaled Bitmaps.
This allows skia to choose whether to use the prescaled bitmap or the
unscaled bitmap depending on which would be optimal in the current
situation. This commit also introduces two functions necessary for
properly resizing Rects when using the non-pre-scaled bitmaps.
CRs-fixed: 451681
Change-Id: I36779d8a680a3ced7c28da492e879de02c7e87a5
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkBitmap.cpp | 21 | ||||
-rw-r--r-- | src/core/SkCanvas.cpp | 67 |
2 files changed, 88 insertions, 0 deletions
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp index 0b98513..84bb9b2 100644 --- a/src/core/SkBitmap.cpp +++ b/src/core/SkBitmap.cpp @@ -116,6 +116,7 @@ SkBitmap& SkBitmap::operator=(const SkBitmap& src) { } else { // we have a pixelref, so pixels/ctable reflect it // ignore the values from the memcpy fPixels = NULL; + fUnscaledBitmap = NULL; fColorTable = NULL; // Note that what to for genID is somewhat arbitrary. We have no // way to track changes to raw pixels across multiple SkBitmaps. @@ -137,6 +138,7 @@ void SkBitmap::swap(SkBitmap& other) { SkTSwap(fPixelLockCount, other.fPixelLockCount); SkTSwap(fMipMap, other.fMipMap); SkTSwap(fPixels, other.fPixels); + SkTSwap(fUnscaledBitmap, other.fUnscaledBitmap); SkTSwap(fRawPixelGenerationID, other.fRawPixelGenerationID); SkTSwap(fRowBytes, other.fRowBytes); SkTSwap(fWidth, other.fWidth); @@ -291,10 +293,18 @@ void SkBitmap::updatePixelsFromRef() const { p = (char*)p + fPixelRefOffset; } fPixels = p; + if (NULL != fUnscaledBitmap) { + delete fUnscaledBitmap; + fUnscaledBitmap = NULL; + } SkRefCnt_SafeAssign(fColorTable, fPixelRef->colorTable()); } else { SkASSERT(0 == fPixelLockCount); fPixels = NULL; + if (NULL != fUnscaledBitmap) { + delete fUnscaledBitmap; + fUnscaledBitmap = NULL; + } if (fColorTable) { fColorTable->unref(); fColorTable = NULL; @@ -377,6 +387,8 @@ void SkBitmap::freePixels() { fColorTable = NULL; } + freeUnscaledBitmap(); + if (NULL != fPixelRef) { if (fPixelLockCount > 0) { fPixelRef->unlockPixels(); @@ -389,6 +401,13 @@ void SkBitmap::freePixels() { fPixels = NULL; } +void SkBitmap::freeUnscaledBitmap() { + if (NULL != fUnscaledBitmap) { + delete fUnscaledBitmap; + fUnscaledBitmap = NULL; + } +} + void SkBitmap::freeMipMap() { if (fMipMap) { fMipMap->unref(); @@ -888,6 +907,7 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const { // did we get lucky and we can just return tmpSrc? if (tmpSrc.config() == dstConfig && NULL == alloc) { dst->swap(tmpSrc); + dst->fUnscaledBitmap = NULL; return true; } @@ -950,6 +970,7 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const { tmpDst.setIsOpaque(src->isOpaque()); dst->swap(tmpDst); + dst->fUnscaledBitmap = NULL; return true; } diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 0e26728..7ee6b94 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -1490,12 +1490,79 @@ void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkIRect* src this->internalDrawBitmap(*bitmapPtr, src, matrix, paint); } +// this one is non-virtual, so it can be called safely by other canvas apis +void SkCanvas::internalDrawBitmapScalarRect(const SkBitmap& bitmap, const SkRect* src, + const SkRect& dst, const SkPaint* paint) { + SkIRect srcRounded, *srcRoundedPtr = NULL; + + if (bitmap.width() == 0 || bitmap.height() == 0 || dst.isEmpty()) { + return; + } + + if (NULL != src) { + srcRoundedPtr = &srcRounded; + src->roundOut(srcRoundedPtr); + } + + // do this now, to avoid the cost of calling extract for RLE bitmaps + if (NULL == paint || paint->canComputeFastBounds()) { + SkRect storage; + const SkRect* bounds = &dst; + if (paint) { + bounds = &paint->computeFastBounds(dst, &storage); + } + if (this->quickReject(*bounds, paint2EdgeType(paint))) { + return; + } + } + + const SkBitmap* bitmapPtr = &bitmap; + + SkMatrix matrix; + SkRect tmpSrc; + if (src) { + tmpSrc = *src; + // if the extract process clipped off the top or left of the + // original, we adjust for that here to get the position right. + if (tmpSrc.fLeft > 0) { + tmpSrc.fRight -= tmpSrc.fLeft; + tmpSrc.fLeft = 0; + } + if (tmpSrc.fTop > 0) { + tmpSrc.fBottom -= tmpSrc.fTop; + tmpSrc.fTop = 0; + } + } else { + tmpSrc.set(0, 0, SkIntToScalar(bitmap.width()), + SkIntToScalar(bitmap.height())); + } + matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit); + + // ensure that src is "valid" before we pass it to our internal routines + // and to SkDevice. i.e. sure it is contained inside the original bitmap. + SkIRect tmpISrc; + if (srcRoundedPtr) { + tmpISrc.set(0, 0, bitmap.width(), bitmap.height()); + if (!tmpISrc.intersect(*srcRoundedPtr)) { + return; + } + srcRoundedPtr = &tmpISrc; + } + this->internalDrawBitmap(*bitmapPtr, srcRoundedPtr, matrix, paint); +} + void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, const SkRect& dst, const SkPaint* paint) { SkDEBUGCODE(bitmap.validate();) this->internalDrawBitmapRect(bitmap, src, dst, paint); } +void SkCanvas::drawBitmapScalarRect(const SkBitmap& bitmap, const SkRect* src, + const SkRect& dst, const SkPaint* paint) { + SkDEBUGCODE(bitmap.validate();) + this->internalDrawBitmapScalarRect(bitmap, src, dst, paint); +} + void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) { SkDEBUGCODE(bitmap.validate();) |