From 4dcd062803fef457899add1df56e9defb667ce8d Mon Sep 17 00:00:00 2001 From: "commit-bot@chromium.org" Date: Mon, 29 Jul 2013 14:43:31 +0000 Subject: Matrix decomposition cleanup: Add is_degenerate_2x2(), and fix some asserts (atan2 can take a zero x value, but both x == 0 and y == 0 is undefined). R=reed@google.com, robertphillips@google.com Author: jvanverth@google.com Review URL: https://chromiumcodereview.appspot.com/20303003 git-svn-id: http://skia.googlecode.com/svn/trunk@10410 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/core/SkMatrix.cpp | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) (limited to 'src/core') diff --git a/src/core/SkMatrix.cpp b/src/core/SkMatrix.cpp index 64edd67e87..52ed0143b9 100644 --- a/src/core/SkMatrix.cpp +++ b/src/core/SkMatrix.cpp @@ -170,6 +170,15 @@ bool operator==(const SkMatrix& a, const SkMatrix& b) { /////////////////////////////////////////////////////////////////////////////// +// helper function to determine if upper-left 2x2 of matrix is degenerate +static inline bool is_degenerate_2x2(SkScalar scaleX, SkScalar skewX, + SkScalar skewY, SkScalar scaleY) { + SkScalar perp_dot = scaleX*scaleY - skewX*skewY; + return SkScalarNearlyZero(perp_dot, SK_ScalarNearlyZero*SK_ScalarNearlyZero); +} + +/////////////////////////////////////////////////////////////////////////////// + bool SkMatrix::isSimilarity(SkScalar tol) const { // if identity or translate matrix TypeMask mask = this->getType(); @@ -189,10 +198,7 @@ bool SkMatrix::isSimilarity(SkScalar tol) const { SkScalar sx = fMat[kMSkewX]; SkScalar sy = fMat[kMSkewY]; - // TODO: I (rphillips) think there should be an || in here (see preservesRightAngles) - // degenerate matrix, non-similarity - if (SkScalarNearlyZero(mx) && SkScalarNearlyZero(my) - && SkScalarNearlyZero(sx) && SkScalarNearlyZero(sy)) { + if (is_degenerate_2x2(mx, sx, sy, my)) { return false; } @@ -224,9 +230,7 @@ bool SkMatrix::preservesRightAngles(SkScalar tol) const { SkScalar sx = fMat[kMSkewX]; SkScalar sy = fMat[kMSkewY]; - if ((SkScalarNearlyZero(mx) && SkScalarNearlyZero(sx)) || - (SkScalarNearlyZero(my) && SkScalarNearlyZero(sy))) { - // degenerate matrix + if (is_degenerate_2x2(mx, sx, sy, my)) { return false; } @@ -1979,6 +1983,10 @@ bool SkDecomposeUpper2x2(const SkMatrix& matrix, SkScalar C = matrix[SkMatrix::kMSkewY]; SkScalar D = matrix[SkMatrix::kMScaleY]; + if (is_degenerate_2x2(A, B, C, D)) { + return false; + } + SkScalar E = SK_ScalarHalf*(A + D); SkScalar F = SK_ScalarHalf*(A - D); SkScalar G = SK_ScalarHalf*(C + B); @@ -1989,26 +1997,24 @@ bool SkDecomposeUpper2x2(const SkMatrix& matrix, SkScalar xs, ys, r0, r1; - // can't have zero yScale, must be degenerate - if (SkScalarNearlyEqual(sqrt0, sqrt1)) { - return false; - } xs = sqrt0 + sqrt1; ys = sqrt0 - sqrt1; + // can't have zero yScale, must be degenerate + SkASSERT(!SkScalarNearlyZero(ys)); // uniformly scaled rotation if (SkScalarNearlyZero(F) && SkScalarNearlyZero(G)) { - SkASSERT(!SkScalarNearlyZero(E)); + SkASSERT(!SkScalarNearlyZero(E) || !SkScalarNearlyZero(H)); r0 = SkScalarATan2(H, E); r1 = 0; // uniformly scaled reflection } else if (SkScalarNearlyZero(E) && SkScalarNearlyZero(H)) { - SkASSERT(!SkScalarNearlyZero(F)); + SkASSERT(!SkScalarNearlyZero(F) || !SkScalarNearlyZero(G)); r0 = -SkScalarATan2(G, F); r1 = 0; } else { - SkASSERT(!SkScalarNearlyZero(E)); - SkASSERT(!SkScalarNearlyZero(F)); + SkASSERT(!SkScalarNearlyZero(E) || !SkScalarNearlyZero(H)); + SkASSERT(!SkScalarNearlyZero(F) || !SkScalarNearlyZero(G)); SkScalar arctan0 = SkScalarATan2(H, E); SkScalar arctan1 = SkScalarATan2(G, F); -- cgit v1.2.3