| Index: src/core/SkMatrix.cpp
|
| diff --git a/src/core/SkMatrix.cpp b/src/core/SkMatrix.cpp
|
| index 483c6c83e44ef064f3f0191408b98e827668d037..40f6e5298d9375df55a8822b2a0c2372b1b0f116 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) {
|
|
|