diff --git a/gm/bitmaprect.cpp b/gm/bitmaprect.cpp index 53a855e778..df30106c7c 100644 --- a/gm/bitmaprect.cpp +++ b/gm/bitmaprect.cpp @@ -275,6 +275,7 @@ protected: private: typedef skiagm::GM INHERITED; }; +DEF_GM( return new BitmapRectRounding; ) ////////////////////////////////////////////////////////////////////////////// @@ -298,4 +299,3 @@ static skiagm::GMRegistry reg3(MyFactory3); static skiagm::GMRegistry reg4(MyFactory4); #endif -DEF_GM( return new BitmapRectRounding; ) diff --git a/include/core/SkDraw.h b/include/core/SkDraw.h index 4b8d02b0ae..2bb9c89627 100644 --- a/include/core/SkDraw.h +++ b/include/core/SkDraw.h @@ -34,7 +34,11 @@ public: void drawPaint(const SkPaint&) const; void drawPoints(SkCanvas::PointMode, size_t count, const SkPoint[], const SkPaint&, bool forceUseDevice = false) const; - void drawRect(const SkRect&, const SkPaint&) const; + void drawRect(const SkRect& prePaintRect, const SkPaint&, const SkMatrix* paintMatrix, + const SkRect* postPaintRect) const; + void drawRect(const SkRect& rect, const SkPaint& paint) const { + this->drawRect(rect, paint, NULL, NULL); + } void drawRRect(const SkRRect&, const SkPaint&) const; /** * To save on mallocs, we allow a flag that tells us that srcPath is @@ -55,7 +59,9 @@ public: this->drawPath(path, paint, NULL, false, false, customBlitter); } - void drawBitmap(const SkBitmap&, const SkMatrix&, const SkPaint&) const; + /* If dstOrNull is null, computes a dst by mapping the bitmap's bounds through the matrix. */ + void drawBitmap(const SkBitmap&, const SkMatrix&, const SkRect* dstOrNull, + const SkPaint&) const; void drawSprite(const SkBitmap&, int x, int y, const SkPaint&) const; void drawText(const char text[], size_t byteLength, SkScalar x, SkScalar y, const SkPaint& paint) const; diff --git a/include/core/SkRect.h b/include/core/SkRect.h index 0038c7c2fa..8e4d669c48 100644 --- a/include/core/SkRect.h +++ b/include/core/SkRect.h @@ -395,6 +395,12 @@ struct SK_API SkRect { return r; } + static SkRect SK_WARN_UNUSED_RESULT MakeIWH(int w, int h) { + SkRect r; + r.set(0, 0, SkIntToScalar(w), SkIntToScalar(h)); + return r; + } + static SkRect SK_WARN_UNUSED_RESULT MakeSize(const SkSize& size) { SkRect r; r.set(0, 0, size.width(), size.height()); diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp index 020f1da13b..1f17e6fac1 100644 --- a/src/core/SkBitmapDevice.cpp +++ b/src/core/SkBitmapDevice.cpp @@ -218,7 +218,7 @@ void SkBitmapDevice::drawPath(const SkDraw& draw, const SkPath& path, void SkBitmapDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap, const SkMatrix& matrix, const SkPaint& paint) { - draw.drawBitmap(bitmap, matrix, paint); + draw.drawBitmap(bitmap, matrix, NULL, paint); } void SkBitmapDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, @@ -291,7 +291,7 @@ void SkBitmapDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, // We can go faster by just calling drawBitmap, which will concat the // matrix with the CTM, and try to call drawSprite if it can. If not, // it will make a shader and call drawRect, as we do below. - this->drawBitmap(draw, *bitmapPtr, matrix, paint); + draw.drawBitmap(*bitmapPtr, matrix, dstPtr, paint); return; } diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp index 61ab35df45..0a6365c335 100644 --- a/src/core/SkDraw.cpp +++ b/src/core/SkDraw.cpp @@ -786,7 +786,8 @@ static SkPoint* rect_points(SkRect& r) { return SkTCast(&r); } -void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const { +void SkDraw::drawRect(const SkRect& prePaintRect, const SkPaint& paint, + const SkMatrix* paintMatrix, const SkRect* postPaintRect) const { SkDEBUGCODE(this->validate();) // nothing to draw @@ -794,22 +795,40 @@ void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const { return; } + const SkMatrix* matrix; + SkMatrix combinedMatrixStorage; + if (paintMatrix) { + SkASSERT(postPaintRect); + combinedMatrixStorage.setConcat(*fMatrix, *paintMatrix); + matrix = &combinedMatrixStorage; + } else { + SkASSERT(!postPaintRect); + matrix = fMatrix; + } + SkPoint strokeSize; RectType rtype = ComputeRectType(paint, *fMatrix, &strokeSize); if (kPath_RectType == rtype) { + SkDraw draw(*this); + if (paintMatrix) { + draw.fMatrix = matrix; + } SkPath tmp; - tmp.addRect(rect); + tmp.addRect(prePaintRect); tmp.setFillType(SkPath::kWinding_FillType); - this->drawPath(tmp, paint, NULL, true); + draw.drawPath(tmp, paint, NULL, true); return; } - const SkMatrix& matrix = *fMatrix; - SkRect devRect; - + SkRect devRect; + if (paintMatrix) { + // skip the paintMatrix when transforming the rect by the CTM + fMatrix->mapPoints(rect_points(devRect), rect_points(*postPaintRect), 2); + } else { + fMatrix->mapPoints(rect_points(devRect), rect_points(prePaintRect), 2); + } // transform rect into devRect - matrix.mapPoints(rect_points(devRect), rect_points(rect), 2); devRect.sort(); // look for the quick exit, before we build a blitter @@ -832,10 +851,9 @@ void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const { SkRect localDevRect; looper.mapRect(&localDevRect, devRect); SkMatrix localMatrix; - looper.mapMatrix(&localMatrix, matrix); + looper.mapMatrix(&localMatrix, *matrix); - SkAutoBlitterChoose blitterStorage(looper.getBitmap(), localMatrix, - paint); + SkAutoBlitterChoose blitterStorage(looper.getBitmap(), localMatrix, paint); const SkRasterClip& clip = looper.getRC(); SkBlitter* blitter = blitterStorage.get(); @@ -1227,7 +1245,7 @@ static bool clipHandlesSprite(const SkRasterClip& clip, int x, int y, } void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix, - const SkPaint& origPaint) const { + const SkRect* dstBounds, const SkPaint& origPaint) const { SkDEBUGCODE(this->validate();) // nothing to draw @@ -1282,12 +1300,13 @@ void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix, draw.drawBitmapAsMask(bitmap, paint); } else { SkAutoBitmapShaderInstall install(bitmap, paint); - - SkRect r; - r.set(0, 0, SkIntToScalar(bitmap.width()), - SkIntToScalar(bitmap.height())); - // is this ok if paint has a rasterizer? - draw.drawRect(r, install.paintWithShader()); + const SkPaint& paintWithShader = install.paintWithShader(); + const SkRect srcBounds = SkRect::MakeIWH(bitmap.width(), bitmap.height()); + if (dstBounds) { + this->drawRect(srcBounds, paintWithShader, &prematrix, dstBounds); + } else { + draw.drawRect(srcBounds, paintWithShader); + } } }