1 // Copyright 2017 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "core/fxcrt/fx_coordinates.h" 6 7 #include <vector> 8 9 #include "testing/gtest/include/gtest/gtest.h" 10 11 TEST(CFX_FloatRect, GetBBox) { 12 CFX_FloatRect rect = CFX_FloatRect::GetBBox(nullptr, 0); 13 EXPECT_FLOAT_EQ(0.0f, rect.left); 14 EXPECT_FLOAT_EQ(0.0f, rect.bottom); 15 EXPECT_FLOAT_EQ(0.0f, rect.right); 16 EXPECT_FLOAT_EQ(0.0f, rect.top); 17 18 std::vector<CFX_PointF> data; 19 data.emplace_back(0.0f, 0.0f); 20 rect = CFX_FloatRect::GetBBox(data.data(), 0); 21 EXPECT_FLOAT_EQ(0.0f, rect.left); 22 EXPECT_FLOAT_EQ(0.0f, rect.bottom); 23 EXPECT_FLOAT_EQ(0.0f, rect.right); 24 EXPECT_FLOAT_EQ(0.0f, rect.top); 25 rect = CFX_FloatRect::GetBBox(data.data(), data.size()); 26 EXPECT_FLOAT_EQ(0.0f, rect.left); 27 EXPECT_FLOAT_EQ(0.0f, rect.bottom); 28 EXPECT_FLOAT_EQ(0.0f, rect.right); 29 EXPECT_FLOAT_EQ(0.0f, rect.top); 30 31 data.emplace_back(2.5f, 6.2f); 32 data.emplace_back(1.5f, 6.2f); 33 rect = CFX_FloatRect::GetBBox(data.data(), 2); 34 EXPECT_FLOAT_EQ(0.0f, rect.left); 35 EXPECT_FLOAT_EQ(0.0f, rect.bottom); 36 EXPECT_FLOAT_EQ(2.5f, rect.right); 37 EXPECT_FLOAT_EQ(6.2f, rect.top); 38 39 rect = CFX_FloatRect::GetBBox(data.data(), data.size()); 40 EXPECT_FLOAT_EQ(0.0f, rect.left); 41 EXPECT_FLOAT_EQ(0.0f, rect.bottom); 42 EXPECT_FLOAT_EQ(2.5f, rect.right); 43 EXPECT_FLOAT_EQ(6.2f, rect.top); 44 45 data.emplace_back(2.5f, 6.3f); 46 rect = CFX_FloatRect::GetBBox(data.data(), data.size()); 47 EXPECT_FLOAT_EQ(0.0f, rect.left); 48 EXPECT_FLOAT_EQ(0.0f, rect.bottom); 49 EXPECT_FLOAT_EQ(2.5f, rect.right); 50 EXPECT_FLOAT_EQ(6.3f, rect.top); 51 52 data.emplace_back(-3.0f, 6.3f); 53 rect = CFX_FloatRect::GetBBox(data.data(), data.size()); 54 EXPECT_FLOAT_EQ(-3.0f, rect.left); 55 EXPECT_FLOAT_EQ(0.0f, rect.bottom); 56 EXPECT_FLOAT_EQ(2.5f, rect.right); 57 EXPECT_FLOAT_EQ(6.3f, rect.top); 58 59 data.emplace_back(4.0f, -8.0f); 60 rect = CFX_FloatRect::GetBBox(data.data(), data.size()); 61 EXPECT_FLOAT_EQ(-3.0f, rect.left); 62 EXPECT_FLOAT_EQ(-8.0f, rect.bottom); 63 EXPECT_FLOAT_EQ(4.0f, rect.right); 64 EXPECT_FLOAT_EQ(6.3f, rect.top); 65 } 66 67 TEST(CFX_FloatRect, Normalize) { 68 CFX_FloatRect rect; 69 rect.Normalize(); 70 EXPECT_FLOAT_EQ(0.0f, rect.left); 71 EXPECT_FLOAT_EQ(0.0f, rect.bottom); 72 EXPECT_FLOAT_EQ(0.0f, rect.right); 73 EXPECT_FLOAT_EQ(0.0f, rect.top); 74 75 rect = CFX_FloatRect(-1.0f, -3.0f, 4.5f, 3.2f); 76 rect.Normalize(); 77 EXPECT_FLOAT_EQ(-1.0f, rect.left); 78 EXPECT_FLOAT_EQ(-3.0f, rect.bottom); 79 EXPECT_FLOAT_EQ(4.5f, rect.right); 80 EXPECT_FLOAT_EQ(3.2f, rect.top); 81 rect.Scale(-1.0f); 82 rect.Normalize(); 83 EXPECT_FLOAT_EQ(-4.5f, rect.left); 84 EXPECT_FLOAT_EQ(-3.2f, rect.bottom); 85 EXPECT_FLOAT_EQ(1.0f, rect.right); 86 EXPECT_FLOAT_EQ(3.0f, rect.top); 87 } 88 89 TEST(CFX_FloatRect, Scale) { 90 CFX_FloatRect rect(-1.0f, -3.0f, 4.5f, 3.2f); 91 rect.Scale(1.0f); 92 EXPECT_FLOAT_EQ(-1.0f, rect.left); 93 EXPECT_FLOAT_EQ(-3.0f, rect.bottom); 94 EXPECT_FLOAT_EQ(4.5f, rect.right); 95 EXPECT_FLOAT_EQ(3.2f, rect.top); 96 rect.Scale(0.5f); 97 EXPECT_FLOAT_EQ(-0.5, rect.left); 98 EXPECT_FLOAT_EQ(-1.5, rect.bottom); 99 EXPECT_FLOAT_EQ(2.25f, rect.right); 100 EXPECT_FLOAT_EQ(1.6f, rect.top); 101 rect.Scale(2.0f); 102 EXPECT_FLOAT_EQ(-1.0f, rect.left); 103 EXPECT_FLOAT_EQ(-3.0f, rect.bottom); 104 EXPECT_FLOAT_EQ(4.5f, rect.right); 105 EXPECT_FLOAT_EQ(3.2f, rect.top); 106 rect.Scale(-1.0f); 107 EXPECT_FLOAT_EQ(1.0f, rect.left); 108 EXPECT_FLOAT_EQ(3.0f, rect.bottom); 109 EXPECT_FLOAT_EQ(-4.5f, rect.right); 110 EXPECT_FLOAT_EQ(-3.2f, rect.top); 111 rect.Scale(0.0f); 112 EXPECT_FLOAT_EQ(0.0f, rect.left); 113 EXPECT_FLOAT_EQ(0.0f, rect.bottom); 114 EXPECT_FLOAT_EQ(0.0f, rect.right); 115 EXPECT_FLOAT_EQ(0.0f, rect.top); 116 } 117 118 TEST(CFX_FloatRect, ScaleEmpty) { 119 CFX_FloatRect rect; 120 rect.Scale(1.0f); 121 EXPECT_FLOAT_EQ(0.0f, rect.left); 122 EXPECT_FLOAT_EQ(0.0f, rect.bottom); 123 EXPECT_FLOAT_EQ(0.0f, rect.right); 124 EXPECT_FLOAT_EQ(0.0f, rect.top); 125 rect.Scale(0.5f); 126 EXPECT_FLOAT_EQ(0.0f, rect.left); 127 EXPECT_FLOAT_EQ(0.0f, rect.bottom); 128 EXPECT_FLOAT_EQ(0.0f, rect.right); 129 EXPECT_FLOAT_EQ(0.0f, rect.top); 130 rect.Scale(2.0f); 131 EXPECT_FLOAT_EQ(0.0f, rect.left); 132 EXPECT_FLOAT_EQ(0.0f, rect.bottom); 133 EXPECT_FLOAT_EQ(0.0f, rect.right); 134 EXPECT_FLOAT_EQ(0.0f, rect.top); 135 rect.Scale(0.0f); 136 EXPECT_FLOAT_EQ(0.0f, rect.left); 137 EXPECT_FLOAT_EQ(0.0f, rect.bottom); 138 EXPECT_FLOAT_EQ(0.0f, rect.right); 139 EXPECT_FLOAT_EQ(0.0f, rect.top); 140 } 141 142 TEST(CFX_FloatRect, ScaleFromCenterPoint) { 143 CFX_FloatRect rect(-1.0f, -3.0f, 4.5f, 3.2f); 144 rect.ScaleFromCenterPoint(1.0f); 145 EXPECT_FLOAT_EQ(-1.0f, rect.left); 146 EXPECT_FLOAT_EQ(-3.0f, rect.bottom); 147 EXPECT_FLOAT_EQ(4.5f, rect.right); 148 EXPECT_FLOAT_EQ(3.2f, rect.top); 149 rect.ScaleFromCenterPoint(0.5f); 150 EXPECT_FLOAT_EQ(0.375f, rect.left); 151 EXPECT_FLOAT_EQ(-1.45f, rect.bottom); 152 EXPECT_FLOAT_EQ(3.125f, rect.right); 153 EXPECT_FLOAT_EQ(1.65f, rect.top); 154 rect.ScaleFromCenterPoint(2.0f); 155 EXPECT_FLOAT_EQ(-1.0f, rect.left); 156 EXPECT_FLOAT_EQ(-3.0f, rect.bottom); 157 EXPECT_FLOAT_EQ(4.5f, rect.right); 158 EXPECT_FLOAT_EQ(3.2f, rect.top); 159 rect.ScaleFromCenterPoint(-1.0f); 160 EXPECT_FLOAT_EQ(4.5f, rect.left); 161 EXPECT_FLOAT_EQ(3.2f, rect.bottom); 162 EXPECT_FLOAT_EQ(-1.0f, rect.right); 163 EXPECT_FLOAT_EQ(-3.0f, rect.top); 164 rect.ScaleFromCenterPoint(0.0f); 165 EXPECT_FLOAT_EQ(1.75f, rect.left); 166 EXPECT_NEAR(0.1f, rect.bottom, 0.001f); 167 EXPECT_FLOAT_EQ(1.75f, rect.right); 168 EXPECT_NEAR(0.1f, rect.top, 0.001f); 169 } 170 171 TEST(CFX_FloatRect, ScaleFromCenterPointEmpty) { 172 CFX_FloatRect rect; 173 rect.ScaleFromCenterPoint(1.0f); 174 EXPECT_FLOAT_EQ(0.0f, rect.left); 175 EXPECT_FLOAT_EQ(0.0f, rect.bottom); 176 EXPECT_FLOAT_EQ(0.0f, rect.right); 177 EXPECT_FLOAT_EQ(0.0f, rect.top); 178 rect.ScaleFromCenterPoint(0.5f); 179 EXPECT_FLOAT_EQ(0.0f, rect.left); 180 EXPECT_FLOAT_EQ(0.0f, rect.bottom); 181 EXPECT_FLOAT_EQ(0.0f, rect.right); 182 EXPECT_FLOAT_EQ(0.0f, rect.top); 183 rect.ScaleFromCenterPoint(2.0f); 184 EXPECT_FLOAT_EQ(0.0f, rect.left); 185 EXPECT_FLOAT_EQ(0.0f, rect.bottom); 186 EXPECT_FLOAT_EQ(0.0f, rect.right); 187 EXPECT_FLOAT_EQ(0.0f, rect.top); 188 rect.ScaleFromCenterPoint(0.0f); 189 EXPECT_FLOAT_EQ(0.0f, rect.left); 190 EXPECT_FLOAT_EQ(0.0f, rect.bottom); 191 EXPECT_FLOAT_EQ(0.0f, rect.right); 192 EXPECT_FLOAT_EQ(0.0f, rect.top); 193 } 194 195 #ifndef NDEBUG 196 TEST(CFX_FloatRect, Print) { 197 std::ostringstream os; 198 CFX_FloatRect rect; 199 os << rect; 200 EXPECT_STREQ("rect[0x0 (0, 0)]", os.str().c_str()); 201 202 os.str(""); 203 rect = CFX_FloatRect(10, 20, 14, 23); 204 os << rect; 205 EXPECT_STREQ("rect[4x3 (10, 20)]", os.str().c_str()); 206 207 os.str(""); 208 rect = CFX_FloatRect(10.5, 20.5, 14.75, 23.75); 209 os << rect; 210 EXPECT_STREQ("rect[4.25x3.25 (10.5, 20.5)]", os.str().c_str()); 211 } 212 #endif 213 214 TEST(CFX_Matrix, ReverseIdentity) { 215 CFX_Matrix m; 216 m.SetIdentity(); 217 CFX_Matrix rev = m.GetInverse(); 218 219 EXPECT_FLOAT_EQ(1.0, rev.a); 220 EXPECT_FLOAT_EQ(0.0, rev.b); 221 EXPECT_FLOAT_EQ(0.0, rev.c); 222 EXPECT_FLOAT_EQ(1.0, rev.d); 223 EXPECT_FLOAT_EQ(0.0, rev.e); 224 EXPECT_FLOAT_EQ(0.0, rev.f); 225 226 CFX_PointF expected(2, 3); 227 CFX_PointF result = rev.Transform(m.Transform(CFX_PointF(2, 3))); 228 EXPECT_FLOAT_EQ(expected.x, result.x); 229 EXPECT_FLOAT_EQ(expected.y, result.y); 230 } 231 232 TEST(CFX_Matrix, Reverse) { 233 static constexpr float data[6] = {3, 0, 2, 3, 1, 4}; 234 CFX_Matrix m(data); 235 CFX_Matrix rev = m.GetInverse(); 236 237 EXPECT_FLOAT_EQ(0.33333334f, rev.a); 238 EXPECT_FLOAT_EQ(0.0f, rev.b); 239 EXPECT_FLOAT_EQ(-0.22222222f, rev.c); 240 EXPECT_FLOAT_EQ(0.33333334f, rev.d); 241 EXPECT_FLOAT_EQ(0.55555556f, rev.e); 242 EXPECT_FLOAT_EQ(-1.3333334f, rev.f); 243 244 CFX_PointF expected(2, 3); 245 CFX_PointF result = rev.Transform(m.Transform(CFX_PointF(2, 3))); 246 EXPECT_FLOAT_EQ(expected.x, result.x); 247 EXPECT_FLOAT_EQ(expected.y, result.y); 248 } 249 250 // Note, I think these are a bug and the matrix should be the identity. 251 TEST(CFX_Matrix, ReverseCR702041) { 252 // The determinate is < std::numeric_limits<float>::epsilon() 253 static constexpr float data[6] = {0.947368443f, -0.108947366f, -0.923076928f, 254 0.106153846f, 18.0f, 787.929993f}; 255 CFX_Matrix m(data); 256 CFX_Matrix rev = m.GetInverse(); 257 258 EXPECT_FLOAT_EQ(14247728.0f, rev.a); 259 EXPECT_FLOAT_EQ(14622668.0f, rev.b); 260 EXPECT_FLOAT_EQ(1.2389329e+08f, rev.c); 261 EXPECT_FLOAT_EQ(1.2715364e+08f, rev.d); 262 EXPECT_FLOAT_EQ(-9.7875698e+10f, rev.e); 263 EXPECT_FLOAT_EQ(-1.0045138e+11f, rev.f); 264 265 // Should be 2, 3 266 CFX_PointF expected(0, 0); 267 CFX_PointF result = rev.Transform(m.Transform(CFX_PointF(2, 3))); 268 EXPECT_FLOAT_EQ(expected.x, result.x); 269 EXPECT_FLOAT_EQ(expected.y, result.y); 270 } 271 272 TEST(CFX_Matrix, ReverseCR714187) { 273 // The determinate is < std::numeric_limits<float>::epsilon() 274 static constexpr float data[6] = {0.000037f, 0.0f, 0.0f, 275 -0.000037f, 182.413101f, 136.977646f}; 276 CFX_Matrix m(data); 277 CFX_Matrix rev = m.GetInverse(); 278 279 EXPECT_FLOAT_EQ(27027.025f, rev.a); 280 EXPECT_FLOAT_EQ(0.0f, rev.b); 281 EXPECT_FLOAT_EQ(0.0f, rev.c); 282 EXPECT_FLOAT_EQ(-27027.025f, rev.d); 283 EXPECT_FLOAT_EQ(-4930083.5f, rev.e); 284 EXPECT_FLOAT_EQ(3702098.2f, rev.f); 285 286 // Should be 3 .... 287 CFX_PointF expected(2, 2.75); 288 CFX_PointF result = rev.Transform(m.Transform(CFX_PointF(2, 3))); 289 EXPECT_FLOAT_EQ(expected.x, result.x); 290 EXPECT_FLOAT_EQ(expected.y, result.y); 291 } 292