remove (unnecessary) SkScalarMul and SkScalarMulAdd macros from SkMatrix.cpp.

SkScalarMulDiv remains, but it can be removed later (though it is slightly clearer to use it at times).

BUG=skia:
R=caryclark@google.com, mtklein@google.com, halcanary@google.com

Author: reed@google.com

Review URL: https://codereview.chromium.org/150493002

git-svn-id: http://skia.googlecode.com/svn/trunk@13252 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
commit-bot@chromium.org 2014-01-30 22:13:12 +00:00
parent 0ed90029e3
commit 0b9ada1318

View File

@ -10,7 +10,20 @@
#include "SkOnce.h" #include "SkOnce.h"
#include "SkString.h" #include "SkString.h"
#define kMatrix22Elem SK_Scalar1 // In a few places, we performed the following
// a * b + c * d + e
// as
// a * b + (c * d + e)
//
// sdot and scross are indended to capture these compound operations into a
// function, with an eye toward considering upscaling the intermediates to
// doubles for more precision (as we do in concat and invert).
//
// However, these few lines that performed the last add before the "dot", cause
// tiny image differences, so we guard that change until we see the impact on
// chrome's layouttests.
//
#define SK_LEGACY_MATRIX_MATH_ORDER
static inline float SkDoubleToFloat(double x) { static inline float SkDoubleToFloat(double x) {
return static_cast<float>(x); return static_cast<float>(x);
@ -22,11 +35,10 @@ static inline float SkDoubleToFloat(double x) {
*/ */
void SkMatrix::reset() { void SkMatrix::reset() {
fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1; fMat[kMScaleX] = fMat[kMScaleY] = fMat[kMPersp2] = 1;
fMat[kMSkewX] = fMat[kMSkewY] = fMat[kMSkewX] = fMat[kMSkewY] =
fMat[kMTransX] = fMat[kMTransY] = fMat[kMTransX] = fMat[kMTransY] =
fMat[kMPersp0] = fMat[kMPersp1] = 0; fMat[kMPersp0] = fMat[kMPersp1] = 0;
fMat[kMPersp2] = kMatrix22Elem;
this->setTypeMask(kIdentity_Mask | kRectStaysRect_Mask); this->setTypeMask(kIdentity_Mask | kRectStaysRect_Mask);
} }
@ -46,8 +58,7 @@ uint8_t SkMatrix::computePerspectiveTypeMask() const {
// Benchmarking suggests that replacing this set of SkScalarAs2sCompliment // Benchmarking suggests that replacing this set of SkScalarAs2sCompliment
// is a win, but replacing those below is not. We don't yet understand // is a win, but replacing those below is not. We don't yet understand
// that result. // that result.
if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 || if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 || fMat[kMPersp2] != 1) {
fMat[kMPersp2] != kMatrix22Elem) {
// If this is a perspective transform, we return true for all other // If this is a perspective transform, we return true for all other
// transform flags - this does not disable any optimizations, respects // transform flags - this does not disable any optimizations, respects
// the rule that the type mask must be conservative, and speeds up // the rule that the type mask must be conservative, and speeds up
@ -61,8 +72,7 @@ uint8_t SkMatrix::computePerspectiveTypeMask() const {
uint8_t SkMatrix::computeTypeMask() const { uint8_t SkMatrix::computeTypeMask() const {
unsigned mask = 0; unsigned mask = 0;
if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 || if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 || fMat[kMPersp2] != 1) {
fMat[kMPersp2] != kMatrix22Elem) {
// Once it is determined that that this is a perspective transform, // Once it is determined that that this is a perspective transform,
// all other flags are moot as far as optimizations are concerned. // all other flags are moot as far as optimizations are concerned.
return SkToU8(kORableMasks); return SkToU8(kORableMasks);
@ -209,15 +219,27 @@ bool SkMatrix::preservesRightAngles(SkScalar tol) const {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
static inline SkScalar sdot(SkScalar a, SkScalar b, SkScalar c, SkScalar d) {
return a * b + c * d;
}
static inline SkScalar sdot(SkScalar a, SkScalar b, SkScalar c, SkScalar d,
SkScalar e, SkScalar f) {
return a * b + c * d + e * f;
}
static inline SkScalar scross(SkScalar a, SkScalar b, SkScalar c, SkScalar d) {
return a * b - c * d;
}
void SkMatrix::setTranslate(SkScalar dx, SkScalar dy) { void SkMatrix::setTranslate(SkScalar dx, SkScalar dy) {
if (dx || dy) { if (dx || dy) {
fMat[kMTransX] = dx; fMat[kMTransX] = dx;
fMat[kMTransY] = dy; fMat[kMTransY] = dy;
fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1; fMat[kMScaleX] = fMat[kMScaleY] = fMat[kMPersp2] = 1;
fMat[kMSkewX] = fMat[kMSkewY] = fMat[kMSkewX] = fMat[kMSkewY] =
fMat[kMPersp0] = fMat[kMPersp1] = 0; fMat[kMPersp0] = fMat[kMPersp1] = 0;
fMat[kMPersp2] = kMatrix22Elem;
this->setTypeMask(kTranslate_Mask | kRectStaysRect_Mask); this->setTypeMask(kTranslate_Mask | kRectStaysRect_Mask);
} else { } else {
@ -233,10 +255,8 @@ bool SkMatrix::preTranslate(SkScalar dx, SkScalar dy) {
} }
if (dx || dy) { if (dx || dy) {
fMat[kMTransX] += SkScalarMul(fMat[kMScaleX], dx) + fMat[kMTransX] += sdot(fMat[kMScaleX], dx, fMat[kMSkewX], dy);
SkScalarMul(fMat[kMSkewX], dy); fMat[kMTransY] += sdot(fMat[kMSkewY], dx, fMat[kMScaleY], dy);
fMat[kMTransY] += SkScalarMul(fMat[kMSkewY], dx) +
SkScalarMul(fMat[kMScaleY], dy);
this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
} }
@ -261,14 +281,14 @@ bool SkMatrix::postTranslate(SkScalar dx, SkScalar dy) {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void SkMatrix::setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { void SkMatrix::setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
if (SK_Scalar1 == sx && SK_Scalar1 == sy) { if (1 == sx && 1 == sy) {
this->reset(); this->reset();
} else { } else {
fMat[kMScaleX] = sx; fMat[kMScaleX] = sx;
fMat[kMScaleY] = sy; fMat[kMScaleY] = sy;
fMat[kMTransX] = px - SkScalarMul(sx, px); fMat[kMTransX] = px - sx * px;
fMat[kMTransY] = py - SkScalarMul(sy, py); fMat[kMTransY] = py - sy * py;
fMat[kMPersp2] = kMatrix22Elem; fMat[kMPersp2] = 1;
fMat[kMSkewX] = fMat[kMSkewY] = fMat[kMSkewX] = fMat[kMSkewY] =
fMat[kMPersp0] = fMat[kMPersp1] = 0; fMat[kMPersp0] = fMat[kMPersp1] = 0;
@ -278,12 +298,12 @@ void SkMatrix::setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
} }
void SkMatrix::setScale(SkScalar sx, SkScalar sy) { void SkMatrix::setScale(SkScalar sx, SkScalar sy) {
if (SK_Scalar1 == sx && SK_Scalar1 == sy) { if (1 == sx && 1 == sy) {
this->reset(); this->reset();
} else { } else {
fMat[kMScaleX] = sx; fMat[kMScaleX] = sx;
fMat[kMScaleY] = sy; fMat[kMScaleY] = sy;
fMat[kMPersp2] = kMatrix22Elem; fMat[kMPersp2] = 1;
fMat[kMTransX] = fMat[kMTransY] = fMat[kMTransX] = fMat[kMTransY] =
fMat[kMSkewX] = fMat[kMSkewY] = fMat[kMSkewX] = fMat[kMSkewY] =
@ -297,7 +317,7 @@ bool SkMatrix::setIDiv(int divx, int divy) {
if (!divx || !divy) { if (!divx || !divy) {
return false; return false;
} }
this->setScale(SK_Scalar1 / divx, SK_Scalar1 / divy); this->setScale(SkScalarInvert(divx), SkScalarInvert(divy));
return true; return true;
} }
@ -308,7 +328,7 @@ bool SkMatrix::preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
} }
bool SkMatrix::preScale(SkScalar sx, SkScalar sy) { bool SkMatrix::preScale(SkScalar sx, SkScalar sy) {
if (SK_Scalar1 == sx && SK_Scalar1 == sy) { if (1 == sx && 1 == sy) {
return true; return true;
} }
@ -317,20 +337,20 @@ bool SkMatrix::preScale(SkScalar sx, SkScalar sy) {
// Also, the fixed-point case checks for overflow, but the float doesn't, // Also, the fixed-point case checks for overflow, but the float doesn't,
// so we can get away with these blind multiplies. // so we can get away with these blind multiplies.
fMat[kMScaleX] = SkScalarMul(fMat[kMScaleX], sx); fMat[kMScaleX] *= sx;
fMat[kMSkewY] = SkScalarMul(fMat[kMSkewY], sx); fMat[kMSkewY] *= sx;
fMat[kMPersp0] = SkScalarMul(fMat[kMPersp0], sx); fMat[kMPersp0] *= sx;
fMat[kMSkewX] = SkScalarMul(fMat[kMSkewX], sy); fMat[kMSkewX] *= sy;
fMat[kMScaleY] = SkScalarMul(fMat[kMScaleY], sy); fMat[kMScaleY] *= sy;
fMat[kMPersp1] = SkScalarMul(fMat[kMPersp1], sy); fMat[kMPersp1] *= sy;
this->orTypeMask(kScale_Mask); this->orTypeMask(kScale_Mask);
return true; return true;
} }
bool SkMatrix::postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { bool SkMatrix::postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
if (SK_Scalar1 == sx && SK_Scalar1 == sy) { if (1 == sx && 1 == sy) {
return true; return true;
} }
SkMatrix m; SkMatrix m;
@ -339,7 +359,7 @@ bool SkMatrix::postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
} }
bool SkMatrix::postScale(SkScalar sx, SkScalar sy) { bool SkMatrix::postScale(SkScalar sx, SkScalar sy) {
if (SK_Scalar1 == sx && SK_Scalar1 == sy) { if (1 == sx && 1 == sy) {
return true; return true;
} }
SkMatrix m; SkMatrix m;
@ -373,18 +393,18 @@ bool SkMatrix::postIDiv(int divx, int divy) {
void SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV, void SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV,
SkScalar px, SkScalar py) { SkScalar px, SkScalar py) {
const SkScalar oneMinusCosV = SK_Scalar1 - cosV; const SkScalar oneMinusCosV = 1 - cosV;
fMat[kMScaleX] = cosV; fMat[kMScaleX] = cosV;
fMat[kMSkewX] = -sinV; fMat[kMSkewX] = -sinV;
fMat[kMTransX] = SkScalarMul(sinV, py) + SkScalarMul(oneMinusCosV, px); fMat[kMTransX] = sdot(sinV, py, oneMinusCosV, px);
fMat[kMSkewY] = sinV; fMat[kMSkewY] = sinV;
fMat[kMScaleY] = cosV; fMat[kMScaleY] = cosV;
fMat[kMTransY] = SkScalarMul(-sinV, px) + SkScalarMul(oneMinusCosV, py); fMat[kMTransY] = sdot(-sinV, px, oneMinusCosV, py);
fMat[kMPersp0] = fMat[kMPersp1] = 0; fMat[kMPersp0] = fMat[kMPersp1] = 0;
fMat[kMPersp2] = kMatrix22Elem; fMat[kMPersp2] = 1;
this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
} }
@ -399,7 +419,7 @@ void SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV) {
fMat[kMTransY] = 0; fMat[kMTransY] = 0;
fMat[kMPersp0] = fMat[kMPersp1] = 0; fMat[kMPersp0] = fMat[kMPersp1] = 0;
fMat[kMPersp2] = kMatrix22Elem; fMat[kMPersp2] = 1;
this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
} }
@ -443,31 +463,31 @@ bool SkMatrix::postRotate(SkScalar degrees) {
//////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////
void SkMatrix::setSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { void SkMatrix::setSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
fMat[kMScaleX] = SK_Scalar1; fMat[kMScaleX] = 1;
fMat[kMSkewX] = sx; fMat[kMSkewX] = sx;
fMat[kMTransX] = SkScalarMul(-sx, py); fMat[kMTransX] = -sx * py;
fMat[kMSkewY] = sy; fMat[kMSkewY] = sy;
fMat[kMScaleY] = SK_Scalar1; fMat[kMScaleY] = 1;
fMat[kMTransY] = SkScalarMul(-sy, px); fMat[kMTransY] = -sy * px;
fMat[kMPersp0] = fMat[kMPersp1] = 0; fMat[kMPersp0] = fMat[kMPersp1] = 0;
fMat[kMPersp2] = kMatrix22Elem; fMat[kMPersp2] = 1;
this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
} }
void SkMatrix::setSkew(SkScalar sx, SkScalar sy) { void SkMatrix::setSkew(SkScalar sx, SkScalar sy) {
fMat[kMScaleX] = SK_Scalar1; fMat[kMScaleX] = 1;
fMat[kMSkewX] = sx; fMat[kMSkewX] = sx;
fMat[kMTransX] = 0; fMat[kMTransX] = 0;
fMat[kMSkewY] = sy; fMat[kMSkewY] = sy;
fMat[kMScaleY] = SK_Scalar1; fMat[kMScaleY] = 1;
fMat[kMTransY] = 0; fMat[kMTransY] = 0;
fMat[kMPersp0] = fMat[kMPersp1] = 0; fMat[kMPersp0] = fMat[kMPersp1] = 0;
fMat[kMPersp2] = kMatrix22Elem; fMat[kMPersp2] = 1;
this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
} }
@ -510,8 +530,8 @@ bool SkMatrix::setRectToRect(const SkRect& src, const SkRect& dst,
sk_bzero(fMat, 8 * sizeof(SkScalar)); sk_bzero(fMat, 8 * sizeof(SkScalar));
this->setTypeMask(kScale_Mask | kRectStaysRect_Mask); this->setTypeMask(kScale_Mask | kRectStaysRect_Mask);
} else { } else {
SkScalar tx, sx = SkScalarDiv(dst.width(), src.width()); SkScalar tx, sx = dst.width() / src.width();
SkScalar ty, sy = SkScalarDiv(dst.height(), src.height()); SkScalar ty, sy = dst.height() / src.height();
bool xLarger = false; bool xLarger = false;
if (align != kFill_ScaleToFit) { if (align != kFill_ScaleToFit) {
@ -523,15 +543,15 @@ bool SkMatrix::setRectToRect(const SkRect& src, const SkRect& dst,
} }
} }
tx = dst.fLeft - SkScalarMul(src.fLeft, sx); tx = dst.fLeft - src.fLeft * sx;
ty = dst.fTop - SkScalarMul(src.fTop, sy); ty = dst.fTop - src.fTop * sy;
if (align == kCenter_ScaleToFit || align == kEnd_ScaleToFit) { if (align == kCenter_ScaleToFit || align == kEnd_ScaleToFit) {
SkScalar diff; SkScalar diff;
if (xLarger) { if (xLarger) {
diff = dst.width() - SkScalarMul(src.width(), sy); diff = dst.width() - src.width() * sy;
} else { } else {
diff = dst.height() - SkScalarMul(src.height(), sy); diff = dst.height() - src.height() * sy;
} }
if (align == kCenter_ScaleToFit) { if (align == kCenter_ScaleToFit) {
@ -553,7 +573,7 @@ bool SkMatrix::setRectToRect(const SkRect& src, const SkRect& dst,
fMat[kMPersp0] = fMat[kMPersp1] = 0; fMat[kMPersp0] = fMat[kMPersp1] = 0;
unsigned mask = kRectStaysRect_Mask; unsigned mask = kRectStaysRect_Mask;
if (sx != SK_Scalar1 || sy != SK_Scalar1) { if (sx != 1 || sy != 1) {
mask |= kScale_Mask; mask |= kScale_Mask;
} }
if (tx || ty) { if (tx || ty) {
@ -562,7 +582,7 @@ bool SkMatrix::setRectToRect(const SkRect& src, const SkRect& dst,
this->setTypeMask(mask); this->setTypeMask(mask);
} }
// shared cleanup // shared cleanup
fMat[kMPersp2] = kMatrix22Elem; fMat[kMPersp2] = 1;
return true; return true;
} }
@ -586,7 +606,7 @@ static inline int negifaddoverflows(float& result, float a, float b) {
} }
static void normalize_perspective(SkScalar mat[9]) { static void normalize_perspective(SkScalar mat[9]) {
if (SkScalarAbs(mat[SkMatrix::kMPersp2]) > kMatrix22Elem) { if (SkScalarAbs(mat[SkMatrix::kMPersp2]) > 1) {
for (int i = 0; i < 9; i++) for (int i = 0; i < 9; i++)
mat[i] = SkScalarHalf(mat[i]); mat[i] = SkScalarHalf(mat[i]);
} }
@ -672,7 +692,7 @@ bool SkMatrix::setConcat(const SkMatrix& a, const SkMatrix& b) {
} }
tmp.fMat[kMPersp0] = tmp.fMat[kMPersp1] = 0; tmp.fMat[kMPersp0] = tmp.fMat[kMPersp1] = 0;
tmp.fMat[kMPersp2] = kMatrix22Elem; tmp.fMat[kMPersp2] = 1;
//SkDebugf("Concat mat non-persp type: %d\n", tmp.getType()); //SkDebugf("Concat mat non-persp type: %d\n", tmp.getType());
//SkASSERT(!(tmp.getType() & kPerspective_Mask)); //SkASSERT(!(tmp.getType() & kPerspective_Mask));
tmp.setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); tmp.setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
@ -702,19 +722,38 @@ bool SkMatrix::postConcat(const SkMatrix& mat) {
the intermediate math, even though we know that is more expensive. the intermediate math, even though we know that is more expensive.
*/ */
typedef double SkDetScalar; static inline SkScalar scross_dscale(SkScalar a, SkScalar b,
#define SkPerspMul(a, b) SkScalarMul(a, b) SkScalar c, SkScalar d, double scale) {
#define SkScalarMulShift(a, b, s) SkDoubleToFloat((a) * (b)) return SkDoubleToScalar(scross(a, b, c, d) * scale);
static double sk_inv_determinant(const float mat[9], int isPerspective, }
int* /* (only used in Fixed case) */) {
static inline double dcross(double a, double b, double c, double d) {
return a * b - c * d;
}
static inline SkScalar dcross_dscale(double a, double b,
double c, double d, double scale) {
return SkDoubleToScalar(dcross(a, b, c, d) * scale);
}
static double sk_inv_determinant(const float mat[9], int isPerspective) {
double det; double det;
if (isPerspective) { if (isPerspective) {
det = mat[SkMatrix::kMScaleX] * ((double)mat[SkMatrix::kMScaleY] * mat[SkMatrix::kMPersp2] - (double)mat[SkMatrix::kMTransY] * mat[SkMatrix::kMPersp1]) + det = mat[SkMatrix::kMScaleX] *
mat[SkMatrix::kMSkewX] * ((double)mat[SkMatrix::kMTransY] * mat[SkMatrix::kMPersp0] - (double)mat[SkMatrix::kMSkewY] * mat[SkMatrix::kMPersp2]) + dcross(mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp2],
mat[SkMatrix::kMTransX] * ((double)mat[SkMatrix::kMSkewY] * mat[SkMatrix::kMPersp1] - (double)mat[SkMatrix::kMScaleY] * mat[SkMatrix::kMPersp0]); mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp1])
+
mat[SkMatrix::kMSkewX] *
dcross(mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp0],
mat[SkMatrix::kMSkewY], mat[SkMatrix::kMPersp2])
+
mat[SkMatrix::kMTransX] *
dcross(mat[SkMatrix::kMSkewY], mat[SkMatrix::kMPersp1],
mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp0]);
} else { } else {
det = (double)mat[SkMatrix::kMScaleX] * mat[SkMatrix::kMScaleY] - (double)mat[SkMatrix::kMSkewX] * mat[SkMatrix::kMSkewY]; det = dcross(mat[SkMatrix::kMScaleX], mat[SkMatrix::kMScaleY],
mat[SkMatrix::kMSkewX], mat[SkMatrix::kMSkewY]);
} }
// Since the determinant is on the order of the cube of the matrix members, // Since the determinant is on the order of the cube of the matrix members,
@ -725,19 +764,12 @@ static double sk_inv_determinant(const float mat[9], int isPerspective,
} }
return 1.0 / det; return 1.0 / det;
} }
// we declar a,b,c,d to all be doubles, because we want to perform
// double-precision muls and subtract, even though the original values are
// from the matrix, which are floats.
static float inline mul_diff_scale(double a, double b, double c, double d,
double scale) {
return SkDoubleToFloat((a * b - c * d) * scale);
}
void SkMatrix::SetAffineIdentity(SkScalar affine[6]) { void SkMatrix::SetAffineIdentity(SkScalar affine[6]) {
affine[kAScaleX] = SK_Scalar1; affine[kAScaleX] = 1;
affine[kASkewY] = 0; affine[kASkewY] = 0;
affine[kASkewX] = 0; affine[kASkewX] = 0;
affine[kAScaleY] = SK_Scalar1; affine[kAScaleY] = 1;
affine[kATransX] = 0; affine[kATransX] = 0;
affine[kATransY] = 0; affine[kATransY] = 0;
} }
@ -782,9 +814,9 @@ bool SkMatrix::invertNonIdentity(SkMatrix* inv) const {
inv->fMat[kMScaleX] = invX; inv->fMat[kMScaleX] = invX;
inv->fMat[kMScaleY] = invY; inv->fMat[kMScaleY] = invY;
inv->fMat[kMPersp2] = kMatrix22Elem; inv->fMat[kMPersp2] = 1;
inv->fMat[kMTransX] = -SkScalarMul(fMat[kMTransX], invX); inv->fMat[kMTransX] = -fMat[kMTransX] * invX;
inv->fMat[kMTransY] = -SkScalarMul(fMat[kMTransY], invY); inv->fMat[kMTransY] = -fMat[kMTransY] * invY;
inv->setTypeMask(mask | kRectStaysRect_Mask); inv->setTypeMask(mask | kRectStaysRect_Mask);
} else { } else {
@ -799,9 +831,8 @@ bool SkMatrix::invertNonIdentity(SkMatrix* inv) const {
return invertible; return invertible;
} }
int isPersp = mask & kPerspective_Mask; int isPersp = mask & kPerspective_Mask;
int shift; double scale = sk_inv_determinant(fMat, isPersp);
SkDetScalar scale = sk_inv_determinant(fMat, isPersp, &shift);
if (scale == 0) { // underflow if (scale == 0) { // underflow
return false; return false;
@ -814,33 +845,29 @@ bool SkMatrix::invertNonIdentity(SkMatrix* inv) const {
} }
if (isPersp) { if (isPersp) {
shift = 61 - shift; inv->fMat[kMScaleX] = scross_dscale(fMat[kMScaleY], fMat[kMPersp2], fMat[kMTransY], fMat[kMPersp1], scale);
inv->fMat[kMScaleX] = SkScalarMulShift(SkPerspMul(fMat[kMScaleY], fMat[kMPersp2]) - SkPerspMul(fMat[kMTransY], fMat[kMPersp1]), scale, shift); inv->fMat[kMSkewX] = scross_dscale(fMat[kMTransX], fMat[kMPersp1], fMat[kMSkewX], fMat[kMPersp2], scale);
inv->fMat[kMSkewX] = SkScalarMulShift(SkPerspMul(fMat[kMTransX], fMat[kMPersp1]) - SkPerspMul(fMat[kMSkewX], fMat[kMPersp2]), scale, shift); inv->fMat[kMTransX] = scross_dscale(fMat[kMSkewX], fMat[kMTransY], fMat[kMTransX], fMat[kMScaleY], scale);
inv->fMat[kMTransX] = SkScalarMulShift(SkScalarMul(fMat[kMSkewX], fMat[kMTransY]) - SkScalarMul(fMat[kMTransX], fMat[kMScaleY]), scale, shift);
inv->fMat[kMSkewY] = SkScalarMulShift(SkPerspMul(fMat[kMTransY], fMat[kMPersp0]) - SkPerspMul(fMat[kMSkewY], fMat[kMPersp2]), scale, shift); inv->fMat[kMSkewY] = scross_dscale(fMat[kMTransY], fMat[kMPersp0], fMat[kMSkewY], fMat[kMPersp2], scale);
inv->fMat[kMScaleY] = SkScalarMulShift(SkPerspMul(fMat[kMScaleX], fMat[kMPersp2]) - SkPerspMul(fMat[kMTransX], fMat[kMPersp0]), scale, shift); inv->fMat[kMScaleY] = scross_dscale(fMat[kMScaleX], fMat[kMPersp2], fMat[kMTransX], fMat[kMPersp0], scale);
inv->fMat[kMTransY] = SkScalarMulShift(SkScalarMul(fMat[kMTransX], fMat[kMSkewY]) - SkScalarMul(fMat[kMScaleX], fMat[kMTransY]), scale, shift); inv->fMat[kMTransY] = scross_dscale(fMat[kMTransX], fMat[kMSkewY], fMat[kMScaleX], fMat[kMTransY], scale);
inv->fMat[kMPersp0] = SkScalarMulShift(SkScalarMul(fMat[kMSkewY], fMat[kMPersp1]) - SkScalarMul(fMat[kMScaleY], fMat[kMPersp0]), scale, shift); inv->fMat[kMPersp0] = scross_dscale(fMat[kMSkewY], fMat[kMPersp1], fMat[kMScaleY], fMat[kMPersp0], scale);
inv->fMat[kMPersp1] = SkScalarMulShift(SkScalarMul(fMat[kMSkewX], fMat[kMPersp0]) - SkScalarMul(fMat[kMScaleX], fMat[kMPersp1]), scale, shift); inv->fMat[kMPersp1] = scross_dscale(fMat[kMSkewX], fMat[kMPersp0], fMat[kMScaleX], fMat[kMPersp1], scale);
inv->fMat[kMPersp2] = SkScalarMulShift(SkScalarMul(fMat[kMScaleX], fMat[kMScaleY]) - SkScalarMul(fMat[kMSkewX], fMat[kMSkewY]), scale, shift); inv->fMat[kMPersp2] = scross_dscale(fMat[kMScaleX], fMat[kMScaleY], fMat[kMSkewX], fMat[kMSkewY], scale);
} else { // not perspective } else { // not perspective
inv->fMat[kMScaleX] = SkDoubleToFloat(fMat[kMScaleY] * scale); inv->fMat[kMScaleX] = SkDoubleToScalar(fMat[kMScaleY] * scale);
inv->fMat[kMSkewX] = SkDoubleToFloat(-fMat[kMSkewX] * scale); inv->fMat[kMSkewX] = SkDoubleToScalar(-fMat[kMSkewX] * scale);
inv->fMat[kMTransX] = mul_diff_scale(fMat[kMSkewX], fMat[kMTransY], inv->fMat[kMTransX] = dcross_dscale(fMat[kMSkewX], fMat[kMTransY], fMat[kMScaleY], fMat[kMTransX], scale);
fMat[kMScaleY], fMat[kMTransX], scale);
inv->fMat[kMSkewY] = SkDoubleToFloat(-fMat[kMSkewY] * scale); inv->fMat[kMSkewY] = SkDoubleToScalar(-fMat[kMSkewY] * scale);
inv->fMat[kMScaleY] = SkDoubleToFloat(fMat[kMScaleX] * scale); inv->fMat[kMScaleY] = SkDoubleToScalar(fMat[kMScaleX] * scale);
inv->fMat[kMTransY] = mul_diff_scale(fMat[kMSkewY], fMat[kMTransX], inv->fMat[kMTransY] = dcross_dscale(fMat[kMSkewY], fMat[kMTransX], fMat[kMScaleX], fMat[kMTransY], scale);
fMat[kMScaleX], fMat[kMTransY], scale);
inv->fMat[kMPersp0] = 0; inv->fMat[kMPersp0] = 0;
inv->fMat[kMPersp1] = 0; inv->fMat[kMPersp1] = 0;
inv->fMat[kMPersp2] = kMatrix22Elem; inv->fMat[kMPersp2] = 1;
} }
inv->setTypeMask(fTypeMask); inv->setTypeMask(fTypeMask);
@ -886,8 +913,8 @@ void SkMatrix::Scale_pts(const SkMatrix& m, SkPoint dst[],
SkScalar mx = m.fMat[kMScaleX]; SkScalar mx = m.fMat[kMScaleX];
SkScalar my = m.fMat[kMScaleY]; SkScalar my = m.fMat[kMScaleY];
do { do {
dst->fY = SkScalarMul(src->fY, my); dst->fY = src->fY * my;
dst->fX = SkScalarMul(src->fX, mx); dst->fX = src->fX * mx;
src += 1; src += 1;
dst += 1; dst += 1;
} while (--count); } while (--count);
@ -904,8 +931,8 @@ void SkMatrix::ScaleTrans_pts(const SkMatrix& m, SkPoint dst[],
SkScalar tx = m.fMat[kMTransX]; SkScalar tx = m.fMat[kMTransX];
SkScalar ty = m.fMat[kMTransY]; SkScalar ty = m.fMat[kMTransY];
do { do {
dst->fY = SkScalarMulAdd(src->fY, my, ty); dst->fY = src->fY * my + ty;
dst->fX = SkScalarMulAdd(src->fX, mx, tx); dst->fX = src->fX * mx + tx;
src += 1; src += 1;
dst += 1; dst += 1;
} while (--count); } while (--count);
@ -925,8 +952,8 @@ void SkMatrix::Rot_pts(const SkMatrix& m, SkPoint dst[],
SkScalar sy = src->fY; SkScalar sy = src->fY;
SkScalar sx = src->fX; SkScalar sx = src->fX;
src += 1; src += 1;
dst->fY = SkScalarMul(sx, ky) + SkScalarMul(sy, my); dst->fY = sdot(sx, ky, sy, my);
dst->fX = SkScalarMul(sx, mx) + SkScalarMul(sy, kx); dst->fX = sdot(sx, mx, sy, kx);
dst += 1; dst += 1;
} while (--count); } while (--count);
} }
@ -947,8 +974,13 @@ void SkMatrix::RotTrans_pts(const SkMatrix& m, SkPoint dst[],
SkScalar sy = src->fY; SkScalar sy = src->fY;
SkScalar sx = src->fX; SkScalar sx = src->fX;
src += 1; src += 1;
dst->fY = SkScalarMul(sx, ky) + SkScalarMulAdd(sy, my, ty); #ifdef SK_LEGACY_MATRIX_MATH_ORDER
dst->fX = SkScalarMul(sx, mx) + SkScalarMulAdd(sy, kx, tx); dst->fY = sx * ky + (sy * my + ty);
dst->fX = sx * mx + (sy * kx + tx);
#else
dst->fY = sdot(sx, ky, sy, my) + ty;
dst->fX = sdot(sx, mx, sy, kx) + tx;
#endif
dst += 1; dst += 1;
} while (--count); } while (--count);
} }
@ -964,18 +996,19 @@ void SkMatrix::Persp_pts(const SkMatrix& m, SkPoint dst[],
SkScalar sx = src->fX; SkScalar sx = src->fX;
src += 1; src += 1;
SkScalar x = SkScalarMul(sx, m.fMat[kMScaleX]) + SkScalar x = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX];
SkScalarMul(sy, m.fMat[kMSkewX]) + m.fMat[kMTransX]; SkScalar y = sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
SkScalar y = SkScalarMul(sx, m.fMat[kMSkewY]) + #ifdef SK_LEGACY_MATRIX_MATH_ORDER
SkScalarMul(sy, m.fMat[kMScaleY]) + m.fMat[kMTransY]; SkScalar z = sx * m.fMat[kMPersp0] + (sy * m.fMat[kMPersp1] + m.fMat[kMPersp2]);
SkScalar z = SkScalarMul(sx, m.fMat[kMPersp0]) + #else
SkScalarMulAdd(sy, m.fMat[kMPersp1], m.fMat[kMPersp2]); SkScalar z = sdot(sx, m.fMat[kMPersp0], sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2];
#endif
if (z) { if (z) {
z = SkScalarFastInvert(z); z = SkScalarFastInvert(z);
} }
dst->fY = SkScalarMul(y, z); dst->fY = y * z;
dst->fX = SkScalarMul(x, z); dst->fX = x * z;
dst += 1; dst += 1;
} while (--count); } while (--count);
} }
@ -1019,15 +1052,9 @@ void SkMatrix::mapHomogeneousPoints(SkScalar dst[], const SkScalar src[], int co
SkScalar sw = src[2]; SkScalar sw = src[2];
src += 3; src += 3;
SkScalar x = SkScalarMul(sx, fMat[kMScaleX]) + SkScalar x = sdot(sx, fMat[kMScaleX], sy, fMat[kMSkewX], sw, fMat[kMTransX]);
SkScalarMul(sy, fMat[kMSkewX]) + SkScalar y = sdot(sx, fMat[kMSkewY], sy, fMat[kMScaleY], sw, fMat[kMTransY]);
SkScalarMul(sw, fMat[kMTransX]); SkScalar w = sdot(sx, fMat[kMPersp0], sy, fMat[kMPersp1], sw, fMat[kMPersp2]);
SkScalar y = SkScalarMul(sx, fMat[kMSkewY]) +
SkScalarMul(sy, fMat[kMScaleY]) +
SkScalarMul(sw, fMat[kMTransY]);
SkScalar w = SkScalarMul(sx, fMat[kMPersp0]) +
SkScalarMul(sy, fMat[kMPersp1]) +
SkScalarMul(sw, fMat[kMPersp2]);
dst[0] = x; dst[0] = x;
dst[1] = y; dst[1] = y;
@ -1098,27 +1125,27 @@ void SkMatrix::Persp_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
SkPoint* pt) { SkPoint* pt) {
SkASSERT(m.hasPerspective()); SkASSERT(m.hasPerspective());
SkScalar x = SkScalarMul(sx, m.fMat[kMScaleX]) + SkScalar x = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX];
SkScalarMul(sy, m.fMat[kMSkewX]) + m.fMat[kMTransX]; SkScalar y = sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
SkScalar y = SkScalarMul(sx, m.fMat[kMSkewY]) + SkScalar z = sdot(sx, m.fMat[kMPersp0], sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2];
SkScalarMul(sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
SkScalar z = SkScalarMul(sx, m.fMat[kMPersp0]) +
SkScalarMul(sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2];
if (z) { if (z) {
z = SkScalarFastInvert(z); z = SkScalarFastInvert(z);
} }
pt->fX = SkScalarMul(x, z); pt->fX = x * z;
pt->fY = SkScalarMul(y, z); pt->fY = y * z;
} }
void SkMatrix::RotTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, void SkMatrix::RotTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
SkPoint* pt) { SkPoint* pt) {
SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask)) == kAffine_Mask); SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask)) == kAffine_Mask);
pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]) + #ifdef SK_LEGACY_MATRIX_MATH_ORDER
SkScalarMulAdd(sy, m.fMat[kMSkewX], m.fMat[kMTransX]); pt->fX = sx * m.fMat[kMScaleX] + (sy * m.fMat[kMSkewX] + m.fMat[kMTransX]);
pt->fY = SkScalarMul(sx, m.fMat[kMSkewY]) + pt->fY = sx * m.fMat[kMSkewY] + (sy * m.fMat[kMScaleY] + m.fMat[kMTransY]);
SkScalarMulAdd(sy, m.fMat[kMScaleY], m.fMat[kMTransY]); #else
pt->fX = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX];
pt->fY = sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
#endif
} }
void SkMatrix::Rot_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, void SkMatrix::Rot_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
@ -1127,10 +1154,13 @@ void SkMatrix::Rot_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
SkASSERT(0 == m.fMat[kMTransX]); SkASSERT(0 == m.fMat[kMTransX]);
SkASSERT(0 == m.fMat[kMTransY]); SkASSERT(0 == m.fMat[kMTransY]);
pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]) + #ifdef SK_LEGACY_MATRIX_MATH_ORDER
SkScalarMulAdd(sy, m.fMat[kMSkewX], m.fMat[kMTransX]); pt->fX = sx * m.fMat[kMScaleX] + (sy * m.fMat[kMSkewX] + m.fMat[kMTransX]);
pt->fY = SkScalarMul(sx, m.fMat[kMSkewY]) + pt->fY = sx * m.fMat[kMSkewY] + (sy * m.fMat[kMScaleY] + m.fMat[kMTransY]);
SkScalarMulAdd(sy, m.fMat[kMScaleY], m.fMat[kMTransY]); #else
pt->fX = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX];
pt->fY = sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
#endif
} }
void SkMatrix::ScaleTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, void SkMatrix::ScaleTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
@ -1138,8 +1168,8 @@ void SkMatrix::ScaleTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask)) SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask))
== kScale_Mask); == kScale_Mask);
pt->fX = SkScalarMulAdd(sx, m.fMat[kMScaleX], m.fMat[kMTransX]); pt->fX = sx * m.fMat[kMScaleX] + m.fMat[kMTransX];
pt->fY = SkScalarMulAdd(sy, m.fMat[kMScaleY], m.fMat[kMTransY]); pt->fY = sy * m.fMat[kMScaleY] + m.fMat[kMTransY];
} }
void SkMatrix::Scale_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, void SkMatrix::Scale_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
@ -1149,8 +1179,8 @@ void SkMatrix::Scale_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
SkASSERT(0 == m.fMat[kMTransX]); SkASSERT(0 == m.fMat[kMTransX]);
SkASSERT(0 == m.fMat[kMTransY]); SkASSERT(0 == m.fMat[kMTransY]);
pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]); pt->fX = sx * m.fMat[kMScaleX];
pt->fY = SkScalarMul(sy, m.fMat[kMScaleY]); pt->fY = sy * m.fMat[kMScaleY];
} }
void SkMatrix::Trans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, void SkMatrix::Trans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
@ -1190,7 +1220,7 @@ bool SkMatrix::fixedStepInX(SkScalar y, SkFixed* stepX, SkFixed* stepY) const {
if (PerspNearlyZero(fMat[kMPersp0])) { if (PerspNearlyZero(fMat[kMPersp0])) {
if (stepX || stepY) { if (stepX || stepY) {
if (PerspNearlyZero(fMat[kMPersp1]) && if (PerspNearlyZero(fMat[kMPersp1]) &&
PerspNearlyZero(fMat[kMPersp2] - kMatrix22Elem)) { PerspNearlyZero(fMat[kMPersp2] - 1)) {
if (stepX) { if (stepX) {
*stepX = SkScalarToFixed(fMat[kMScaleX]); *stepX = SkScalarToFixed(fMat[kMScaleX]);
} }
@ -1200,10 +1230,10 @@ bool SkMatrix::fixedStepInX(SkScalar y, SkFixed* stepX, SkFixed* stepY) const {
} else { } else {
SkScalar z = y * fMat[kMPersp1] + fMat[kMPersp2]; SkScalar z = y * fMat[kMPersp1] + fMat[kMPersp2];
if (stepX) { if (stepX) {
*stepX = SkScalarToFixed(SkScalarDiv(fMat[kMScaleX], z)); *stepX = SkScalarToFixed(fMat[kMScaleX] / z);
} }
if (stepY) { if (stepY) {
*stepY = SkScalarToFixed(SkScalarDiv(fMat[kMSkewY], z)); *stepY = SkScalarToFixed(fMat[kMSkewY] / z);
} }
} }
} }
@ -1291,8 +1321,7 @@ static inline bool poly_to_point(SkPoint* pt, const SkPoint poly[], int count) {
pt2.fX = poly[0].fY - poly[3].fY; pt2.fX = poly[0].fY - poly[3].fY;
pt2.fY = poly[3].fX - poly[0].fX; pt2.fY = poly[3].fX - poly[0].fX;
CALC_X: CALC_X:
x = SkScalarDiv(SkScalarMul(pt1.fX, pt2.fX) + x = sdot(pt1.fX, pt2.fX, pt1.fY, pt2.fY) / y;
SkScalarMul(pt1.fY, pt2.fY), y);
break; break;
} }
} }
@ -1354,13 +1383,13 @@ bool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst,
if (checkForZero(denom)) { if (checkForZero(denom)) {
return false; return false;
} }
a1 = SkScalarDiv(SkScalarMulDiv(x0 - x1, y2, x2) - y0 + y1, denom); a1 = (SkScalarMulDiv(x0 - x1, y2, x2) - y0 + y1) / denom;
} else { } else {
float denom = x1 - SkScalarMulDiv(y1, x2, y2); float denom = x1 - SkScalarMulDiv(y1, x2, y2);
if (checkForZero(denom)) { if (checkForZero(denom)) {
return false; return false;
} }
a1 = SkScalarDiv(x0 - x1 - SkScalarMulDiv(y0 - y1, x2, y2), denom); a1 = (x0 - x1 - SkScalarMulDiv(y0 - y1, x2, y2)) / denom;
} }
/* check if abs(x1) > abs(y1) */ /* check if abs(x1) > abs(y1) */
@ -1369,27 +1398,25 @@ bool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst,
if (checkForZero(denom)) { if (checkForZero(denom)) {
return false; return false;
} }
a2 = SkScalarDiv(y0 - y2 - SkScalarMulDiv(x0 - x2, y1, x1), denom); a2 = (y0 - y2 - SkScalarMulDiv(x0 - x2, y1, x1)) / denom;
} else { } else {
float denom = SkScalarMulDiv(y2, x1, y1) - x2; float denom = SkScalarMulDiv(y2, x1, y1) - x2;
if (checkForZero(denom)) { if (checkForZero(denom)) {
return false; return false;
} }
a2 = SkScalarDiv(SkScalarMulDiv(y0 - y2, x1, y1) - x0 + x2, denom); a2 = (SkScalarMulDiv(y0 - y2, x1, y1) - x0 + x2) / denom;
} }
float invScale = 1 / scale.fX; float invScale = SkScalarInvert(scale.fX);
dst->fMat[kMScaleX] = SkScalarMul(SkScalarMul(a2, srcPt[3].fX) + dst->fMat[kMScaleX] = (a2 * srcPt[3].fX + srcPt[3].fX - srcPt[0].fX) * invScale;
srcPt[3].fX - srcPt[0].fX, invScale); dst->fMat[kMSkewY] = (a2 * srcPt[3].fY + srcPt[3].fY - srcPt[0].fY) * invScale;
dst->fMat[kMSkewY] = SkScalarMul(SkScalarMul(a2, srcPt[3].fY) + dst->fMat[kMPersp0] = a2 * invScale;
srcPt[3].fY - srcPt[0].fY, invScale);
dst->fMat[kMPersp0] = SkScalarMul(a2, invScale); invScale = SkScalarInvert(scale.fY);
invScale = 1 / scale.fY; dst->fMat[kMSkewX] = (a1 * srcPt[1].fX + srcPt[1].fX - srcPt[0].fX) * invScale;
dst->fMat[kMSkewX] = SkScalarMul(SkScalarMul(a1, srcPt[1].fX) + dst->fMat[kMScaleY] = (a1 * srcPt[1].fY + srcPt[1].fY - srcPt[0].fY) * invScale;
srcPt[1].fX - srcPt[0].fX, invScale); dst->fMat[kMPersp1] = a1 * invScale;
dst->fMat[kMScaleY] = SkScalarMul(SkScalarMul(a1, srcPt[1].fY) +
srcPt[1].fY - srcPt[0].fY, invScale);
dst->fMat[kMPersp1] = SkScalarMul(a1, invScale);
dst->fMat[kMTransX] = srcPt[0].fX; dst->fMat[kMTransX] = srcPt[0].fX;
dst->fMat[kMTransY] = srcPt[0].fY; dst->fMat[kMTransY] = srcPt[0].fY;
dst->fMat[kMPersp2] = 1; dst->fMat[kMPersp2] = 1;
@ -1458,10 +1485,10 @@ enum MinOrMax {
template <MinOrMax MIN_OR_MAX> SkScalar get_stretch_factor(SkMatrix::TypeMask typeMask, template <MinOrMax MIN_OR_MAX> SkScalar get_stretch_factor(SkMatrix::TypeMask typeMask,
const SkScalar m[9]) { const SkScalar m[9]) {
if (typeMask & SkMatrix::kPerspective_Mask) { if (typeMask & SkMatrix::kPerspective_Mask) {
return -SK_Scalar1; return -1;
} }
if (SkMatrix::kIdentity_Mask == typeMask) { if (SkMatrix::kIdentity_Mask == typeMask) {
return SK_Scalar1; return 1;
} }
if (!(typeMask & SkMatrix::kAffine_Mask)) { if (!(typeMask & SkMatrix::kAffine_Mask)) {
if (kMin_MinOrMax == MIN_OR_MAX) { if (kMin_MinOrMax == MIN_OR_MAX) {
@ -1475,19 +1502,19 @@ template <MinOrMax MIN_OR_MAX> SkScalar get_stretch_factor(SkMatrix::TypeMask ty
// ignore the translation part of the matrix, just look at 2x2 portion. // ignore the translation part of the matrix, just look at 2x2 portion.
// compute singular values, take largest or smallest abs value. // compute singular values, take largest or smallest abs value.
// [a b; b c] = A^T*A // [a b; b c] = A^T*A
SkScalar a = SkScalarMul(m[SkMatrix::kMScaleX], m[SkMatrix::kMScaleX]) + SkScalar a = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMScaleX],
SkScalarMul(m[SkMatrix::kMSkewY], m[SkMatrix::kMSkewY]); m[SkMatrix::kMSkewY], m[SkMatrix::kMSkewY]);
SkScalar b = SkScalarMul(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewX]) + SkScalar b = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewX],
SkScalarMul(m[SkMatrix::kMScaleY], m[SkMatrix::kMSkewY]); m[SkMatrix::kMScaleY], m[SkMatrix::kMSkewY]);
SkScalar c = SkScalarMul(m[SkMatrix::kMSkewX], m[SkMatrix::kMSkewX]) + SkScalar c = sdot(m[SkMatrix::kMSkewX], m[SkMatrix::kMSkewX],
SkScalarMul(m[SkMatrix::kMScaleY], m[SkMatrix::kMScaleY]); m[SkMatrix::kMScaleY], m[SkMatrix::kMScaleY]);
// eigenvalues of A^T*A are the squared singular values of A. // eigenvalues of A^T*A are the squared singular values of A.
// characteristic equation is det((A^T*A) - l*I) = 0 // characteristic equation is det((A^T*A) - l*I) = 0
// l^2 - (a + c)l + (ac-b^2) // l^2 - (a + c)l + (ac-b^2)
// solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff
// and roots are guaranteed to be pos and real). // and roots are guaranteed to be pos and real).
SkScalar chosenRoot; SkScalar chosenRoot;
SkScalar bSqd = SkScalarMul(b,b); SkScalar bSqd = b * b;
// if upper left 2x2 is orthogonal save some math // if upper left 2x2 is orthogonal save some math
if (bSqd <= SK_ScalarNearlyZero*SK_ScalarNearlyZero) { if (bSqd <= SK_ScalarNearlyZero*SK_ScalarNearlyZero) {
if (kMin_MinOrMax == MIN_OR_MAX) { if (kMin_MinOrMax == MIN_OR_MAX) {
@ -1498,7 +1525,7 @@ template <MinOrMax MIN_OR_MAX> SkScalar get_stretch_factor(SkMatrix::TypeMask ty
} else { } else {
SkScalar aminusc = a - c; SkScalar aminusc = a - c;
SkScalar apluscdiv2 = SkScalarHalf(a + c); SkScalar apluscdiv2 = SkScalarHalf(a + c);
SkScalar x = SkScalarHalf(SkScalarSqrt(SkScalarMul(aminusc, aminusc) + 4 * bSqd)); SkScalar x = SkScalarHalf(SkScalarSqrt(aminusc * aminusc + 4 * bSqd));
if (kMin_MinOrMax == MIN_OR_MAX) { if (kMin_MinOrMax == MIN_OR_MAX) {
chosenRoot = apluscdiv2 - x; chosenRoot = apluscdiv2 - x;
} else { } else {
@ -1661,7 +1688,7 @@ bool SkDecomposeUpper2x2(const SkMatrix& matrix,
double Sa, Sb, Sd; double Sa, Sb, Sd;
// if M is already symmetric (i.e., M = I*S) // if M is already symmetric (i.e., M = I*S)
if (SkScalarNearlyEqual(B, C)) { if (SkScalarNearlyEqual(B, C)) {
cosQ = SK_Scalar1; cosQ = 1;
sinQ = 0; sinQ = 0;
Sa = A; Sa = A;
@ -1670,7 +1697,7 @@ bool SkDecomposeUpper2x2(const SkMatrix& matrix,
} else { } else {
cosQ = A + D; cosQ = A + D;
sinQ = C - B; sinQ = C - B;
SkScalar reciplen = SK_Scalar1/SkScalarSqrt(cosQ*cosQ + sinQ*sinQ); SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cosQ*cosQ + sinQ*sinQ));
cosQ *= reciplen; cosQ *= reciplen;
sinQ *= reciplen; sinQ *= reciplen;
@ -1686,7 +1713,7 @@ bool SkDecomposeUpper2x2(const SkMatrix& matrix,
// From this, should be able to reconstruct S as U*W*U^T // From this, should be able to reconstruct S as U*W*U^T
if (SkScalarNearlyZero(SkDoubleToScalar(Sb))) { if (SkScalarNearlyZero(SkDoubleToScalar(Sb))) {
// already diagonalized // already diagonalized
cos1 = SK_Scalar1; cos1 = 1;
sin1 = 0; sin1 = 0;
w1 = Sa; w1 = Sa;
w2 = Sd; w2 = Sd;
@ -1705,7 +1732,7 @@ bool SkDecomposeUpper2x2(const SkMatrix& matrix,
} }
cos1 = SkDoubleToScalar(Sb); sin1 = SkDoubleToScalar(w1 - Sa); cos1 = SkDoubleToScalar(Sb); sin1 = SkDoubleToScalar(w1 - Sa);
SkScalar reciplen = SK_Scalar1/SkScalarSqrt(cos1*cos1 + sin1*sin1); SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cos1*cos1 + sin1*sin1));
cos1 *= reciplen; cos1 *= reciplen;
sin1 *= reciplen; sin1 *= reciplen;