Index: src/gpu/SkGpuDevice.cpp |
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp |
index 483a1496c1c89261a0ecf895017561a8d6f0eab9..d43552e0d724892f09c397d6ff765537b59a9ba7 100644 |
--- a/src/gpu/SkGpuDevice.cpp |
+++ b/src/gpu/SkGpuDevice.cpp |
@@ -1140,6 +1140,74 @@ static inline void clamped_outset_with_offset(SkIRect* iRect, |
} |
} |
+static bool has_aligned_samples(const SkRect& srcRect, |
+ const SkRect& transformedRect) { |
+ // detect pixel disalignment |
+ if (SkScalarAbs(SkScalarRoundToScalar(transformedRect.left()) - |
+ transformedRect.left()) < COLOR_BLEED_TOLERANCE && |
+ SkScalarAbs(SkScalarRoundToScalar(transformedRect.top()) - |
+ transformedRect.top()) < COLOR_BLEED_TOLERANCE && |
+ SkScalarAbs(transformedRect.width() - srcRect.width()) < |
+ COLOR_BLEED_TOLERANCE && |
+ SkScalarAbs(transformedRect.height() - srcRect.height()) < |
+ COLOR_BLEED_TOLERANCE) { |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+static bool may_color_bleed(const SkRect& srcRect, |
+ const SkRect& transformedRect, |
+ const SkMatrix& m) { |
+ // Only gets called if has_aligned_samples returned false. |
+ // So we can assume that sampling is axis aligned but not texel aligned. |
+ SkASSERT(!has_aligned_samples(srcRect, transformedRect)); |
+ SkRect innerSrcRect(srcRect), innerTransformedRect, |
+ outerTransformedRect(transformedRect); |
+ innerSrcRect.inset(SK_ScalarHalf, SK_ScalarHalf); |
+ m.mapRect(&innerTransformedRect, innerSrcRect); |
+ |
+ // The gap between outerTransformedRect and innerTransformedRect |
+ // represents the projection of the source border area, which is |
+ // problematic for color bleeding. We must check whether any |
+ // destination pixels sample the border area. |
+ outerTransformedRect.inset(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE); |
+ innerTransformedRect.outset(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE); |
+ SkIRect outer, inner; |
+ outerTransformedRect.round(&outer); |
+ innerTransformedRect.round(&inner); |
+ // If the inner and outer rects round to the same result, it means the |
+ // border does not overlap any pixel centers. Yay! |
+ return inner != outer; |
+} |
+ |
+static bool needs_texture_domain(const SkBitmap& bitmap, |
+ const SkRect& srcRect, |
+ GrTextureParams ¶ms, |
+ const SkMatrix& contextMatrix, |
+ bool bicubic) { |
+ bool needsTextureDomain = false; |
+ |
+ if (bicubic || params.filterMode() != GrTextureParams::kNone_FilterMode) { |
+ // Need texture domain if drawing a sub rect |
+ needsTextureDomain = srcRect.width() < bitmap.width() || |
+ srcRect.height() < bitmap.height(); |
+ if (!bicubic && needsTextureDomain && contextMatrix.rectStaysRect()) { |
+ // sampling is axis-aligned |
+ SkRect transformedRect; |
+ contextMatrix.mapRect(&transformedRect, srcRect); |
+ |
+ if (has_aligned_samples(srcRect, transformedRect)) { |
+ params.setFilterMode(GrTextureParams::kNone_FilterMode); |
+ needsTextureDomain = false; |
+ } else { |
+ needsTextureDomain = may_color_bleed(srcRect, transformedRect, contextMatrix); |
+ } |
+ } |
+ } |
+ return needsTextureDomain; |
+} |
+ |
void SkGpuDevice::drawBitmapCommon(const SkDraw& draw, |
const SkBitmap& bitmap, |
const SkRect* srcRectPtr, |
@@ -1278,7 +1346,18 @@ void SkGpuDevice::drawBitmapCommon(const SkDraw& draw, |
doBicubic); |
} else { |
// take the simple case |
- this->internalDrawBitmap(bitmap, srcRect, params, paint, flags, doBicubic); |
+ bool needsTextureDomain = needs_texture_domain(bitmap, |
+ srcRect, |
+ params, |
+ fContext->getMatrix(), |
+ doBicubic); |
+ this->internalDrawBitmap(bitmap, |
+ srcRect, |
+ params, |
+ paint, |
+ flags, |
+ doBicubic, |
+ needsTextureDomain); |
} |
} |
@@ -1349,54 +1428,24 @@ 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); |
- |
- this->internalDrawBitmap(tmpB, tileR, params, paint, flags, bicubic); |
+ GrTextureParams paramsTemp = params; |
+ bool needsTextureDomain = needs_texture_domain(bitmap, |
+ srcRect, |
+ paramsTemp, |
+ fContext->getMatrix(), |
+ bicubic); |
+ this->internalDrawBitmap(tmpB, |
+ tileR, |
+ paramsTemp, |
+ paint, |
+ flags, |
+ bicubic, |
+ needsTextureDomain); |
} |
} |
} |
} |
-static bool has_aligned_samples(const SkRect& srcRect, |
- const SkRect& transformedRect) { |
- // detect pixel disalignment |
- if (SkScalarAbs(SkScalarRoundToScalar(transformedRect.left()) - |
- transformedRect.left()) < COLOR_BLEED_TOLERANCE && |
- SkScalarAbs(SkScalarRoundToScalar(transformedRect.top()) - |
- transformedRect.top()) < COLOR_BLEED_TOLERANCE && |
- SkScalarAbs(transformedRect.width() - srcRect.width()) < |
- COLOR_BLEED_TOLERANCE && |
- SkScalarAbs(transformedRect.height() - srcRect.height()) < |
- COLOR_BLEED_TOLERANCE) { |
- return true; |
- } |
- return false; |
-} |
- |
-static bool may_color_bleed(const SkRect& srcRect, |
- const SkRect& transformedRect, |
- const SkMatrix& m) { |
- // Only gets called if has_aligned_samples returned false. |
- // So we can assume that sampling is axis aligned but not texel aligned. |
- SkASSERT(!has_aligned_samples(srcRect, transformedRect)); |
- SkRect innerSrcRect(srcRect), innerTransformedRect, |
- outerTransformedRect(transformedRect); |
- innerSrcRect.inset(SK_ScalarHalf, SK_ScalarHalf); |
- m.mapRect(&innerTransformedRect, innerSrcRect); |
- |
- // The gap between outerTransformedRect and innerTransformedRect |
- // represents the projection of the source border area, which is |
- // problematic for color bleeding. We must check whether any |
- // destination pixels sample the border area. |
- outerTransformedRect.inset(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE); |
- innerTransformedRect.outset(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE); |
- SkIRect outer, inner; |
- outerTransformedRect.round(&outer); |
- innerTransformedRect.round(&inner); |
- // If the inner and outer rects round to the same result, it means the |
- // border does not overlap any pixel centers. Yay! |
- return inner != outer; |
-} |
- |
/* |
* This is called by drawBitmap(), which has to handle images that may be too |
@@ -1410,7 +1459,8 @@ void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap, |
const GrTextureParams& params, |
const SkPaint& paint, |
SkCanvas::DrawBitmapRectFlags flags, |
- bool bicubic) { |
+ bool bicubic, |
+ bool needsTextureDomain) { |
SkASSERT(bitmap.width() <= fContext->getMaxTextureSize() && |
bitmap.height() <= fContext->getMaxTextureSize()); |
@@ -1429,31 +1479,9 @@ void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap, |
SkScalarMul(srcRect.fRight, wInv), |
SkScalarMul(srcRect.fBottom, hInv)); |
- bool needsTextureDomain = false; |
- if (!(flags & SkCanvas::kBleed_DrawBitmapRectFlag) && |
- (bicubic || params.filterMode() != GrTextureParams::kNone_FilterMode)) { |
- // Need texture domain if drawing a sub rect |
- needsTextureDomain = srcRect.width() < bitmap.width() || |
- srcRect.height() < bitmap.height(); |
- if (!bicubic && needsTextureDomain && fContext->getMatrix().rectStaysRect()) { |
- const SkMatrix& matrix = fContext->getMatrix(); |
- // sampling is axis-aligned |
- SkRect transformedRect; |
- matrix.mapRect(&transformedRect, srcRect); |
- |
- if (has_aligned_samples(srcRect, transformedRect)) { |
- // We could also turn off filtering here (but we already did a cache lookup with |
- // params). |
- needsTextureDomain = false; |
- } else { |
- needsTextureDomain = may_color_bleed(srcRect, transformedRect, matrix); |
- } |
- } |
- } |
- |
SkRect textureDomain = SkRect::MakeEmpty(); |
SkAutoTUnref<GrEffectRef> effect; |
- if (needsTextureDomain) { |
+ if (needsTextureDomain && !(flags & SkCanvas::kBleed_DrawBitmapRectFlag)) { |
// Use a constrained texture domain to avoid color bleeding |
SkScalar left, top, right, bottom; |
if (srcRect.width() > SK_Scalar1) { |