matrix_decomposition_unittests.cc 5.1 KB
Newer Older
M
Michael Goderbauer 已提交
1
// Copyright 2013 The Flutter Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
#include "flutter/fml/build_config.h"
6 7 8 9 10 11

#if defined(OS_WIN)
#define _USE_MATH_DEFINES
#endif
#include <cmath>

12
#include "flutter/flow/matrix_decomposition.h"
13
#include "gtest/gtest.h"
14 15 16 17 18 19 20

TEST(MatrixDecomposition, Rotation) {
  SkMatrix44 matrix = SkMatrix44::I();

  const auto angle = M_PI_4;
  matrix.setRotateAbout(0.0, 0.0, 1.0, angle);

21
  flutter::MatrixDecomposition decomposition(matrix);
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
  ASSERT_TRUE(decomposition.IsValid());

  const auto sine = sin(angle * 0.5);

  ASSERT_FLOAT_EQ(0, decomposition.rotation().fData[0]);
  ASSERT_FLOAT_EQ(0, decomposition.rotation().fData[1]);
  ASSERT_FLOAT_EQ(sine, decomposition.rotation().fData[2]);
  ASSERT_FLOAT_EQ(cos(angle * 0.5), decomposition.rotation().fData[3]);
}

TEST(MatrixDecomposition, Scale) {
  SkMatrix44 matrix = SkMatrix44::I();

  const auto scale = 5.0;
  matrix.setScale(scale + 0, scale + 1, scale + 2);

38
  flutter::MatrixDecomposition decomposition(matrix);
39 40 41 42 43 44 45 46 47 48 49 50 51
  ASSERT_TRUE(decomposition.IsValid());

  ASSERT_FLOAT_EQ(scale + 0, decomposition.scale().fX);
  ASSERT_FLOAT_EQ(scale + 1, decomposition.scale().fY);
  ASSERT_FLOAT_EQ(scale + 2, decomposition.scale().fZ);
}

TEST(MatrixDecomposition, Translate) {
  SkMatrix44 matrix = SkMatrix44::I();

  const auto translate = 125.0;
  matrix.setTranslate(translate + 0, translate + 1, translate + 2);

52
  flutter::MatrixDecomposition decomposition(matrix);
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
  ASSERT_TRUE(decomposition.IsValid());

  ASSERT_FLOAT_EQ(translate + 0, decomposition.translation().fX);
  ASSERT_FLOAT_EQ(translate + 1, decomposition.translation().fY);
  ASSERT_FLOAT_EQ(translate + 2, decomposition.translation().fZ);
}

TEST(MatrixDecomposition, Combination) {
  const auto rotation = M_PI_4;
  const auto scale = 5;
  const auto translate = 125.0;

  SkMatrix44 m1 = SkMatrix44::I();
  m1.setRotateAbout(0, 0, 1, rotation);

  SkMatrix44 m2 = SkMatrix44::I();
  m2.setScale(scale);

  SkMatrix44 m3 = SkMatrix44::I();
  m3.setTranslate(translate, translate, translate);

  SkMatrix44 combined = m3 * m2 * m1;

76
  flutter::MatrixDecomposition decomposition(combined);
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
  ASSERT_TRUE(decomposition.IsValid());

  ASSERT_FLOAT_EQ(translate, decomposition.translation().fX);
  ASSERT_FLOAT_EQ(translate, decomposition.translation().fY);
  ASSERT_FLOAT_EQ(translate, decomposition.translation().fZ);

  ASSERT_FLOAT_EQ(scale, decomposition.scale().fX);
  ASSERT_FLOAT_EQ(scale, decomposition.scale().fY);
  ASSERT_FLOAT_EQ(scale, decomposition.scale().fZ);

  const auto sine = sin(rotation * 0.5);

  ASSERT_FLOAT_EQ(0, decomposition.rotation().fData[0]);
  ASSERT_FLOAT_EQ(0, decomposition.rotation().fData[1]);
  ASSERT_FLOAT_EQ(sine, decomposition.rotation().fData[2]);
  ASSERT_FLOAT_EQ(cos(rotation * 0.5), decomposition.rotation().fData[3]);
}
94

