Index: src/core/SkBitmapProcState.cpp |
diff --git a/src/core/SkBitmapProcState.cpp b/src/core/SkBitmapProcState.cpp |
index 0b50fbc32dc8f4d160a78bc54e4b46de300ff14b..720a30f05c4a72b77365237c929755e0c1a4cf17 100644 |
--- a/src/core/SkBitmapProcState.cpp |
+++ b/src/core/SkBitmapProcState.cpp |
@@ -98,6 +98,12 @@ |
return (dimension & ~0x3FFF) == 0; |
} |
+static SkScalar effective_matrix_scale(const SkMatrix& mat) { |
+ SkScalar dx = SkVector::Length(mat.getScaleX(), mat.getSkewY()); |
+ SkScalar dy = SkVector::Length(mat.getSkewX(), mat.getScaleY()); |
+ return SkScalarSqrt(dx * dy); |
+} |
+ |
// Check to see that the size of the bitmap that would be produced by |
// scaling by the given inverted matrix is less than the maximum allowed. |
static inline bool cache_size_okay(const SkBitmap& bm, const SkMatrix& invMat) { |
@@ -113,6 +119,22 @@ |
} |
/* |
+ * Extract the "best" scale factors from a matrix. |
+ */ |
+static bool extract_scale(const SkMatrix& matrix, SkVector* scale) { |
+ SkASSERT(!matrix.hasPerspective()); |
+ SkScalar sx = SkPoint::Length(matrix[SkMatrix::kMScaleX], matrix[SkMatrix::kMSkewY]); |
+ SkScalar sy = SkPoint::Length(matrix[SkMatrix::kMSkewX], matrix[SkMatrix::kMScaleY]); |
+ if (!SkScalarIsFinite(sx) || !SkScalarIsFinite(sy) || |
+ SkScalarNearlyZero(sx) || SkScalarNearlyZero(sy)) |
+ { |
+ return false; |
+ } |
+ scale->set(sx, sy); |
+ return true; |
+} |
+ |
+/* |
* High quality is implemented by performing up-right scale-only filtering and then |
* using bilerp for any remaining transformations. |
*/ |
@@ -132,12 +154,12 @@ |
SkScalar invScaleX = fInvMatrix.getScaleX(); |
SkScalar invScaleY = fInvMatrix.getScaleY(); |
if (fInvMatrix.getType() & SkMatrix::kAffine_Mask) { |
- SkSize scale; |
- if (!fInvMatrix.decomposeScale(&scale)) { |
- return; |
- } |
- invScaleX = scale.width(); |
- invScaleY = scale.height(); |
+ SkVector scale; |
+ if (!extract_scale(fInvMatrix, &scale)) { |
+ return; // can't find suitable scale factors |
+ } |
+ invScaleX = scale.x(); |
+ invScaleY = scale.y(); |
} |
if (SkScalarNearlyEqual(invScaleX, 1) && SkScalarNearlyEqual(invScaleY, 1)) { |
return; // no need for HQ |
@@ -182,11 +204,7 @@ |
// to a valid bitmap. |
fFilterLevel = kLow_SkFilterQuality; |
- SkSize invScaleSize; |
- if (!fInvMatrix.decomposeScale(&invScaleSize, NULL)) { |
- return; |
- } |
- SkScalar invScale = SkScalarSqrt(invScaleSize.width() * invScaleSize.height()); |
+ SkScalar invScale = effective_matrix_scale(fInvMatrix); |
if (invScale > SK_Scalar1) { |
fCurrMip.reset(SkMipMapCache::FindAndRef(fOrigBitmap)); |