| Index: src/gpu/SkGpuDevice.cpp
|
| diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
|
| index 86c8ba90f8a24c18f14eb20dc03256f341d50aeb..c997b79bde5c2ea741b39524bb285dcd6dee73b4 100644
|
| --- a/src/gpu/SkGpuDevice.cpp
|
| +++ b/src/gpu/SkGpuDevice.cpp
|
| @@ -27,6 +27,7 @@
|
| #include "SkPathEffect.h"
|
| #include "SkRRect.h"
|
| #include "SkStroke.h"
|
| +#include "SkTLazy.h"
|
| #include "SkUtils.h"
|
| #include "SkErrorInternals.h"
|
|
|
| @@ -1015,6 +1016,8 @@ static void determine_clipped_src_rect(const GrContext* context,
|
| SkRect clippedSrcRect = SkRect::Make(*clippedSrcIRect);
|
| inv.mapRect(&clippedSrcRect);
|
| if (NULL != srcRectPtr) {
|
| + // we've setup src space 0,0 to map to the top left of the src rect.
|
| + clippedSrcRect.offset(srcRectPtr->fLeft, srcRectPtr->fTop);
|
| if (!clippedSrcRect.intersect(*srcRectPtr)) {
|
| clippedSrcIRect->setEmpty();
|
| return;
|
| @@ -1077,13 +1080,17 @@ bool SkGpuDevice::shouldTileBitmap(const SkBitmap& bitmap,
|
| return usedTileBytes < 2 * bmpSize;
|
| }
|
|
|
| -void SkGpuDevice::drawBitmap(const SkDraw& draw,
|
| +void SkGpuDevice::drawBitmap(const SkDraw& origDraw,
|
| const SkBitmap& bitmap,
|
| const SkMatrix& m,
|
| const SkPaint& paint) {
|
| - // We cannot call drawBitmapRect here since 'm' could be anything
|
| - this->drawBitmapCommon(draw, bitmap, NULL, m, paint,
|
| - SkCanvas::kNone_DrawBitmapRectFlag);
|
| + SkMatrix concat;
|
| + SkTCopyOnFirstWrite<SkDraw> draw(origDraw);
|
| + if (!m.isIdentity()) {
|
| + concat.setConcat(*draw->fMatrix, m);
|
| + draw.writable()->fMatrix = &concat;
|
| + }
|
| + this->drawBitmapCommon(*draw, bitmap, NULL, NULL, paint, SkCanvas::kNone_DrawBitmapRectFlag);
|
| }
|
|
|
| // This method outsets 'iRect' by 'outset' all around and then clamps its extents to
|
| @@ -1122,19 +1129,26 @@ static inline void clamped_outset_with_offset(SkIRect* iRect,
|
| void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
|
| const SkBitmap& bitmap,
|
| const SkRect* srcRectPtr,
|
| - const SkMatrix& m,
|
| + const SkSize* dstSizePtr,
|
| const SkPaint& paint,
|
| SkCanvas::DrawBitmapRectFlags flags) {
|
| CHECK_SHOULD_DRAW(draw, false);
|
|
|
| SkRect srcRect;
|
| + SkSize dstSize;
|
| // If there is no src rect, or the src rect contains the entire bitmap then we're effectively
|
| // in the (easier) bleed case, so update flags.
|
| if (NULL == srcRectPtr) {
|
| - srcRect.set(0, 0, SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()));
|
| + SkScalar w = SkIntToScalar(bitmap.width());
|
| + SkScalar h = SkIntToScalar(bitmap.height());
|
| + dstSize.fWidth = w;
|
| + dstSize.fHeight = h;
|
| + srcRect.set(0, 0, w, h);
|
| flags = (SkCanvas::DrawBitmapRectFlags) (flags | SkCanvas::kBleed_DrawBitmapRectFlag);
|
| } else {
|
| + SkASSERT(NULL != dstSizePtr);
|
| srcRect = *srcRectPtr;
|
| + dstSize = *dstSizePtr;
|
| if (srcRect.fLeft <= 0 && srcRect.fTop <= 0 &&
|
| srcRect.fRight >= bitmap.width() && srcRect.fBottom >= bitmap.height()) {
|
| flags = (SkCanvas::DrawBitmapRectFlags) (flags | SkCanvas::kBleed_DrawBitmapRectFlag);
|
| @@ -1144,10 +1158,13 @@ void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
|
| if (paint.getMaskFilter()){
|
| // Convert the bitmap to a shader so that the rect can be drawn
|
| // through drawRect, which supports mask filters.
|
| - SkMatrix newM(m);
|
| SkBitmap tmp; // subset of bitmap, if necessary
|
| const SkBitmap* bitmapPtr = &bitmap;
|
| + SkMatrix localM;
|
| if (NULL != srcRectPtr) {
|
| + localM.setTranslate(-srcRectPtr->fLeft, -srcRectPtr->fTop);
|
| + localM.postScale(dstSize.fWidth / srcRectPtr->width(),
|
| + dstSize.fHeight / srcRectPtr->height());
|
| // In bleed mode we position and trim the bitmap based on the src rect which is
|
| // already accounted for in 'm' and 'srcRect'. In clamp mode we need to chop out
|
| // the desired portion of the bitmap and then update 'm' and 'srcRect' to
|
| @@ -1164,28 +1181,29 @@ void SkGpuDevice::drawBitmapCommon(const SkDraw& draw,
|
| }
|
| bitmapPtr = &tmp;
|
| srcRect.offset(-offset.fX, -offset.fY);
|
| +
|
| // The source rect has changed so update the matrix
|
| - newM.preTranslate(offset.fX, offset.fY);
|
| + localM.preTranslate(offset.fX, offset.fY);
|
| }
|
| + } else {
|
| + localM.reset();
|
| }
|
|
|
| - SkPaint paintWithTexture(paint);
|
| - paintWithTexture.setShader(SkShader::CreateBitmapShader(*bitmapPtr,
|
| + SkPaint paintWithShader(paint);
|
| + paintWithShader.setShader(SkShader::CreateBitmapShader(*bitmapPtr,
|
| SkShader::kClamp_TileMode, SkShader::kClamp_TileMode))->unref();
|
| -
|
| - // Transform 'newM' needs to be concatenated to the current matrix,
|
| - // rather than transforming the primitive directly, so that 'newM' will
|
| - // also affect the behavior of the mask filter.
|
| - SkMatrix drawMatrix;
|
| - drawMatrix.setConcat(fContext->getMatrix(), newM);
|
| - SkDraw transformedDraw(draw);
|
| - transformedDraw.fMatrix = &drawMatrix;
|
| -
|
| - this->drawRect(transformedDraw, srcRect, paintWithTexture);
|
| + paintWithShader.getShader()->setLocalMatrix(localM);
|
| + SkRect dstRect = {0, 0, dstSize.fWidth, dstSize.fHeight};
|
| + this->drawRect(draw, dstRect, paintWithShader);
|
|
|
| return;
|
| }
|
|
|
| + // If there is no mask filter than it is OK to handle the src rect -> dst rect scaling using
|
| + // the view matrix rather than a local matrix.
|
| + SkMatrix m;
|
| + m.setScale(dstSize.fWidth / srcRect.width(),
|
| + dstSize.fHeight / srcRect.height());
|
| fContext->concatMatrix(m);
|
|
|
| GrTextureParams params;
|
| @@ -1287,6 +1305,12 @@ void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap,
|
| SkPoint offset = SkPoint::Make(SkIntToScalar(iTileR.fLeft),
|
| SkIntToScalar(iTileR.fTop));
|
|
|
| + // Adjust the context matrix to draw at the right x,y in device space
|
| + SkMatrix tmpM;
|
| + GrContext::AutoMatrix am;
|
| + tmpM.setTranslate(offset.fX - srcRect.fLeft, offset.fY - srcRect.fTop);
|
| + am.setPreConcat(fContext, tmpM);
|
| +
|
| if (SkPaint::kNone_FilterLevel != paint.getFilterLevel() || bicubic) {
|
| SkIRect iClampRect;
|
|
|
| @@ -1307,10 +1331,7 @@ void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap,
|
| if (bitmap.extractSubset(&tmpB, iTileR)) {
|
| // now offset it to make it "local" to our tmp bitmap
|
| tileR.offset(-offset.fX, -offset.fY);
|
| - SkMatrix tmpM;
|
| - tmpM.setTranslate(offset.fX, offset.fY);
|
| - GrContext::AutoMatrix am;
|
| - am.setPreConcat(fContext, tmpM);
|
| +
|
| this->internalDrawBitmap(tmpB, tileR, params, paint, flags, bicubic);
|
| }
|
| }
|
| @@ -1381,7 +1402,7 @@ void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap,
|
| return;
|
| }
|
|
|
| - SkRect dstRect(srcRect);
|
| + SkRect dstRect = {0, 0, srcRect.width(), srcRect.height() };
|
| SkRect paintRect;
|
| SkScalar wInv = SkScalarInvert(SkIntToScalar(texture->width()));
|
| SkScalar hInv = SkScalarInvert(SkIntToScalar(texture->height()));
|
| @@ -1533,7 +1554,7 @@ void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
|
| SK_Scalar1 * h / texture->height()));
|
| }
|
|
|
| -void SkGpuDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
|
| +void SkGpuDevice::drawBitmapRect(const SkDraw& origDraw, const SkBitmap& bitmap,
|
| const SkRect* src, const SkRect& dst,
|
| const SkPaint& paint,
|
| SkCanvas::DrawBitmapRectFlags flags) {
|
| @@ -1550,6 +1571,7 @@ void SkGpuDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
|
| } else {
|
| tmpSrc = bitmapBounds;
|
| }
|
| +
|
| matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
|
|
|
| // clip the tmpSrc to the bounds of the bitmap. No check needed if src==null.
|
| @@ -1561,7 +1583,21 @@ void SkGpuDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
|
| }
|
| }
|
|
|
| - this->drawBitmapCommon(draw, bitmap, &tmpSrc, matrix, paint, flags);
|
| + SkRect tmpDst;
|
| + matrix.mapRect(&tmpDst, tmpSrc);
|
| +
|
| + SkTCopyOnFirstWrite<SkDraw> draw(origDraw);
|
| + if (0 != tmpDst.fLeft || 0 != tmpDst.fTop) {
|
| + // Translate so that tempDst's top left is at the origin.
|
| + matrix = *origDraw.fMatrix;
|
| + matrix.preTranslate(tmpDst.fLeft, tmpDst.fTop);
|
| + draw.writable()->fMatrix = &matrix;
|
| + }
|
| + SkSize dstSize;
|
| + dstSize.fWidth = tmpDst.width();
|
| + dstSize.fHeight = tmpDst.height();
|
| +
|
| + this->drawBitmapCommon(*draw, bitmap, &tmpSrc, &dstSize, paint, flags);
|
| }
|
|
|
| void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
|
|
|