MatrixTest.cpp revision 1878651990d7c9da72cf43481432232bbef3550d
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
7e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.org
8889bd8bd7f604acae0a6303365bc82c06da1e6f3tomhudson@google.com#include "SkMath.h"
9ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com#include "SkMatrix.h"
1008284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org#include "SkMatrixUtils.h"
11383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com#include "SkRandom.h"
128f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "Test.h"
13ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
14ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.comstatic bool nearly_equal_scalar(SkScalar a, SkScalar b) {
152047f00e4698f83499ab91911999a65c21a951c9epoger@google.com    const SkScalar tolerance = SK_Scalar1 / 200000;
16ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    return SkScalarAbs(a - b) <= tolerance;
17ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com}
18ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
19ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.comstatic bool nearly_equal(const SkMatrix& a, const SkMatrix& b) {
20ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    for (int i = 0; i < 9; i++) {
21ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com        if (!nearly_equal_scalar(a[i], b[i])) {
22fab44db294846ff05d837b9cf0bf97a073891da7bungeman@google.com            SkDebugf("not equal %g %g\n", (float)a[i], (float)b[i]);
23ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            return false;
24ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com        }
25ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    }
26ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    return true;
27ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com}
28ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
298fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.comstatic bool are_equal(skiatest::Reporter* reporter,
308fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com                      const SkMatrix& a,
318fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com                      const SkMatrix& b) {
328fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com    bool equal = a == b;
338fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com    bool cheapEqual = a.cheapEqualTo(b);
348fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com    if (equal != cheapEqual) {
3539d4f3a02c21a32b766b13068d5bb65d4c332846bsalomon@google.com        if (equal) {
368fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com            bool foundZeroSignDiff = false;
378fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com            for (int i = 0; i < 9; ++i) {
388fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com                float aVal = a.get(i);
398fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com                float bVal = b.get(i);
40373ebc634573364c27b1ebd35bb537ef1285cba4bsalomon@google.com                int aValI = *SkTCast<int*>(&aVal);
41373ebc634573364c27b1ebd35bb537ef1285cba4bsalomon@google.com                int bValI = *SkTCast<int*>(&bVal);
428fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com                if (0 == aVal && 0 == bVal && aValI != bValI) {
438fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com                    foundZeroSignDiff = true;
448fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com                } else {
458fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com                    REPORTER_ASSERT(reporter, aVal == bVal && aValI == aValI);
468fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com                }
478fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com            }
488fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com            REPORTER_ASSERT(reporter, foundZeroSignDiff);
498fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com        } else {
508fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com            bool foundNaN = false;
518fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com            for (int i = 0; i < 9; ++i) {
528fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com                float aVal = a.get(i);
538fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com                float bVal = b.get(i);
54373ebc634573364c27b1ebd35bb537ef1285cba4bsalomon@google.com                int aValI = *SkTCast<int*>(&aVal);
55373ebc634573364c27b1ebd35bb537ef1285cba4bsalomon@google.com                int bValI = *SkTCast<int*>(&bVal);
568fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com                if (sk_float_isnan(aVal) && aValI == bValI) {
578fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com                    foundNaN = true;
588fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com                } else {
598fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com                    REPORTER_ASSERT(reporter, aVal == bVal && aValI == bValI);
608fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com                }
618fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com            }
628fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com            REPORTER_ASSERT(reporter, foundNaN);
638fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com        }
648fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com    }
658fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com    return equal;
668fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com}
678fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com
68ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.comstatic bool is_identity(const SkMatrix& m) {
69ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    SkMatrix identity;
7080e39a77b16f4396eed230efea1d0b2fc8cbfb00reed@android.com    identity.reset();
71ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    return nearly_equal(m, identity);
72ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com}
73ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
7497cd69ca23b27d88e08727366c29c1147eb564dereed@google.comstatic void test_matrix_recttorect(skiatest::Reporter* reporter) {
7597cd69ca23b27d88e08727366c29c1147eb564dereed@google.com    SkRect src, dst;
7697cd69ca23b27d88e08727366c29c1147eb564dereed@google.com    SkMatrix matrix;
77f57c01bdcfdf1c923b9a473974bfe6f8c66eca3eskia.committer@gmail.com
7897cd69ca23b27d88e08727366c29c1147eb564dereed@google.com    src.set(0, 0, SK_Scalar1*10, SK_Scalar1*10);
7997cd69ca23b27d88e08727366c29c1147eb564dereed@google.com    dst = src;
8097cd69ca23b27d88e08727366c29c1147eb564dereed@google.com    matrix.setRectToRect(src, dst, SkMatrix::kFill_ScaleToFit);
8197cd69ca23b27d88e08727366c29c1147eb564dereed@google.com    REPORTER_ASSERT(reporter, SkMatrix::kIdentity_Mask == matrix.getType());
8297cd69ca23b27d88e08727366c29c1147eb564dereed@google.com    REPORTER_ASSERT(reporter, matrix.rectStaysRect());
83f57c01bdcfdf1c923b9a473974bfe6f8c66eca3eskia.committer@gmail.com
8497cd69ca23b27d88e08727366c29c1147eb564dereed@google.com    dst.offset(SK_Scalar1, SK_Scalar1);
8597cd69ca23b27d88e08727366c29c1147eb564dereed@google.com    matrix.setRectToRect(src, dst, SkMatrix::kFill_ScaleToFit);
8697cd69ca23b27d88e08727366c29c1147eb564dereed@google.com    REPORTER_ASSERT(reporter, SkMatrix::kTranslate_Mask == matrix.getType());
8797cd69ca23b27d88e08727366c29c1147eb564dereed@google.com    REPORTER_ASSERT(reporter, matrix.rectStaysRect());
88f57c01bdcfdf1c923b9a473974bfe6f8c66eca3eskia.committer@gmail.com
8997cd69ca23b27d88e08727366c29c1147eb564dereed@google.com    dst.fRight += SK_Scalar1;
9097cd69ca23b27d88e08727366c29c1147eb564dereed@google.com    matrix.setRectToRect(src, dst, SkMatrix::kFill_ScaleToFit);
91e659c2e820de0b8d12d81247ed4430022ded0a90skia.committer@gmail.com    REPORTER_ASSERT(reporter,
9293f03324189f211db95c312b3cb08b435cc5ac34robertphillips@google.com                    (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask) == matrix.getType());
9397cd69ca23b27d88e08727366c29c1147eb564dereed@google.com    REPORTER_ASSERT(reporter, matrix.rectStaysRect());
9497cd69ca23b27d88e08727366c29c1147eb564dereed@google.com
9597cd69ca23b27d88e08727366c29c1147eb564dereed@google.com    dst = src;
9697cd69ca23b27d88e08727366c29c1147eb564dereed@google.com    dst.fRight = src.fRight * 2;
9797cd69ca23b27d88e08727366c29c1147eb564dereed@google.com    matrix.setRectToRect(src, dst, SkMatrix::kFill_ScaleToFit);
9897cd69ca23b27d88e08727366c29c1147eb564dereed@google.com    REPORTER_ASSERT(reporter, SkMatrix::kScale_Mask == matrix.getType());
9997cd69ca23b27d88e08727366c29c1147eb564dereed@google.com    REPORTER_ASSERT(reporter, matrix.rectStaysRect());
10097cd69ca23b27d88e08727366c29c1147eb564dereed@google.com}
10197cd69ca23b27d88e08727366c29c1147eb564dereed@google.com
1024b7577b042966657c776fd95c67f9363af57945freed@android.comstatic void test_flatten(skiatest::Reporter* reporter, const SkMatrix& m) {
1034b7577b042966657c776fd95c67f9363af57945freed@android.com    // add 100 in case we have a bug, I don't want to kill my stack in the test
1044faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    static const size_t kBufferSize = SkMatrix::kMaxFlattenSize + 100;
1054faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    char buffer[kBufferSize];
1064faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    size_t size1 = m.writeToMemory(NULL);
1074faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    size_t size2 = m.writeToMemory(buffer);
1084b7577b042966657c776fd95c67f9363af57945freed@android.com    REPORTER_ASSERT(reporter, size1 == size2);
1094b7577b042966657c776fd95c67f9363af57945freed@android.com    REPORTER_ASSERT(reporter, size1 <= SkMatrix::kMaxFlattenSize);
110d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
1114b7577b042966657c776fd95c67f9363af57945freed@android.com    SkMatrix m2;
1124faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    size_t size3 = m2.readFromMemory(buffer, kBufferSize);
11394e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com    REPORTER_ASSERT(reporter, size1 == size3);
1148fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com    REPORTER_ASSERT(reporter, are_equal(reporter, m, m2));
115d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
1164faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    char buffer2[kBufferSize];
11794e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com    size3 = m2.writeToMemory(buffer2);
11894e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com    REPORTER_ASSERT(reporter, size1 == size3);
1194b7577b042966657c776fd95c67f9363af57945freed@android.com    REPORTER_ASSERT(reporter, memcmp(buffer, buffer2, size1) == 0);
1204b7577b042966657c776fd95c67f9363af57945freed@android.com}
1214b7577b042966657c776fd95c67f9363af57945freed@android.com
1221878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.orgstatic void test_matrix_min_max_scale(skiatest::Reporter* reporter) {
123383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com    SkMatrix identity;
124383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com    identity.reset();
1251878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org    REPORTER_ASSERT(reporter, SK_Scalar1 == identity.getMinScale());
1261878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org    REPORTER_ASSERT(reporter, SK_Scalar1 == identity.getMaxScale());
127383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com
128383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com    SkMatrix scale;
129383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com    scale.setScale(SK_Scalar1 * 2, SK_Scalar1 * 4);
1301878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org    REPORTER_ASSERT(reporter, SK_Scalar1 * 2 == scale.getMinScale());
1311878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org    REPORTER_ASSERT(reporter, SK_Scalar1 * 4 == scale.getMaxScale());
132383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com
133383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com    SkMatrix rot90Scale;
134383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com    rot90Scale.setRotate(90 * SK_Scalar1);
135383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com    rot90Scale.postScale(SK_Scalar1 / 4, SK_Scalar1 / 2);
1361878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org    REPORTER_ASSERT(reporter, SK_Scalar1 / 4 == rot90Scale.getMinScale());
1371878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org    REPORTER_ASSERT(reporter, SK_Scalar1 / 2 == rot90Scale.getMaxScale());
138383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com
139383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com    SkMatrix rotate;
140383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com    rotate.setRotate(128 * SK_Scalar1);
1411878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(SK_Scalar1, rotate.getMinScale() ,SK_ScalarNearlyZero));
1421878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(SK_Scalar1, rotate.getMaxScale(), SK_ScalarNearlyZero));
143383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com
144383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com    SkMatrix translate;
145383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com    translate.setTranslate(10 * SK_Scalar1, -5 * SK_Scalar1);
1461878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org    REPORTER_ASSERT(reporter, SK_Scalar1 == translate.getMinScale());
1471878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org    REPORTER_ASSERT(reporter, SK_Scalar1 == translate.getMaxScale());
148383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com
149383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com    SkMatrix perspX;
150383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com    perspX.reset();
15107faed110275048c83a55ae39042da2c9d916108bungeman@google.com    perspX.setPerspX(SkScalarToPersp(SK_Scalar1 / 1000));
1521878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org    REPORTER_ASSERT(reporter, -SK_Scalar1 == perspX.getMinScale());
1531878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org    REPORTER_ASSERT(reporter, -SK_Scalar1 == perspX.getMaxScale());
154383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com
155383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com    SkMatrix perspY;
156383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com    perspY.reset();
157cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org    perspY.setPerspY(SkScalarToPersp(-SK_Scalar1 / 500));
1581878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org    REPORTER_ASSERT(reporter, -SK_Scalar1 == perspY.getMinScale());
1591878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org    REPORTER_ASSERT(reporter, -SK_Scalar1 == perspY.getMaxScale());
160383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com
161383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com    SkMatrix baseMats[] = {scale, rot90Scale, rotate,
162383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com                           translate, perspX, perspY};
163383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com    SkMatrix mats[2*SK_ARRAY_COUNT(baseMats)];
16483a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(baseMats); ++i) {
165383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com        mats[i] = baseMats[i];
166383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com        bool invertable = mats[i].invert(&mats[i + SK_ARRAY_COUNT(baseMats)]);
167383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com        REPORTER_ASSERT(reporter, invertable);
168383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com    }
169e0e7cfe44bb9d66d76120a79e5275c294bacaa22commit-bot@chromium.org    SkRandom rand;
170383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com    for (int m = 0; m < 1000; ++m) {
171383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com        SkMatrix mat;
172383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com        mat.reset();
173383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com        for (int i = 0; i < 4; ++i) {
174383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com            int x = rand.nextU() % SK_ARRAY_COUNT(mats);
175383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com            mat.postConcat(mats[x]);
176383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com        }
177d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
1781878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org        SkScalar minScale = mat.getMinScale();
1791878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org        SkScalar maxScale = mat.getMaxScale();
1801878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org        REPORTER_ASSERT(reporter, (minScale < 0) == (maxScale < 0));
1811878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org        REPORTER_ASSERT(reporter, (maxScale < 0) == mat.hasPerspective());
182383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com
183383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com        if (mat.hasPerspective()) {
184383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com            m -= 1; // try another non-persp matrix
185383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com            continue;
186383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com        }
187383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com
1881878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org        // test a bunch of vectors. All should be scaled by between minScale and maxScale
189cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org        // (modulo some error) and we should find a vector that is scaled by almost each.
1901878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org        static const SkScalar gVectorScaleTol = (105 * SK_Scalar1) / 100;
1911878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org        static const SkScalar gCloseScaleTol = (97 * SK_Scalar1) / 100;
192cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org        SkScalar max = 0, min = SK_ScalarMax;
193383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com        SkVector vectors[1000];
19483a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com        for (size_t i = 0; i < SK_ARRAY_COUNT(vectors); ++i) {
195383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com            vectors[i].fX = rand.nextSScalar1();
196383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com            vectors[i].fY = rand.nextSScalar1();
197383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com            if (!vectors[i].normalize()) {
198383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com                i -= 1;
199383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com                continue;
200383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com            }
201383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com        }
202383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com        mat.mapVectors(vectors, SK_ARRAY_COUNT(vectors));
20383a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com        for (size_t i = 0; i < SK_ARRAY_COUNT(vectors); ++i) {
204383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com            SkScalar d = vectors[i].length();
2051878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org            REPORTER_ASSERT(reporter, SkScalarDiv(d, maxScale) < gVectorScaleTol);
2061878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org            REPORTER_ASSERT(reporter, SkScalarDiv(minScale, d) < gVectorScaleTol);
207383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com            if (max < d) {
208383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com                max = d;
209383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com            }
210cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org            if (min > d) {
211cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org                min = d;
212cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org            }
213383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com        }
2141878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org        REPORTER_ASSERT(reporter, SkScalarDiv(max, maxScale) >= gCloseScaleTol);
2151878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org        REPORTER_ASSERT(reporter, SkScalarDiv(minScale, min) >= gCloseScaleTol);
216383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com    }
217383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com}
218383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com
21946d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.comstatic void test_matrix_is_similarity(skiatest::Reporter* reporter) {
22069afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    SkMatrix mat;
22169afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com
22269afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    // identity
22369afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.setIdentity();
22446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    REPORTER_ASSERT(reporter, mat.isSimilarity());
22569afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com
22669afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    // translation only
22769afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.reset();
22869afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.setTranslate(SkIntToScalar(100), SkIntToScalar(100));
22946d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    REPORTER_ASSERT(reporter, mat.isSimilarity());
23069afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com
23169afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    // scale with same size
23269afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.reset();
23369afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.setScale(SkIntToScalar(15), SkIntToScalar(15));
23446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    REPORTER_ASSERT(reporter, mat.isSimilarity());
23569afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com
23669afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    // scale with one negative
23769afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.reset();
23869afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.setScale(SkIntToScalar(-15), SkIntToScalar(15));
23946d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    REPORTER_ASSERT(reporter, mat.isSimilarity());
24069afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com
24169afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    // scale with different size
24269afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.reset();
24369afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.setScale(SkIntToScalar(15), SkIntToScalar(20));
24446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    REPORTER_ASSERT(reporter, !mat.isSimilarity());
24569afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com
24669afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    // scale with same size at a pivot point
24769afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.reset();
24869afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.setScale(SkIntToScalar(15), SkIntToScalar(15),
24969afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com                 SkIntToScalar(2), SkIntToScalar(2));
25046d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    REPORTER_ASSERT(reporter, mat.isSimilarity());
25169afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com
25269afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    // scale with different size at a pivot point
25369afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.reset();
25469afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.setScale(SkIntToScalar(15), SkIntToScalar(20),
25569afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com                 SkIntToScalar(2), SkIntToScalar(2));
25646d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    REPORTER_ASSERT(reporter, !mat.isSimilarity());
25769afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com
25869afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    // skew with same size
25969afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.reset();
26069afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.setSkew(SkIntToScalar(15), SkIntToScalar(15));
26146d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    REPORTER_ASSERT(reporter, !mat.isSimilarity());
26269afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com
26369afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    // skew with different size
26469afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.reset();
26569afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.setSkew(SkIntToScalar(15), SkIntToScalar(20));
26646d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    REPORTER_ASSERT(reporter, !mat.isSimilarity());
26769afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com
26869afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    // skew with same size at a pivot point
26969afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.reset();
27069afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.setSkew(SkIntToScalar(15), SkIntToScalar(15),
27169afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com                SkIntToScalar(2), SkIntToScalar(2));
27246d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    REPORTER_ASSERT(reporter, !mat.isSimilarity());
27369afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com
27469afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    // skew with different size at a pivot point
27569afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.reset();
27669afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.setSkew(SkIntToScalar(15), SkIntToScalar(20),
27769afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com                SkIntToScalar(2), SkIntToScalar(2));
27846d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    REPORTER_ASSERT(reporter, !mat.isSimilarity());
27969afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com
28069afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    // perspective x
28169afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.reset();
28269afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.setPerspX(SkScalarToPersp(SK_Scalar1 / 2));
28346d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    REPORTER_ASSERT(reporter, !mat.isSimilarity());
28469afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com
28569afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    // perspective y
28669afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.reset();
28769afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.setPerspY(SkScalarToPersp(SK_Scalar1 / 2));
28846d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    REPORTER_ASSERT(reporter, !mat.isSimilarity());
28969afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com
29069afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    // rotate
29169afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    for (int angle = 0; angle < 360; ++angle) {
29269afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com        mat.reset();
29369afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com        mat.setRotate(SkIntToScalar(angle));
29446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com        REPORTER_ASSERT(reporter, mat.isSimilarity());
29569afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    }
29669afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com
29769afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    // see if there are any accumulated precision issues
29869afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.reset();
29969afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    for (int i = 1; i < 360; i++) {
30069afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com        mat.postRotate(SkIntToScalar(1));
30169afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    }
30246d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    REPORTER_ASSERT(reporter, mat.isSimilarity());
30369afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com
30469afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    // rotate + translate
30569afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.reset();
30669afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.setRotate(SkIntToScalar(30));
30769afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.postTranslate(SkIntToScalar(10), SkIntToScalar(20));
30846d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    REPORTER_ASSERT(reporter, mat.isSimilarity());
30969afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com
31069afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    // rotate + uniform scale
31169afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.reset();
31269afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.setRotate(SkIntToScalar(30));
31369afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.postScale(SkIntToScalar(2), SkIntToScalar(2));
31446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    REPORTER_ASSERT(reporter, mat.isSimilarity());
31569afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com
31669afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    // rotate + non-uniform scale
31769afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.reset();
31869afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.setRotate(SkIntToScalar(30));
31969afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.postScale(SkIntToScalar(3), SkIntToScalar(2));
32046d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    REPORTER_ASSERT(reporter, !mat.isSimilarity());
32169afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com
32269afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    // all zero
32369afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.setAll(0, 0, 0, 0, 0, 0, 0, 0, 0);
32446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    REPORTER_ASSERT(reporter, !mat.isSimilarity());
32569afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com
32669afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    // all zero except perspective
32769afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.setAll(0, 0, 0, 0, 0, 0, 0, 0, SK_Scalar1);
32846d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    REPORTER_ASSERT(reporter, !mat.isSimilarity());
32969afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com
33069afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    // scales zero, only skews
33169afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com    mat.setAll(0, SK_Scalar1, 0,
33269afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com               SK_Scalar1, 0, 0,
33369afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com               0, 0, SkMatrix::I()[8]);
33446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    REPORTER_ASSERT(reporter, mat.isSimilarity());
33569afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com}
33669afee1c8fd22affc873890cfcf766d6f5cfdcc2bsalomon@google.com
33708284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org// For test_matrix_decomposition, below.
3385c561cb8d8151d38c69128345106cbf225033a1askia.committer@gmail.comstatic bool scalar_nearly_equal_relative(SkScalar a, SkScalar b,
33908284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org                                         SkScalar tolerance = SK_ScalarNearlyZero) {
34008284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    // from Bruce Dawson
3415b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    // absolute check
34208284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    SkScalar diff = SkScalarAbs(a - b);
34308284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    if (diff < tolerance) {
34408284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org        return true;
34508284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    }
34608284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
3475b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    // relative check
34808284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    a = SkScalarAbs(a);
34908284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    b = SkScalarAbs(b);
35008284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    SkScalar largest = (b > a) ? b : a;
35108284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
35208284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    if (diff <= largest*tolerance) {
35308284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org        return true;
35408284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    }
35508284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
35608284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    return false;
35708284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org}
35808284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
3595b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.orgstatic bool check_matrix_recomposition(const SkMatrix& mat,
3605b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org                                       const SkPoint& rotation1,
3615b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org                                       const SkPoint& scale,
3625b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org                                       const SkPoint& rotation2) {
3635b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    SkScalar c1 = rotation1.fX;
3645b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    SkScalar s1 = rotation1.fY;
3655b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    SkScalar scaleX = scale.fX;
3665b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    SkScalar scaleY = scale.fY;
3675b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    SkScalar c2 = rotation2.fX;
3685b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    SkScalar s2 = rotation2.fY;
36985092f05c406ed5a0c65ff576816924c1a6b903bskia.committer@gmail.com
3705b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    // We do a relative check here because large scale factors cause problems with an absolute check
3715b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    bool result = scalar_nearly_equal_relative(mat[SkMatrix::kMScaleX],
3725b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org                                               scaleX*c1*c2 - scaleY*s1*s2) &&
3735b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org                  scalar_nearly_equal_relative(mat[SkMatrix::kMSkewX],
3745b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org                                               -scaleX*s1*c2 - scaleY*c1*s2) &&
3755b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org                  scalar_nearly_equal_relative(mat[SkMatrix::kMSkewY],
3765b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org                                               scaleX*c1*s2 + scaleY*s1*c2) &&
3775b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org                  scalar_nearly_equal_relative(mat[SkMatrix::kMScaleY],
3785b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org                                               -scaleX*s1*s2 + scaleY*c1*c2);
3795b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    return result;
3805b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org}
3815b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org
38208284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.orgstatic void test_matrix_decomposition(skiatest::Reporter* reporter) {
38308284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    SkMatrix mat;
3845b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    SkPoint rotation1, scale, rotation2;
38508284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
38608284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    const float kRotation0 = 15.5f;
38708284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    const float kRotation1 = -50.f;
38808284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    const float kScale0 = 5000.f;
38908284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    const float kScale1 = 0.001f;
39008284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
39108284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    // identity
39208284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.reset();
3935b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation1, &scale, &rotation2));
3945b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, check_matrix_recomposition(mat, rotation1, scale, rotation2));
39508284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    // make sure it doesn't crash if we pass in NULLs
3965b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, NULL, NULL, NULL));
39708284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
39808284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    // rotation only
39908284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.setRotate(kRotation0);
4005b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation1, &scale, &rotation2));
4015b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, check_matrix_recomposition(mat, rotation1, scale, rotation2));
40208284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
40308284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    // uniform scale only
40408284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.setScale(kScale0, kScale0);
4055b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation1, &scale, &rotation2));
4065b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, check_matrix_recomposition(mat, rotation1, scale, rotation2));
40708284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
40808284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    // anisotropic scale only
40908284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.setScale(kScale1, kScale0);
4105b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation1, &scale, &rotation2));
4115b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, check_matrix_recomposition(mat, rotation1, scale, rotation2));
41208284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
41308284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    // rotation then uniform scale
41408284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.setRotate(kRotation1);
41508284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.postScale(kScale0, kScale0);
4165b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation1, &scale, &rotation2));
4175b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, check_matrix_recomposition(mat, rotation1, scale, rotation2));
41808284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
41908284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    // uniform scale then rotation
42008284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.setScale(kScale0, kScale0);
42108284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.postRotate(kRotation1);
4225b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation1, &scale, &rotation2));
4235b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, check_matrix_recomposition(mat, rotation1, scale, rotation2));
42408284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
42508284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    // rotation then uniform scale+reflection
42608284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.setRotate(kRotation0);
42708284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.postScale(kScale1, -kScale1);
4285b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation1, &scale, &rotation2));
4295b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, check_matrix_recomposition(mat, rotation1, scale, rotation2));
43008284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
43108284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    // uniform scale+reflection, then rotate
43208284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.setScale(kScale0, -kScale0);
43308284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.postRotate(kRotation1);
4345b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation1, &scale, &rotation2));
4355b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, check_matrix_recomposition(mat, rotation1, scale, rotation2));
43608284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
43708284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    // rotation then anisotropic scale
43808284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.setRotate(kRotation1);
43908284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.postScale(kScale1, kScale0);
4405b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation1, &scale, &rotation2));
4415b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, check_matrix_recomposition(mat, rotation1, scale, rotation2));
44208284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
4435b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    // rotation then anisotropic scale
4445b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    mat.setRotate(90);
4455b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    mat.postScale(kScale1, kScale0);
4465b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation1, &scale, &rotation2));
4475b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, check_matrix_recomposition(mat, rotation1, scale, rotation2));
44885092f05c406ed5a0c65ff576816924c1a6b903bskia.committer@gmail.com
44908284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    // anisotropic scale then rotation
45008284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.setScale(kScale1, kScale0);
45108284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.postRotate(kRotation0);
4525b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation1, &scale, &rotation2));
4535b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, check_matrix_recomposition(mat, rotation1, scale, rotation2));
45485092f05c406ed5a0c65ff576816924c1a6b903bskia.committer@gmail.com
4555b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    // anisotropic scale then rotation
4565b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    mat.setScale(kScale1, kScale0);
4575b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    mat.postRotate(90);
4585b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation1, &scale, &rotation2));
4595b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, check_matrix_recomposition(mat, rotation1, scale, rotation2));
46008284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
46108284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    // rotation, uniform scale, then different rotation
46208284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.setRotate(kRotation1);
46308284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.postScale(kScale0, kScale0);
46408284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.postRotate(kRotation0);
4655b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation1, &scale, &rotation2));
4665b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, check_matrix_recomposition(mat, rotation1, scale, rotation2));
46708284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
46808284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    // rotation, anisotropic scale, then different rotation
46908284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.setRotate(kRotation0);
47008284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.postScale(kScale1, kScale0);
47108284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.postRotate(kRotation1);
4725b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation1, &scale, &rotation2));
4735b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, check_matrix_recomposition(mat, rotation1, scale, rotation2));
47485092f05c406ed5a0c65ff576816924c1a6b903bskia.committer@gmail.com
4755b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    // rotation, anisotropic scale + reflection, then different rotation
4765b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    mat.setRotate(kRotation0);
4775b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    mat.postScale(-kScale1, kScale0);
4785b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    mat.postRotate(kRotation1);
4795b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation1, &scale, &rotation2));
4805b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, check_matrix_recomposition(mat, rotation1, scale, rotation2));
48108284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
48208284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    // try some random matrices
483e0e7cfe44bb9d66d76120a79e5275c294bacaa22commit-bot@chromium.org    SkRandom rand;
48408284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    for (int m = 0; m < 1000; ++m) {
4855b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org        SkScalar rot0 = rand.nextRangeF(-180, 180);
48608284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org        SkScalar sx = rand.nextRangeF(-3000.f, 3000.f);
48708284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org        SkScalar sy = rand.nextRangeF(-3000.f, 3000.f);
4885b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org        SkScalar rot1 = rand.nextRangeF(-180, 180);
48908284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org        mat.setRotate(rot0);
49008284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org        mat.postScale(sx, sy);
49108284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org        mat.postRotate(rot1);
49208284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
4935b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org        if (SkDecomposeUpper2x2(mat, &rotation1, &scale, &rotation2)) {
4945b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org            REPORTER_ASSERT(reporter, check_matrix_recomposition(mat, rotation1, scale, rotation2));
49508284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org        } else {
49608284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org            // if the matrix is degenerate, the basis vectors should be near-parallel or near-zero
49708284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org            SkScalar perpdot = mat[SkMatrix::kMScaleX]*mat[SkMatrix::kMScaleY] -
49808284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org                               mat[SkMatrix::kMSkewX]*mat[SkMatrix::kMSkewY];
49908284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org            REPORTER_ASSERT(reporter, SkScalarNearlyZero(perpdot));
50008284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org        }
50108284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    }
50208284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
50308284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    // translation shouldn't affect this
50408284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.postTranslate(-1000.f, 1000.f);
5055b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation1, &scale, &rotation2));
5065b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, check_matrix_recomposition(mat, rotation1, scale, rotation2));
50708284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
50808284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    // perspective shouldn't affect this
509588f3d3896ce84a00ba0b229a4fe8fff2bf67516jvanverth@google.com    mat[SkMatrix::kMPersp0] = 12.f;
510588f3d3896ce84a00ba0b229a4fe8fff2bf67516jvanverth@google.com    mat[SkMatrix::kMPersp1] = 4.f;
511588f3d3896ce84a00ba0b229a4fe8fff2bf67516jvanverth@google.com    mat[SkMatrix::kMPersp2] = 1872.f;
5125b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation1, &scale, &rotation2));
5135b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, check_matrix_recomposition(mat, rotation1, scale, rotation2));
51408284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
51508284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    // degenerate matrices
51608284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    // mostly zero entries
51708284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.reset();
51808284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat[SkMatrix::kMScaleX] = 0.f;
5195b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, !SkDecomposeUpper2x2(mat, &rotation1, &scale, &rotation2));
52008284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.reset();
52108284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat[SkMatrix::kMScaleY] = 0.f;
5225b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, !SkDecomposeUpper2x2(mat, &rotation1, &scale, &rotation2));
52308284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat.reset();
52408284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    // linearly dependent entries
52508284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat[SkMatrix::kMScaleX] = 1.f;
52608284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat[SkMatrix::kMSkewX] = 2.f;
52708284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat[SkMatrix::kMSkewY] = 4.f;
52808284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    mat[SkMatrix::kMScaleY] = 8.f;
5295b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org    REPORTER_ASSERT(reporter, !SkDecomposeUpper2x2(mat, &rotation1, &scale, &rotation2));
53008284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org}
53108284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org
532259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com// For test_matrix_homogeneous, below.
533259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.comstatic bool scalar_array_nearly_equal_relative(const SkScalar a[], const SkScalar b[], int count) {
534259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    for (int i = 0; i < count; ++i) {
535259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com        if (!scalar_nearly_equal_relative(a[i], b[i])) {
536259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com            return false;
537259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com        }
538259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    }
539259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    return true;
540259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com}
541259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com
542259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com// For test_matrix_homogeneous, below.
543259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com// Maps a single triple in src using m and compares results to those in dst
544259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.comstatic bool naive_homogeneous_mapping(const SkMatrix& m, const SkScalar src[3],
545259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com                                      const SkScalar dst[3]) {
546259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    SkScalar res[3];
547259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    SkScalar ms[9] = {m[0], m[1], m[2],
548259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com                      m[3], m[4], m[5],
549259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com                      m[6], m[7], m[8]};
550259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    res[0] = src[0] * ms[0] + src[1] * ms[1] + src[2] * ms[2];
551259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    res[1] = src[0] * ms[3] + src[1] * ms[4] + src[2] * ms[5];
552259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    res[2] = src[0] * ms[6] + src[1] * ms[7] + src[2] * ms[8];
553259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    return scalar_array_nearly_equal_relative(res, dst, 3);
554259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com}
555259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com
556259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.comstatic void test_matrix_homogeneous(skiatest::Reporter* reporter) {
557259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    SkMatrix mat;
558259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com
559259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    const float kRotation0 = 15.5f;
560259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    const float kRotation1 = -50.f;
561259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    const float kScale0 = 5000.f;
562259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com
563259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    const int kTripleCount = 1000;
564259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    const int kMatrixCount = 1000;
565e0e7cfe44bb9d66d76120a79e5275c294bacaa22commit-bot@chromium.org    SkRandom rand;
566259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com
567259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    SkScalar randTriples[3*kTripleCount];
568259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    for (int i = 0; i < 3*kTripleCount; ++i) {
569259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com        randTriples[i] = rand.nextRangeF(-3000.f, 3000.f);
570259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    }
571259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com
572259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    SkMatrix mats[kMatrixCount];
573259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    for (int i = 0; i < kMatrixCount; ++i) {
574259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com        for (int j = 0; j < 9; ++j) {
575259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com            mats[i].set(j, rand.nextRangeF(-3000.f, 3000.f));
576259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com        }
577259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    }
578259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com
579259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    // identity
580259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    {
581259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    mat.reset();
582259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    SkScalar dst[3*kTripleCount];
583259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    mat.mapHomogeneousPoints(dst, randTriples, kTripleCount);
584259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    REPORTER_ASSERT(reporter, scalar_array_nearly_equal_relative(randTriples, dst, kTripleCount*3));
585259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    }
586259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com
587259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    // zero matrix
588259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    {
589259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    mat.setAll(0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
590259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    SkScalar dst[3*kTripleCount];
591259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    mat.mapHomogeneousPoints(dst, randTriples, kTripleCount);
592259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    SkScalar zeros[3] = {0.f, 0.f, 0.f};
593259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    for (int i = 0; i < kTripleCount; ++i) {
594259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com        REPORTER_ASSERT(reporter, scalar_array_nearly_equal_relative(&dst[i*3], zeros, 3));
595259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    }
596259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    }
597259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com
598259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    // zero point
599259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    {
600259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    SkScalar zeros[3] = {0.f, 0.f, 0.f};
601259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    for (int i = 0; i < kMatrixCount; ++i) {
602259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com        SkScalar dst[3];
603259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com        mats[i].mapHomogeneousPoints(dst, zeros, 1);
604259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com        REPORTER_ASSERT(reporter, scalar_array_nearly_equal_relative(dst, zeros, 3));
605259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    }
606259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    }
607259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com
608259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    // doesn't crash with null dst, src, count == 0
609259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    {
610259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    mats[0].mapHomogeneousPoints(NULL, NULL, 0);
611259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    }
612259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com
613259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    // uniform scale of point
614259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    {
615259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    mat.setScale(kScale0, kScale0);
616259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    SkScalar dst[3];
617259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    SkScalar src[3] = {randTriples[0], randTriples[1], 1.f};
618259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    SkPoint pnt;
619259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    pnt.set(src[0], src[1]);
620259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    mat.mapHomogeneousPoints(dst, src, 1);
621259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    mat.mapPoints(&pnt, &pnt, 1);
622259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[0], pnt.fX));
623259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[1], pnt.fY));
624259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[2], SK_Scalar1));
625259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    }
626259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com
627259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    // rotation of point
628259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    {
629259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    mat.setRotate(kRotation0);
630259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    SkScalar dst[3];
631259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    SkScalar src[3] = {randTriples[0], randTriples[1], 1.f};
632259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    SkPoint pnt;
633259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    pnt.set(src[0], src[1]);
634259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    mat.mapHomogeneousPoints(dst, src, 1);
635259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    mat.mapPoints(&pnt, &pnt, 1);
636259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[0], pnt.fX));
637259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[1], pnt.fY));
638259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[2], SK_Scalar1));
639259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    }
640259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com
641259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    // rotation, scale, rotation of point
642259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    {
643259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    mat.setRotate(kRotation1);
644259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    mat.postScale(kScale0, kScale0);
645259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    mat.postRotate(kRotation0);
646259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    SkScalar dst[3];
647259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    SkScalar src[3] = {randTriples[0], randTriples[1], 1.f};
648259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    SkPoint pnt;
649259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    pnt.set(src[0], src[1]);
650259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    mat.mapHomogeneousPoints(dst, src, 1);
651259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    mat.mapPoints(&pnt, &pnt, 1);
652259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[0], pnt.fX));
653259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[1], pnt.fY));
654259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[2], SK_Scalar1));
655259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    }
656259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com
657259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    // compare with naive approach
658259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    {
659259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    for (int i = 0; i < kMatrixCount; ++i) {
660259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com        for (int j = 0; j < kTripleCount; ++j) {
661259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com            SkScalar dst[3];
662259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com            mats[i].mapHomogeneousPoints(dst, &randTriples[j*3], 1);
663259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com            REPORTER_ASSERT(reporter, naive_homogeneous_mapping(mats[i], &randTriples[j*3], dst));
664259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com        }
665259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    }
666259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    }
667259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com
668259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com}
669259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com
670e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.orgDEF_TEST(Matrix, reporter) {
671ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    SkMatrix    mat, inverse, iden1, iden2;
672ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
673ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    mat.reset();
674ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    mat.setTranslate(SK_Scalar1, SK_Scalar1);
6755bfa55b1cd067fa2fe1cbe409573aeaabd98d23creed@google.com    REPORTER_ASSERT(reporter, mat.invert(&inverse));
676ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    iden1.setConcat(mat, inverse);
677ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    REPORTER_ASSERT(reporter, is_identity(iden1));
678ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
6792fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com    mat.setScale(SkIntToScalar(2), SkIntToScalar(4));
6805bfa55b1cd067fa2fe1cbe409573aeaabd98d23creed@google.com    REPORTER_ASSERT(reporter, mat.invert(&inverse));
681ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    iden1.setConcat(mat, inverse);
682ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    REPORTER_ASSERT(reporter, is_identity(iden1));
6834b7577b042966657c776fd95c67f9363af57945freed@android.com    test_flatten(reporter, mat);
684ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
6852fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com    mat.setScale(SK_Scalar1/2, SkIntToScalar(2));
6865bfa55b1cd067fa2fe1cbe409573aeaabd98d23creed@google.com    REPORTER_ASSERT(reporter, mat.invert(&inverse));
687ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    iden1.setConcat(mat, inverse);
688ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    REPORTER_ASSERT(reporter, is_identity(iden1));
6894b7577b042966657c776fd95c67f9363af57945freed@android.com    test_flatten(reporter, mat);
690ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
691ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    mat.setScale(SkIntToScalar(3), SkIntToScalar(5), SkIntToScalar(20), 0);
692ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    mat.postRotate(SkIntToScalar(25));
693ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    REPORTER_ASSERT(reporter, mat.invert(NULL));
6945bfa55b1cd067fa2fe1cbe409573aeaabd98d23creed@google.com    REPORTER_ASSERT(reporter, mat.invert(&inverse));
695ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    iden1.setConcat(mat, inverse);
696ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    REPORTER_ASSERT(reporter, is_identity(iden1));
697ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    iden2.setConcat(inverse, mat);
698ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    REPORTER_ASSERT(reporter, is_identity(iden2));
6994b7577b042966657c776fd95c67f9363af57945freed@android.com    test_flatten(reporter, mat);
7004b7577b042966657c776fd95c67f9363af57945freed@android.com    test_flatten(reporter, iden2);
70180e39a77b16f4396eed230efea1d0b2fc8cbfb00reed@android.com
7022fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com    mat.setScale(0, SK_Scalar1);
703e40591d5484762067f976d979c506f126c7779e1reed@google.com    REPORTER_ASSERT(reporter, !mat.invert(NULL));
7042fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com    REPORTER_ASSERT(reporter, !mat.invert(&inverse));
7052fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com    mat.setScale(SK_Scalar1, 0);
706e40591d5484762067f976d979c506f126c7779e1reed@google.com    REPORTER_ASSERT(reporter, !mat.invert(NULL));
7072fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com    REPORTER_ASSERT(reporter, !mat.invert(&inverse));
7082fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com
709ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    // rectStaysRect test
710ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    {
711ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com        static const struct {
712ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            SkScalar    m00, m01, m10, m11;
713ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            bool        mStaysRect;
714ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com        }
715ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com        gRectStaysRectSamples[] = {
716ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            {          0,          0,          0,           0, false },
717ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            {          0,          0,          0,  SK_Scalar1, false },
718ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            {          0,          0, SK_Scalar1,           0, false },
719ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            {          0,          0, SK_Scalar1,  SK_Scalar1, false },
720ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            {          0, SK_Scalar1,          0,           0, false },
721ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            {          0, SK_Scalar1,          0,  SK_Scalar1, false },
722ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            {          0, SK_Scalar1, SK_Scalar1,           0, true },
723ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            {          0, SK_Scalar1, SK_Scalar1,  SK_Scalar1, false },
724ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            { SK_Scalar1,          0,          0,           0, false },
725ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            { SK_Scalar1,          0,          0,  SK_Scalar1, true },
726ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            { SK_Scalar1,          0, SK_Scalar1,           0, false },
727ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            { SK_Scalar1,          0, SK_Scalar1,  SK_Scalar1, false },
728ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            { SK_Scalar1, SK_Scalar1,          0,           0, false },
729ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            { SK_Scalar1, SK_Scalar1,          0,  SK_Scalar1, false },
730ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            { SK_Scalar1, SK_Scalar1, SK_Scalar1,           0, false },
731ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            { SK_Scalar1, SK_Scalar1, SK_Scalar1,  SK_Scalar1, false }
732ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com        };
73380e39a77b16f4396eed230efea1d0b2fc8cbfb00reed@android.com
734ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com        for (size_t i = 0; i < SK_ARRAY_COUNT(gRectStaysRectSamples); i++) {
735ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            SkMatrix    m;
73680e39a77b16f4396eed230efea1d0b2fc8cbfb00reed@android.com
737ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            m.reset();
738ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            m.set(SkMatrix::kMScaleX, gRectStaysRectSamples[i].m00);
739ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            m.set(SkMatrix::kMSkewX,  gRectStaysRectSamples[i].m01);
740ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            m.set(SkMatrix::kMSkewY,  gRectStaysRectSamples[i].m10);
741ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            m.set(SkMatrix::kMScaleY, gRectStaysRectSamples[i].m11);
742ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            REPORTER_ASSERT(reporter,
743ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com                    m.rectStaysRect() == gRectStaysRectSamples[i].mStaysRect);
744ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com        }
745ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    }
7461ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com
747ba7983e55ce15ddcd5534011935178760164fb9dbungeman@google.com    mat.reset();
7481ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    mat.set(SkMatrix::kMScaleX, SkIntToScalar(1));
7491ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    mat.set(SkMatrix::kMSkewX,  SkIntToScalar(2));
7501ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    mat.set(SkMatrix::kMTransX, SkIntToScalar(3));
7511ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    mat.set(SkMatrix::kMSkewY,  SkIntToScalar(4));
7521ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    mat.set(SkMatrix::kMScaleY, SkIntToScalar(5));
7531ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    mat.set(SkMatrix::kMTransY, SkIntToScalar(6));
7541ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    SkScalar affine[6];
7551ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    REPORTER_ASSERT(reporter, mat.asAffine(affine));
7561ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com
7571ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    #define affineEqual(e) affine[SkMatrix::kA##e] == mat.get(SkMatrix::kM##e)
7581ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    REPORTER_ASSERT(reporter, affineEqual(ScaleX));
7591ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    REPORTER_ASSERT(reporter, affineEqual(SkewY));
7601ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    REPORTER_ASSERT(reporter, affineEqual(SkewX));
7611ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    REPORTER_ASSERT(reporter, affineEqual(ScaleY));
7621ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    REPORTER_ASSERT(reporter, affineEqual(TransX));
7631ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    REPORTER_ASSERT(reporter, affineEqual(TransY));
7641ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    #undef affineEqual
7651ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com
76607faed110275048c83a55ae39042da2c9d916108bungeman@google.com    mat.set(SkMatrix::kMPersp1, SkScalarToPersp(SK_Scalar1 / 2));
7671ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    REPORTER_ASSERT(reporter, !mat.asAffine(affine));
768383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com
7698fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com    SkMatrix mat2;
7708fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com    mat2.reset();
7718fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com    mat.reset();
7728fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com    SkScalar zero = 0;
7738fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com    mat.set(SkMatrix::kMSkewX, -zero);
7748fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com    REPORTER_ASSERT(reporter, are_equal(reporter, mat, mat2));
7758fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com
7768fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com    mat2.reset();
7778fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com    mat.reset();
7788fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com    mat.set(SkMatrix::kMSkewX, SK_ScalarNaN);
7798fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com    mat2.set(SkMatrix::kMSkewX, SK_ScalarNaN);
7808fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com    REPORTER_ASSERT(reporter, !are_equal(reporter, mat, mat2));
7818fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com
7821878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org    test_matrix_min_max_scale(reporter);
78346d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    test_matrix_is_similarity(reporter);
78497cd69ca23b27d88e08727366c29c1147eb564dereed@google.com    test_matrix_recttorect(reporter);
78508284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org    test_matrix_decomposition(reporter);
786259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com    test_matrix_homogeneous(reporter);
787ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com}
78899bd7d817471ec903a7fe364b4e1d4477b1372b5commit-bot@chromium.org
78999bd7d817471ec903a7fe364b4e1d4477b1372b5commit-bot@chromium.orgDEF_TEST(Matrix_Concat, r) {
79099bd7d817471ec903a7fe364b4e1d4477b1372b5commit-bot@chromium.org    SkMatrix a;
79199bd7d817471ec903a7fe364b4e1d4477b1372b5commit-bot@chromium.org    a.setTranslate(10, 20);
79299bd7d817471ec903a7fe364b4e1d4477b1372b5commit-bot@chromium.org
79399bd7d817471ec903a7fe364b4e1d4477b1372b5commit-bot@chromium.org    SkMatrix b;
79499bd7d817471ec903a7fe364b4e1d4477b1372b5commit-bot@chromium.org    b.setScale(3, 5);
79599bd7d817471ec903a7fe364b4e1d4477b1372b5commit-bot@chromium.org
79699bd7d817471ec903a7fe364b4e1d4477b1372b5commit-bot@chromium.org    SkMatrix expected;
79799bd7d817471ec903a7fe364b4e1d4477b1372b5commit-bot@chromium.org    expected.setConcat(a,b);
79899bd7d817471ec903a7fe364b4e1d4477b1372b5commit-bot@chromium.org
79999bd7d817471ec903a7fe364b4e1d4477b1372b5commit-bot@chromium.org    REPORTER_ASSERT(r, expected == SkMatrix::Concat(a, b));
80099bd7d817471ec903a7fe364b4e1d4477b1372b5commit-bot@chromium.org}
801