diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkCanvas.cpp | 43 | ||||
-rw-r--r-- | src/core/SkDevice.cpp | 75 |
2 files changed, 85 insertions, 33 deletions
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 9ef9c25e91..1bb3a456e9 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -1593,41 +1593,18 @@ void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, } } - SkMatrix matrix; - // Compute matrix from the two rectangles - { - 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); + SkLazyPaint lazy; + if (NULL == paint) { + paint = lazy.init(); } - - // 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 isrcStorage; - SkIRect* isrcPtr = NULL; - if (src) { - src->roundOut(&isrcStorage); - if (!isrcStorage.intersect(0, 0, bitmap.width(), bitmap.height())) { - return; - } - isrcPtr = &isrcStorage; + + LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type) + + while (iter.next()) { + iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint()); } - this->internalDrawBitmap(bitmap, isrcPtr, matrix, paint); + + LOOPER_END } void SkCanvas::drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp index 10d89d591f..fb126dbb34 100644 --- a/src/core/SkDevice.cpp +++ b/src/core/SkDevice.cpp @@ -11,6 +11,7 @@ #include "SkMetaData.h" #include "SkRasterClip.h" #include "SkRect.h" +#include "SkShader.h" SK_DEFINE_INST_COUNT(SkDevice) @@ -348,6 +349,80 @@ void SkDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap, draw.drawBitmap(*bitmapPtr, matrix, paint); } +void SkDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, + const SkRect* src, const SkRect& dst, + const SkPaint& paint) { + SkMatrix matrix; + SkRect bitmapBounds, tmpSrc, tmpDst; + SkBitmap tmpBitmap; + + bitmapBounds.set(0, 0, + SkIntToScalar(bitmap.width()), + SkIntToScalar(bitmap.height())); + + // Compute matrix from the two rectangles + if (src) { + tmpSrc = *src; + } else { + tmpSrc = bitmapBounds; + } + matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit); + + const SkRect* dstPtr = &dst; + const SkBitmap* bitmapPtr = &bitmap; + + // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if + // needed (if the src was clipped). No check needed if src==null. + if (src) { + if (!bitmapBounds.contains(*src)) { + if (!tmpSrc.intersect(bitmapBounds)) { + return; // nothing to draw + } + // recompute dst, based on the smaller tmpSrc + matrix.mapRect(&tmpDst, tmpSrc); + dstPtr = &tmpDst; + } + + // since we may need to clamp to the borders of the src rect within + // the bitmap, we extract a subset. + SkIRect srcIR; + tmpSrc.roundOut(&srcIR); + if (!bitmap.extractSubset(&tmpBitmap, srcIR)) { + return; + } + bitmapPtr = &tmpBitmap; + + // Since we did an extract, we need to adjust the matrix accordingly + SkScalar dx = 0, dy = 0; + if (srcIR.fLeft > 0) { + dx = SkIntToScalar(srcIR.fLeft); + } + if (srcIR.fTop > 0) { + dy = SkIntToScalar(srcIR.fTop); + } + if (dx || dy) { + matrix.preTranslate(dx, dy); + } + } + + // construct a shader, so we can call drawRect with the dst + SkShader* s = SkShader::CreateBitmapShader(*bitmapPtr, + SkShader::kClamp_TileMode, + SkShader::kClamp_TileMode); + if (NULL == s) { + return; + } + s->setLocalMatrix(matrix); + + SkPaint paintWithShader(paint); + paintWithShader.setStyle(SkPaint::kFill_Style); + paintWithShader.setShader(s)->unref(); + + // Call ourself, in case the subclass wanted to share this setup code + // but handle the drawRect code themselves. + this->drawRect(draw, *dstPtr, paintWithShader); +} + void SkDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap, int x, int y, const SkPaint& paint) { draw.drawSprite(bitmap, x, y, paint); |