Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(839)

Unified Diff: src/gpu/SkGpuDevice.cpp

Issue 131323004: Handle drawBitmapRect src_rect->dst_rect mapping as a local matrix rather than view matrix when the… (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: f Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « include/gpu/SkGpuDevice.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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,
« no previous file with comments | « include/gpu/SkGpuDevice.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698