aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkMatrix.cpp
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-05-20 17:02:03 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-05-20 17:02:03 +0000
commit311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8e (patch)
treea70bb2efc6b0e8093b9df8240135374102aa92c2 /src/core/SkMatrix.cpp
parent6379129229b3253811a4bc2311b2fc85a3ea7a20 (diff)
Add function to get both min and max scale factors from matrix
R=reed@google.com, jvanverth@google.com Author: bsalomon@google.com Review URL: https://codereview.chromium.org/298473002 git-svn-id: http://skia.googlecode.com/svn/trunk@14804 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/core/SkMatrix.cpp')
-rw-r--r--src/core/SkMatrix.cpp86
1 files changed, 63 insertions, 23 deletions
diff --git a/src/core/SkMatrix.cpp b/src/core/SkMatrix.cpp
index 483c6c83e4..40f6e5298d 100644
--- a/src/core/SkMatrix.cpp
+++ b/src/core/SkMatrix.cpp
@@ -1451,27 +1451,40 @@ bool SkMatrix::setPolyToPoly(const SkPoint src[], const SkPoint dst[],
///////////////////////////////////////////////////////////////////////////////
-enum MinOrMax {
- kMin_MinOrMax,
- kMax_MinOrMax
+enum MinMaxOrBoth {
+ kMin_MinMaxOrBoth,
+ kMax_MinMaxOrBoth,
+ kBoth_MinMaxOrBoth
};
-template <MinOrMax MIN_OR_MAX> SkScalar get_scale_factor(SkMatrix::TypeMask typeMask,
- const SkScalar m[9]) {
+template <MinMaxOrBoth MIN_MAX_OR_BOTH> bool get_scale_factor(SkMatrix::TypeMask typeMask,
+ const SkScalar m[9],
+ SkScalar results[/*1 or 2*/]) {
if (typeMask & SkMatrix::kPerspective_Mask) {
- return -1;
+ return false;
}
if (SkMatrix::kIdentity_Mask == typeMask) {
- return 1;
+ results[0] = SK_Scalar1;
+ if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
+ results[1] = SK_Scalar1;
+ }
+ return true;
}
if (!(typeMask & SkMatrix::kAffine_Mask)) {
- if (kMin_MinOrMax == MIN_OR_MAX) {
- return SkMinScalar(SkScalarAbs(m[SkMatrix::kMScaleX]),
- SkScalarAbs(m[SkMatrix::kMScaleY]));
+ if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
+ results[0] = SkMinScalar(SkScalarAbs(m[SkMatrix::kMScaleX]),
+ SkScalarAbs(m[SkMatrix::kMScaleY]));
+ } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
+ results[0] = SkMaxScalar(SkScalarAbs(m[SkMatrix::kMScaleX]),
+ SkScalarAbs(m[SkMatrix::kMScaleY]));
} else {
- return SkMaxScalar(SkScalarAbs(m[SkMatrix::kMScaleX]),
- SkScalarAbs(m[SkMatrix::kMScaleY]));
+ results[0] = SkScalarAbs(m[SkMatrix::kMScaleX]);
+ results[1] = SkScalarAbs(m[SkMatrix::kMScaleY]);
+ if (results[0] > results[1]) {
+ SkTSwap(results[0], results[1]);
+ }
}
+ return true;
}
// ignore the translation part of the matrix, just look at 2x2 portion.
// compute singular values, take largest or smallest abs value.
@@ -1487,35 +1500,62 @@ template <MinOrMax MIN_OR_MAX> SkScalar get_scale_factor(SkMatrix::TypeMask type
// l^2 - (a + c)l + (ac-b^2)
// solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff
// and roots are guaranteed to be pos and real).
- SkScalar chosenRoot;
SkScalar bSqd = b * b;
// if upper left 2x2 is orthogonal save some math
if (bSqd <= SK_ScalarNearlyZero*SK_ScalarNearlyZero) {
- if (kMin_MinOrMax == MIN_OR_MAX) {
- chosenRoot = SkMinScalar(a, c);
+ if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
+ results[0] = SkMinScalar(a, c);
+ } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
+ results[0] = SkMaxScalar(a, c);
} else {
- chosenRoot = SkMaxScalar(a, c);
+ results[0] = a;
+ results[1] = c;
+ if (results[0] > results[1]) {
+ SkTSwap(results[0], results[1]);
+ }
}
} else {
SkScalar aminusc = a - c;
SkScalar apluscdiv2 = SkScalarHalf(a + c);
SkScalar x = SkScalarHalf(SkScalarSqrt(aminusc * aminusc + 4 * bSqd));
- if (kMin_MinOrMax == MIN_OR_MAX) {
- chosenRoot = apluscdiv2 - x;
+ if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
+ results[0] = apluscdiv2 - x;
+ } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
+ results[0] = apluscdiv2 + x;
} else {
- chosenRoot = apluscdiv2 + x;
+ results[0] = apluscdiv2 - x;
+ results[1] = apluscdiv2 + x;
}
}
- SkASSERT(chosenRoot >= 0);
- return SkScalarSqrt(chosenRoot);
+ SkASSERT(results[0] >= 0);
+ results[0] = SkScalarSqrt(results[0]);
+ if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) {
+ SkASSERT(results[1] >= 0);
+ results[1] = SkScalarSqrt(results[1]);
+ }
+ return true;
}
SkScalar SkMatrix::getMinScale() const {
- return get_scale_factor<kMin_MinOrMax>(this->getType(), fMat);
+ SkScalar factor;
+ if (get_scale_factor<kMin_MinMaxOrBoth>(this->getType(), fMat, &factor)) {
+ return factor;
+ } else {
+ return -1;
+ }
}
SkScalar SkMatrix::getMaxScale() const {
- return get_scale_factor<kMax_MinOrMax>(this->getType(), fMat);
+ SkScalar factor;
+ if (get_scale_factor<kMax_MinMaxOrBoth>(this->getType(), fMat, &factor)) {
+ return factor;
+ } else {
+ return -1;
+ }
+}
+
+bool SkMatrix::getMinMaxScales(SkScalar scaleFactors[2]) const {
+ return get_scale_factor<kBoth_MinMaxOrBoth>(this->getType(), fMat, scaleFactors);
}
static void reset_identity_matrix(SkMatrix* identity) {