MatrixTest.cpp revision ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976e
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
8ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com#include "Test.h"
9ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com#include "SkMatrix.h"
10ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
11ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.comstatic bool nearly_equal_scalar(SkScalar a, SkScalar b) {
122047f00e4698f83499ab91911999a65c21a951c9epoger@google.com    // Note that we get more compounded error for multiple operations when
132047f00e4698f83499ab91911999a65c21a951c9epoger@google.com    // SK_SCALAR_IS_FIXED.
14ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com#ifdef SK_SCALAR_IS_FLOAT
152047f00e4698f83499ab91911999a65c21a951c9epoger@google.com    const SkScalar tolerance = SK_Scalar1 / 200000;
16ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com#else
172047f00e4698f83499ab91911999a65c21a951c9epoger@google.com    const SkScalar tolerance = SK_Scalar1 / 1024;
18ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com#endif
19ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
20ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    return SkScalarAbs(a - b) <= tolerance;
21ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com}
22ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
23ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.comstatic bool nearly_equal(const SkMatrix& a, const SkMatrix& b) {
24ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    for (int i = 0; i < 9; i++) {
25ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com        if (!nearly_equal_scalar(a[i], b[i])) {
26d41344553163085bfcfaf7d5882c6028934f8e3breed@android.com            printf("not equal %g %g\n", (float)a[i], (float)b[i]);
27ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            return false;
28ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com        }
29ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    }
30ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    return true;
31ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com}
32ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
33ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.comstatic bool is_identity(const SkMatrix& m) {
34ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    SkMatrix identity;
3580e39a77b16f4396eed230efea1d0b2fc8cbfb00reed@android.com    identity.reset();
36ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    return nearly_equal(m, identity);
37ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com}
38ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
394b7577b042966657c776fd95c67f9363af57945freed@android.comstatic void test_flatten(skiatest::Reporter* reporter, const SkMatrix& m) {
404b7577b042966657c776fd95c67f9363af57945freed@android.com    // add 100 in case we have a bug, I don't want to kill my stack in the test
414b7577b042966657c776fd95c67f9363af57945freed@android.com    char buffer[SkMatrix::kMaxFlattenSize + 100];
424b7577b042966657c776fd95c67f9363af57945freed@android.com    uint32_t size1 = m.flatten(NULL);
434b7577b042966657c776fd95c67f9363af57945freed@android.com    uint32_t size2 = m.flatten(buffer);
444b7577b042966657c776fd95c67f9363af57945freed@android.com    REPORTER_ASSERT(reporter, size1 == size2);
454b7577b042966657c776fd95c67f9363af57945freed@android.com    REPORTER_ASSERT(reporter, size1 <= SkMatrix::kMaxFlattenSize);
464b7577b042966657c776fd95c67f9363af57945freed@android.com
474b7577b042966657c776fd95c67f9363af57945freed@android.com    SkMatrix m2;
484b7577b042966657c776fd95c67f9363af57945freed@android.com    uint32_t size3 = m2.unflatten(buffer);
494b7577b042966657c776fd95c67f9363af57945freed@android.com    REPORTER_ASSERT(reporter, size1 == size2);
504b7577b042966657c776fd95c67f9363af57945freed@android.com    REPORTER_ASSERT(reporter, m == m2);
514b7577b042966657c776fd95c67f9363af57945freed@android.com
524b7577b042966657c776fd95c67f9363af57945freed@android.com    char buffer2[SkMatrix::kMaxFlattenSize + 100];
534b7577b042966657c776fd95c67f9363af57945freed@android.com    size3 = m2.flatten(buffer2);
544b7577b042966657c776fd95c67f9363af57945freed@android.com    REPORTER_ASSERT(reporter, size1 == size2);
554b7577b042966657c776fd95c67f9363af57945freed@android.com    REPORTER_ASSERT(reporter, memcmp(buffer, buffer2, size1) == 0);
564b7577b042966657c776fd95c67f9363af57945freed@android.com}
574b7577b042966657c776fd95c67f9363af57945freed@android.com
58ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.comvoid TestMatrix(skiatest::Reporter* reporter) {
59ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    SkMatrix    mat, inverse, iden1, iden2;
60ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
61ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    mat.reset();
62ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    mat.setTranslate(SK_Scalar1, SK_Scalar1);
63ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    mat.invert(&inverse);
64ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    iden1.setConcat(mat, inverse);
65ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    REPORTER_ASSERT(reporter, is_identity(iden1));
66ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
67ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    mat.setScale(SkIntToScalar(2), SkIntToScalar(2));
68ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    mat.invert(&inverse);
69ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    iden1.setConcat(mat, inverse);
70ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    REPORTER_ASSERT(reporter, is_identity(iden1));
714b7577b042966657c776fd95c67f9363af57945freed@android.com    test_flatten(reporter, mat);
72ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
73ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    mat.setScale(SK_Scalar1/2, SK_Scalar1/2);
74ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    mat.invert(&inverse);
75ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    iden1.setConcat(mat, inverse);
76ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    REPORTER_ASSERT(reporter, is_identity(iden1));
774b7577b042966657c776fd95c67f9363af57945freed@android.com    test_flatten(reporter, mat);
78ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
79ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    mat.setScale(SkIntToScalar(3), SkIntToScalar(5), SkIntToScalar(20), 0);
80ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    mat.postRotate(SkIntToScalar(25));
81ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    REPORTER_ASSERT(reporter, mat.invert(NULL));
82ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    mat.invert(&inverse);
83ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    iden1.setConcat(mat, inverse);
84ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    REPORTER_ASSERT(reporter, is_identity(iden1));
85ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    iden2.setConcat(inverse, mat);
86ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    REPORTER_ASSERT(reporter, is_identity(iden2));
874b7577b042966657c776fd95c67f9363af57945freed@android.com    test_flatten(reporter, mat);
884b7577b042966657c776fd95c67f9363af57945freed@android.com    test_flatten(reporter, iden2);
8980e39a77b16f4396eed230efea1d0b2fc8cbfb00reed@android.com
90ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    // rectStaysRect test
91ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    {
92ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com        static const struct {
93ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            SkScalar    m00, m01, m10, m11;
94ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            bool        mStaysRect;
95ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com        }
96ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com        gRectStaysRectSamples[] = {
97ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            {          0,          0,          0,           0, false },
98ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            {          0,          0,          0,  SK_Scalar1, false },
99ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            {          0,          0, SK_Scalar1,           0, false },
100ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            {          0,          0, SK_Scalar1,  SK_Scalar1, false },
101ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            {          0, SK_Scalar1,          0,           0, false },
102ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            {          0, SK_Scalar1,          0,  SK_Scalar1, false },
103ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            {          0, SK_Scalar1, SK_Scalar1,           0, true },
104ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            {          0, SK_Scalar1, SK_Scalar1,  SK_Scalar1, false },
105ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            { SK_Scalar1,          0,          0,           0, false },
106ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            { SK_Scalar1,          0,          0,  SK_Scalar1, true },
107ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            { SK_Scalar1,          0, SK_Scalar1,           0, false },
108ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            { SK_Scalar1,          0, SK_Scalar1,  SK_Scalar1, false },
109ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            { SK_Scalar1, SK_Scalar1,          0,           0, false },
110ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            { SK_Scalar1, SK_Scalar1,          0,  SK_Scalar1, false },
111ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            { SK_Scalar1, SK_Scalar1, SK_Scalar1,           0, false },
112ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            { SK_Scalar1, SK_Scalar1, SK_Scalar1,  SK_Scalar1, false }
113ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com        };
11480e39a77b16f4396eed230efea1d0b2fc8cbfb00reed@android.com
115ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com        for (size_t i = 0; i < SK_ARRAY_COUNT(gRectStaysRectSamples); i++) {
116ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            SkMatrix    m;
11780e39a77b16f4396eed230efea1d0b2fc8cbfb00reed@android.com
118ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            m.reset();
119ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            m.set(SkMatrix::kMScaleX, gRectStaysRectSamples[i].m00);
120ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            m.set(SkMatrix::kMSkewX,  gRectStaysRectSamples[i].m01);
121ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            m.set(SkMatrix::kMSkewY,  gRectStaysRectSamples[i].m10);
122ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            m.set(SkMatrix::kMScaleY, gRectStaysRectSamples[i].m11);
123ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com            REPORTER_ASSERT(reporter,
124ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com                    m.rectStaysRect() == gRectStaysRectSamples[i].mStaysRect);
125ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com        }
126ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com    }
1271ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com
128ba7983e55ce15ddcd5534011935178760164fb9dbungeman@google.com    mat.reset();
1291ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    mat.set(SkMatrix::kMScaleX, SkIntToScalar(1));
1301ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    mat.set(SkMatrix::kMSkewX,  SkIntToScalar(2));
1311ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    mat.set(SkMatrix::kMTransX, SkIntToScalar(3));
1321ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    mat.set(SkMatrix::kMSkewY,  SkIntToScalar(4));
1331ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    mat.set(SkMatrix::kMScaleY, SkIntToScalar(5));
1341ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    mat.set(SkMatrix::kMTransY, SkIntToScalar(6));
1351ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    SkScalar affine[6];
1361ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    REPORTER_ASSERT(reporter, mat.asAffine(affine));
1371ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com
1381ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    #define affineEqual(e) affine[SkMatrix::kA##e] == mat.get(SkMatrix::kM##e)
1391ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    REPORTER_ASSERT(reporter, affineEqual(ScaleX));
1401ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    REPORTER_ASSERT(reporter, affineEqual(SkewY));
1411ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    REPORTER_ASSERT(reporter, affineEqual(SkewX));
1421ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    REPORTER_ASSERT(reporter, affineEqual(ScaleY));
1431ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    REPORTER_ASSERT(reporter, affineEqual(TransX));
1441ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    REPORTER_ASSERT(reporter, affineEqual(TransY));
1451ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    #undef affineEqual
1461ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com
1471ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    mat.set(SkMatrix::kMPersp1, SkIntToScalar(1));
1481ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com    REPORTER_ASSERT(reporter, !mat.asAffine(affine));
149ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com}
150ed673310e2551e64d8196f7776d7d4c92085f8c2reed@android.com
151d8730ea8b25d692c0656f8cf03f02aecfab2a17creed@android.com#include "TestClassDef.h"
152d8730ea8b25d692c0656f8cf03f02aecfab2a17creed@android.comDEFINE_TESTCLASS("Matrix", MatrixTestClass, TestMatrix)
153