95
TEST(MatrixDecomposition, ScaleFloatError) {
96
  for (float scale = 0.0001f; scale < 2.0f; scale += 0.000001f) {
97 98 99
    SkMatrix44 matrix = SkMatrix44::I();
    matrix.setScale(scale, scale, 1.0f);

100
    flutter::MatrixDecomposition decomposition3(matrix);
101 102 103 104 105 106 107 108 109
    ASSERT_TRUE(decomposition3.IsValid());

    ASSERT_FLOAT_EQ(scale, decomposition3.scale().fX);
    ASSERT_FLOAT_EQ(scale, decomposition3.scale().fY);
    ASSERT_FLOAT_EQ(1.f, decomposition3.scale().fZ);
    ASSERT_FLOAT_EQ(0, decomposition3.rotation().fData[0]);
    ASSERT_FLOAT_EQ(0, decomposition3.rotation().fData[1]);
    ASSERT_FLOAT_EQ(0, decomposition3.rotation().fData[2]);
  }
110

111
  SkMatrix44 matrix = SkMatrix44::I();
112 113 114
  const auto scale = 1.7734375f;
  matrix.setScale(scale, scale, 1.f);

115 116 117 118 119 120 121 122 123 124
  // Bug upper bound (empirical)
  const auto scale2 = 1.773437559603f;
  SkMatrix44 matrix2 = SkMatrix44::I();
  matrix2.setScale(scale2, scale2, 1.f);

  // Bug lower bound (empirical)
  const auto scale3 = 1.7734374403954f;
  SkMatrix44 matrix3 = SkMatrix44::I();
  matrix3.setScale(scale3, scale3, 1.f);

125
  flutter::MatrixDecomposition decomposition(matrix);
126 127
  ASSERT_TRUE(decomposition.IsValid());

128
  flutter::MatrixDecomposition decomposition2(matrix2);
129 130
  ASSERT_TRUE(decomposition2.IsValid());

131
  flutter::MatrixDecomposition decomposition3(matrix3);
132 133
  ASSERT_TRUE(decomposition3.IsValid());

134 135 136 137 138 139
  ASSERT_FLOAT_EQ(scale, decomposition.scale().fX);
  ASSERT_FLOAT_EQ(scale, decomposition.scale().fY);
  ASSERT_FLOAT_EQ(1.f, decomposition.scale().fZ);
  ASSERT_FLOAT_EQ(0, decomposition.rotation().fData[0]);
  ASSERT_FLOAT_EQ(0, decomposition.rotation().fData[1]);
  ASSERT_FLOAT_EQ(0, decomposition.rotation().fData[2]);
140 141 142 143 144 145 146 147 148 149 150 151 152 153

  ASSERT_FLOAT_EQ(scale2, decomposition2.scale().fX);
  ASSERT_FLOAT_EQ(scale2, decomposition2.scale().fY);
  ASSERT_FLOAT_EQ(1.f, decomposition2.scale().fZ);
  ASSERT_FLOAT_EQ(0, decomposition2.rotation().fData[0]);
  ASSERT_FLOAT_EQ(0, decomposition2.rotation().fData[1]);
  ASSERT_FLOAT_EQ(0, decomposition2.rotation().fData[2]);

  ASSERT_FLOAT_EQ(scale3, decomposition3.scale().fX);
  ASSERT_FLOAT_EQ(scale3, decomposition3.scale().fY);
  ASSERT_FLOAT_EQ(1.f, decomposition3.scale().fZ);
  ASSERT_FLOAT_EQ(0, decomposition3.rotation().fData[0]);
  ASSERT_FLOAT_EQ(0, decomposition3.rotation().fData[1]);
  ASSERT_FLOAT_EQ(0, decomposition3.rotation().fData[2]);
154
}