Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
fx_coordinates_unittest.cpp
Go to the documentation of this file.
1// Copyright 2017 The PDFium Authors
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 <limits>
8#include <vector>
9
10#include "core/fxcrt/fx_coordinates_test_support.h"
11#include "core/fxcrt/fx_system.h"
12#include "testing/gtest/include/gtest/gtest.h"
13
14namespace {
15
16constexpr float kMinFloat = std::numeric_limits<float>::min();
17constexpr int kMaxInt = std::numeric_limits<int>::max();
18constexpr int kMinInt = std::numeric_limits<int>::min();
19constexpr float kMinIntAsFloat = static_cast<float>(kMinInt);
20constexpr float kMaxIntAsFloat = static_cast<float>(kMaxInt);
21
22} // namespace
23
25 FX_RECT downwards(10, 20, 30, 40);
26 CFX_FloatRect rect(downwards);
27 EXPECT_FLOAT_EQ(rect.left, 10.0f);
28 EXPECT_FLOAT_EQ(rect.bottom, 20.0f);
29 EXPECT_FLOAT_EQ(rect.right, 30.0f);
30 EXPECT_FLOAT_EQ(rect.top, 40.0f);
31}
32
34 CFX_FloatRect rect = CFX_FloatRect::GetBBox({});
35 EXPECT_FLOAT_EQ(0.0f, rect.left);
36 EXPECT_FLOAT_EQ(0.0f, rect.bottom);
37 EXPECT_FLOAT_EQ(0.0f, rect.right);
38 EXPECT_FLOAT_EQ(0.0f, rect.top);
39
40 std::vector<CFX_PointF> data;
41 data.emplace_back(0.0f, 0.0f);
42 rect = CFX_FloatRect::GetBBox(pdfium::make_span(data).first(0));
43 EXPECT_FLOAT_EQ(0.0f, rect.left);
44 EXPECT_FLOAT_EQ(0.0f, rect.bottom);
45 EXPECT_FLOAT_EQ(0.0f, rect.right);
46 EXPECT_FLOAT_EQ(0.0f, rect.top);
47 rect = CFX_FloatRect::GetBBox(data);
48 EXPECT_FLOAT_EQ(0.0f, rect.left);
49 EXPECT_FLOAT_EQ(0.0f, rect.bottom);
50 EXPECT_FLOAT_EQ(0.0f, rect.right);
51 EXPECT_FLOAT_EQ(0.0f, rect.top);
52
53 data.emplace_back(2.5f, 6.2f);
54 data.emplace_back(1.5f, 6.2f);
55 rect = CFX_FloatRect::GetBBox(pdfium::make_span(data).first(2));
56 EXPECT_FLOAT_EQ(0.0f, rect.left);
57 EXPECT_FLOAT_EQ(0.0f, rect.bottom);
58 EXPECT_FLOAT_EQ(2.5f, rect.right);
59 EXPECT_FLOAT_EQ(6.2f, rect.top);
60
61 rect = CFX_FloatRect::GetBBox(data);
62 EXPECT_FLOAT_EQ(0.0f, rect.left);
63 EXPECT_FLOAT_EQ(0.0f, rect.bottom);
64 EXPECT_FLOAT_EQ(2.5f, rect.right);
65 EXPECT_FLOAT_EQ(6.2f, rect.top);
66
67 data.emplace_back(2.5f, 6.3f);
68 rect = CFX_FloatRect::GetBBox(data);
69 EXPECT_FLOAT_EQ(0.0f, rect.left);
70 EXPECT_FLOAT_EQ(0.0f, rect.bottom);
71 EXPECT_FLOAT_EQ(2.5f, rect.right);
72 EXPECT_FLOAT_EQ(6.3f, rect.top);
73
74 data.emplace_back(-3.0f, 6.3f);
75 rect = CFX_FloatRect::GetBBox(data);
76 EXPECT_FLOAT_EQ(-3.0f, rect.left);
77 EXPECT_FLOAT_EQ(0.0f, rect.bottom);
78 EXPECT_FLOAT_EQ(2.5f, rect.right);
79 EXPECT_FLOAT_EQ(6.3f, rect.top);
80
81 data.emplace_back(4.0f, -8.0f);
82 rect = CFX_FloatRect::GetBBox(data);
83 EXPECT_FLOAT_EQ(-3.0f, rect.left);
84 EXPECT_FLOAT_EQ(-8.0f, rect.bottom);
85 EXPECT_FLOAT_EQ(4.0f, rect.right);
86 EXPECT_FLOAT_EQ(6.3f, rect.top);
87}
88
90 FX_RECT inner_rect;
91 CFX_FloatRect rect;
92
93 inner_rect = rect.GetInnerRect();
94 EXPECT_EQ(0, inner_rect.left);
95 EXPECT_EQ(0, inner_rect.bottom);
96 EXPECT_EQ(0, inner_rect.right);
97 EXPECT_EQ(0, inner_rect.top);
98
99 // Function converts from float to int using floor() for top and right, and
100 // ceil() for left and bottom.
101 rect = CFX_FloatRect(-1.1f, 3.6f, 4.4f, -5.7f);
102 inner_rect = rect.GetInnerRect();
103 EXPECT_EQ(-1, inner_rect.left);
104 EXPECT_EQ(4, inner_rect.bottom);
105 EXPECT_EQ(4, inner_rect.right);
106 EXPECT_EQ(-6, inner_rect.top);
107
108 rect = CFX_FloatRect(kMinFloat, kMinFloat, kMinFloat, kMinFloat);
109 inner_rect = rect.GetInnerRect();
110 EXPECT_EQ(0, inner_rect.left);
111 EXPECT_EQ(1, inner_rect.bottom);
112 EXPECT_EQ(1, inner_rect.right);
113 EXPECT_EQ(0, inner_rect.top);
114
115 rect = CFX_FloatRect(-kMinFloat, -kMinFloat, -kMinFloat, -kMinFloat);
116 inner_rect = rect.GetInnerRect();
117 EXPECT_EQ(-1, inner_rect.left);
118 EXPECT_EQ(0, inner_rect.bottom);
119 EXPECT_EQ(0, inner_rect.right);
120 EXPECT_EQ(-1, inner_rect.top);
121
122 // Check at limits of integer range. When saturated would expect to get values
123 // that are clamped to the limits of integers, but instead it is returning all
124 // negative values that represent a rectangle as a dot in a far reach of the
125 // negative coordinate space. Related to crbug.com/1019026
126 rect = CFX_FloatRect(kMinIntAsFloat, kMinIntAsFloat, kMaxIntAsFloat,
127 kMaxIntAsFloat);
128 inner_rect = rect.GetInnerRect();
129 EXPECT_EQ(kMinInt, inner_rect.left);
130 EXPECT_EQ(kMaxInt, inner_rect.bottom);
131 EXPECT_EQ(kMaxInt, inner_rect.right);
132 EXPECT_EQ(kMinInt, inner_rect.top);
133
134 rect = CFX_FloatRect(kMinIntAsFloat - 1.0f, kMinIntAsFloat - 1.0f,
135 kMaxIntAsFloat + 1.0f, kMaxIntAsFloat + 1.0f);
136 inner_rect = rect.GetInnerRect();
137 EXPECT_EQ(kMinInt, inner_rect.left);
138 EXPECT_EQ(kMaxInt, inner_rect.bottom);
139 EXPECT_EQ(kMaxInt, inner_rect.right);
140 EXPECT_EQ(kMinInt, inner_rect.top);
141}
142
144 FX_RECT outer_rect;
145 CFX_FloatRect rect;
146
147 outer_rect = rect.GetOuterRect();
148 EXPECT_EQ(0, outer_rect.left);
149 EXPECT_EQ(0, outer_rect.bottom);
150 EXPECT_EQ(0, outer_rect.right);
151 EXPECT_EQ(0, outer_rect.top);
152
153 // Function converts from float to int using floor() for left and bottom, and
154 // ceil() for right and top.
155 rect = CFX_FloatRect(-1.1f, 3.6f, 4.4f, -5.7f);
156 outer_rect = rect.GetOuterRect();
157 EXPECT_EQ(-2, outer_rect.left);
158 EXPECT_EQ(3, outer_rect.bottom);
159 EXPECT_EQ(5, outer_rect.right);
160 EXPECT_EQ(-5, outer_rect.top);
161
162 rect = CFX_FloatRect(kMinFloat, kMinFloat, kMinFloat, kMinFloat);
163 outer_rect = rect.GetOuterRect();
164 EXPECT_EQ(0, outer_rect.left);
165 EXPECT_EQ(1, outer_rect.bottom);
166 EXPECT_EQ(1, outer_rect.right);
167 EXPECT_EQ(0, outer_rect.top);
168
169 rect = CFX_FloatRect(-kMinFloat, -kMinFloat, -kMinFloat, -kMinFloat);
170 outer_rect = rect.GetOuterRect();
171 EXPECT_EQ(-1, outer_rect.left);
172 EXPECT_EQ(0, outer_rect.bottom);
173 EXPECT_EQ(0, outer_rect.right);
174 EXPECT_EQ(-1, outer_rect.top);
175
176 // Check at limits of integer range. When saturated would expect to get values
177 // that are clamped to the limits of integers.
178 rect = CFX_FloatRect(kMinIntAsFloat, kMinIntAsFloat, kMaxIntAsFloat,
179 kMaxIntAsFloat);
180 outer_rect = rect.GetOuterRect();
181 EXPECT_EQ(kMinInt, outer_rect.left);
182 EXPECT_EQ(kMaxInt, outer_rect.bottom);
183 EXPECT_EQ(kMaxInt, outer_rect.right);
184 EXPECT_EQ(kMinInt, outer_rect.top);
185
186 rect = CFX_FloatRect(kMinIntAsFloat - 1.0f, kMinIntAsFloat - 1.0f,
187 kMaxIntAsFloat + 1.0f, kMaxIntAsFloat + 1.0f);
188 outer_rect = rect.GetOuterRect();
189 EXPECT_EQ(kMinInt, outer_rect.left);
190 EXPECT_EQ(kMaxInt, outer_rect.bottom);
191 EXPECT_EQ(kMaxInt, outer_rect.right);
192 EXPECT_EQ(kMinInt, outer_rect.top);
193}
194
196 CFX_FloatRect rect;
197 rect.Normalize();
198 EXPECT_FLOAT_EQ(0.0f, rect.left);
199 EXPECT_FLOAT_EQ(0.0f, rect.bottom);
200 EXPECT_FLOAT_EQ(0.0f, rect.right);
201 EXPECT_FLOAT_EQ(0.0f, rect.top);
202
203 rect = CFX_FloatRect(-1.0f, -3.0f, 4.5f, 3.2f);
204 rect.Normalize();
205 EXPECT_FLOAT_EQ(-1.0f, rect.left);
206 EXPECT_FLOAT_EQ(-3.0f, rect.bottom);
207 EXPECT_FLOAT_EQ(4.5f, rect.right);
208 EXPECT_FLOAT_EQ(3.2f, rect.top);
209 rect.Scale(-1.0f);
210 rect.Normalize();
211 EXPECT_FLOAT_EQ(-4.5f, rect.left);
212 EXPECT_FLOAT_EQ(-3.2f, rect.bottom);
213 EXPECT_FLOAT_EQ(1.0f, rect.right);
214 EXPECT_FLOAT_EQ(3.0f, rect.top);
215}
216
218 CFX_FloatRect rect(-1.0f, -3.0f, 4.5f, 3.2f);
219 rect.Scale(1.0f);
220 EXPECT_FLOAT_EQ(-1.0f, rect.left);
221 EXPECT_FLOAT_EQ(-3.0f, rect.bottom);
222 EXPECT_FLOAT_EQ(4.5f, rect.right);
223 EXPECT_FLOAT_EQ(3.2f, rect.top);
224 rect.Scale(0.5f);
225 EXPECT_FLOAT_EQ(-0.5, rect.left);
226 EXPECT_FLOAT_EQ(-1.5, rect.bottom);
227 EXPECT_FLOAT_EQ(2.25f, rect.right);
228 EXPECT_FLOAT_EQ(1.6f, rect.top);
229 rect.Scale(2.0f);
230 EXPECT_FLOAT_EQ(-1.0f, rect.left);
231 EXPECT_FLOAT_EQ(-3.0f, rect.bottom);
232 EXPECT_FLOAT_EQ(4.5f, rect.right);
233 EXPECT_FLOAT_EQ(3.2f, rect.top);
234 rect.Scale(-1.0f);
235 EXPECT_FLOAT_EQ(1.0f, rect.left);
236 EXPECT_FLOAT_EQ(3.0f, rect.bottom);
237 EXPECT_FLOAT_EQ(-4.5f, rect.right);
238 EXPECT_FLOAT_EQ(-3.2f, rect.top);
239 rect.Scale(0.0f);
240 EXPECT_FLOAT_EQ(0.0f, rect.left);
241 EXPECT_FLOAT_EQ(0.0f, rect.bottom);
242 EXPECT_FLOAT_EQ(0.0f, rect.right);
243 EXPECT_FLOAT_EQ(0.0f, rect.top);
244}
245
247 CFX_FloatRect rect;
248 rect.Scale(1.0f);
249 EXPECT_FLOAT_EQ(0.0f, rect.left);
250 EXPECT_FLOAT_EQ(0.0f, rect.bottom);
251 EXPECT_FLOAT_EQ(0.0f, rect.right);
252 EXPECT_FLOAT_EQ(0.0f, rect.top);
253 rect.Scale(0.5f);
254 EXPECT_FLOAT_EQ(0.0f, rect.left);
255 EXPECT_FLOAT_EQ(0.0f, rect.bottom);
256 EXPECT_FLOAT_EQ(0.0f, rect.right);
257 EXPECT_FLOAT_EQ(0.0f, rect.top);
258 rect.Scale(2.0f);
259 EXPECT_FLOAT_EQ(0.0f, rect.left);
260 EXPECT_FLOAT_EQ(0.0f, rect.bottom);
261 EXPECT_FLOAT_EQ(0.0f, rect.right);
262 EXPECT_FLOAT_EQ(0.0f, rect.top);
263 rect.Scale(0.0f);
264 EXPECT_FLOAT_EQ(0.0f, rect.left);
265 EXPECT_FLOAT_EQ(0.0f, rect.bottom);
266 EXPECT_FLOAT_EQ(0.0f, rect.right);
267 EXPECT_FLOAT_EQ(0.0f, rect.top);
268}
269
271 CFX_FloatRect rect(-1.0f, -3.0f, 4.5f, 3.2f);
273 EXPECT_FLOAT_EQ(-1.0f, rect.left);
274 EXPECT_FLOAT_EQ(-3.0f, rect.bottom);
275 EXPECT_FLOAT_EQ(4.5f, rect.right);
276 EXPECT_FLOAT_EQ(3.2f, rect.top);
278 EXPECT_FLOAT_EQ(0.375f, rect.left);
279 EXPECT_FLOAT_EQ(-1.45f, rect.bottom);
280 EXPECT_FLOAT_EQ(3.125f, rect.right);
281 EXPECT_FLOAT_EQ(1.65f, rect.top);
283 EXPECT_FLOAT_EQ(-1.0f, rect.left);
284 EXPECT_FLOAT_EQ(-3.0f, rect.bottom);
285 EXPECT_FLOAT_EQ(4.5f, rect.right);
286 EXPECT_FLOAT_EQ(3.2f, rect.top);
288 EXPECT_FLOAT_EQ(4.5f, rect.left);
289 EXPECT_FLOAT_EQ(3.2f, rect.bottom);
290 EXPECT_FLOAT_EQ(-1.0f, rect.right);
291 EXPECT_FLOAT_EQ(-3.0f, rect.top);
293 EXPECT_FLOAT_EQ(1.75f, rect.left);
294 EXPECT_NEAR(0.1f, rect.bottom, 0.001f);
295 EXPECT_FLOAT_EQ(1.75f, rect.right);
296 EXPECT_NEAR(0.1f, rect.top, 0.001f);
297}
298
300 CFX_FloatRect rect;
302 EXPECT_FLOAT_EQ(0.0f, rect.left);
303 EXPECT_FLOAT_EQ(0.0f, rect.bottom);
304 EXPECT_FLOAT_EQ(0.0f, rect.right);
305 EXPECT_FLOAT_EQ(0.0f, rect.top);
307 EXPECT_FLOAT_EQ(0.0f, rect.left);
308 EXPECT_FLOAT_EQ(0.0f, rect.bottom);
309 EXPECT_FLOAT_EQ(0.0f, rect.right);
310 EXPECT_FLOAT_EQ(0.0f, rect.top);
312 EXPECT_FLOAT_EQ(0.0f, rect.left);
313 EXPECT_FLOAT_EQ(0.0f, rect.bottom);
314 EXPECT_FLOAT_EQ(0.0f, rect.right);
315 EXPECT_FLOAT_EQ(0.0f, rect.top);
317 EXPECT_FLOAT_EQ(0.0f, rect.left);
318 EXPECT_FLOAT_EQ(0.0f, rect.bottom);
319 EXPECT_FLOAT_EQ(0.0f, rect.right);
320 EXPECT_FLOAT_EQ(0.0f, rect.top);
321}
322
324 std::ostringstream os;
325 CFX_FloatRect rect;
326 os << rect;
327 EXPECT_EQ("rect[w 0 x h 0 (left 0, bot 0)]", os.str());
328
329 os.str("");
330 rect = CFX_FloatRect(10, 20, 14, 23);
331 os << rect;
332 EXPECT_EQ("rect[w 4 x h 3 (left 10, bot 20)]", os.str());
333
334 os.str("");
335 rect = CFX_FloatRect(10.5, 20.5, 14.75, 23.75);
336 os << rect;
337 EXPECT_EQ("rect[w 4.25 x h 3.25 (left 10.5, bot 20.5)]", os.str());
338}
339
341 std::ostringstream os;
342 CFX_RectF rect;
343 os << rect;
344 EXPECT_EQ("rect[w 0 x h 0 (left 0, top 0)]", os.str());
345
346 os.str("");
347 rect = CFX_RectF(10, 20, 4, 3);
348 os << rect;
349 EXPECT_EQ("rect[w 4 x h 3 (left 10, top 20)]", os.str());
350
351 os.str("");
352 rect = CFX_RectF(10.5, 20.5, 4.25, 3.25);
353 os << rect;
354 EXPECT_EQ("rect[w 4.25 x h 3.25 (left 10.5, top 20.5)]", os.str());
355}
356
359
360 EXPECT_FLOAT_EQ(1.0, rev.a);
361 EXPECT_FLOAT_EQ(0.0, rev.b);
362 EXPECT_FLOAT_EQ(0.0, rev.c);
363 EXPECT_FLOAT_EQ(1.0, rev.d);
364 EXPECT_FLOAT_EQ(0.0, rev.e);
365 EXPECT_FLOAT_EQ(0.0, rev.f);
366
367 CFX_PointF expected(2, 3);
368 CFX_PointF result = rev.Transform(CFX_Matrix().Transform(CFX_PointF(2, 3)));
369 EXPECT_FLOAT_EQ(expected.x, result.x);
370 EXPECT_FLOAT_EQ(expected.y, result.y);
371}
372
374 CFX_Matrix m;
375 EXPECT_FLOAT_EQ(1.0f, m.a);
376 EXPECT_FLOAT_EQ(0.0f, m.b);
377 EXPECT_FLOAT_EQ(0.0f, m.c);
378 EXPECT_FLOAT_EQ(1.0f, m.d);
379 EXPECT_FLOAT_EQ(0.0f, m.e);
380 EXPECT_FLOAT_EQ(0.0f, m.f);
381 EXPECT_TRUE(m.IsIdentity());
382
383 m.a = -1;
384 EXPECT_FALSE(m.IsIdentity());
385
386 m = CFX_Matrix();
387 EXPECT_FLOAT_EQ(1.0f, m.a);
388 EXPECT_FLOAT_EQ(0.0f, m.b);
389 EXPECT_FLOAT_EQ(0.0f, m.c);
390 EXPECT_FLOAT_EQ(1.0f, m.d);
391 EXPECT_FLOAT_EQ(0.0f, m.e);
392 EXPECT_FLOAT_EQ(0.0f, m.f);
393 EXPECT_TRUE(m.IsIdentity());
394}
395
397 constexpr CFX_Matrix m(3, 0, 2, 3, 1, 4);
399
400 EXPECT_FLOAT_EQ(0.33333334f, rev.a);
401 EXPECT_FLOAT_EQ(0.0f, rev.b);
402 EXPECT_FLOAT_EQ(-0.22222222f, rev.c);
403 EXPECT_FLOAT_EQ(0.33333334f, rev.d);
404 EXPECT_FLOAT_EQ(0.55555556f, rev.e);
405 EXPECT_FLOAT_EQ(-1.3333334f, rev.f);
406
407 CFX_PointF expected(2, 3);
408 CFX_PointF result = rev.Transform(m.Transform(CFX_PointF(2, 3)));
409 EXPECT_FLOAT_EQ(expected.x, result.x);
410 EXPECT_FLOAT_EQ(expected.y, result.y);
411}
412
413// Note, I think these are a bug and the matrix should be the identity.
415 // The determinate is < std::numeric_limits<float>::epsilon()
416 constexpr CFX_Matrix m(0.947368443f, -0.108947366f, -0.923076928f,
417 0.106153846f, 18.0f, 787.929993f);
419
420 EXPECT_FLOAT_EQ(14247728.0f, rev.a);
421 EXPECT_FLOAT_EQ(14622668.0f, rev.b);
422 EXPECT_FLOAT_EQ(1.2389329e+08f, rev.c);
423 EXPECT_FLOAT_EQ(1.2715364e+08f, rev.d);
424 EXPECT_FLOAT_EQ(-9.7875698e+10f, rev.e);
425 EXPECT_FLOAT_EQ(-1.0045138e+11f, rev.f);
426
427 // Should be 2, 3
428 CFX_PointF expected(0, 0);
429 CFX_PointF result = rev.Transform(m.Transform(CFX_PointF(2, 3)));
430 EXPECT_FLOAT_EQ(expected.x, result.x);
431 EXPECT_FLOAT_EQ(expected.y, result.y);
432}
433
435 // The determinate is < std::numeric_limits<float>::epsilon()
436 constexpr CFX_Matrix m(0.000037f, 0.0f, 0.0f, -0.000037f, 182.413101f,
437 136.977646f);
439
440 EXPECT_FLOAT_EQ(27027.025f, rev.a);
441 EXPECT_FLOAT_EQ(0.0f, rev.b);
442 EXPECT_FLOAT_EQ(0.0f, rev.c);
443 EXPECT_FLOAT_EQ(-27027.025f, rev.d);
444 EXPECT_FLOAT_EQ(-4930083.5f, rev.e);
445 EXPECT_FLOAT_EQ(3702098.2f, rev.f);
446
447 // Should be 3 ....
448 CFX_PointF expected(2, 2.75);
449 CFX_PointF result = rev.Transform(m.Transform(CFX_PointF(2, 3)));
450 EXPECT_FLOAT_EQ(expected.x, result.x);
451 EXPECT_FLOAT_EQ(expected.y, result.y);
452}
453
454#define EXPECT_NEAR_FIVE_PLACES(a, b) EXPECT_NEAR((a), (b), 1e-5)
455
457 // sin(FXSYS_PI/2) and cos(FXSYS_PI/2) have a tiny error and are not
458 // exactly 1.0f and 0.0f. The rotation matrix is thus not perfect.
459
460 CFX_Matrix rotate_90;
461 rotate_90.Rotate(FXSYS_PI / 2);
462 EXPECT_NEAR_FIVE_PLACES(0.0f, rotate_90.a);
463 EXPECT_NEAR_FIVE_PLACES(1.0f, rotate_90.b);
464 EXPECT_NEAR_FIVE_PLACES(-1.0f, rotate_90.c);
465 EXPECT_NEAR_FIVE_PLACES(0.0f, rotate_90.d);
466 EXPECT_FLOAT_EQ(0.0f, rotate_90.e);
467 EXPECT_FLOAT_EQ(0.0f, rotate_90.f);
468
469 CFX_Matrix translate_23_11;
470 translate_23_11.Translate(23, 11);
471 EXPECT_FLOAT_EQ(1.0f, translate_23_11.a);
472 EXPECT_FLOAT_EQ(0.0f, translate_23_11.b);
473 EXPECT_FLOAT_EQ(0.0f, translate_23_11.c);
474 EXPECT_FLOAT_EQ(1.0f, translate_23_11.d);
475 EXPECT_FLOAT_EQ(23.0f, translate_23_11.e);
476 EXPECT_FLOAT_EQ(11.0f, translate_23_11.f);
477
478 CFX_Matrix scale_5_13;
479 scale_5_13.Scale(5, 13);
480 EXPECT_FLOAT_EQ(5.0f, scale_5_13.a);
481 EXPECT_FLOAT_EQ(0.0f, scale_5_13.b);
482 EXPECT_FLOAT_EQ(0.0f, scale_5_13.c);
483 EXPECT_FLOAT_EQ(13.0f, scale_5_13.d);
484 EXPECT_FLOAT_EQ(0.0, scale_5_13.e);
485 EXPECT_FLOAT_EQ(0.0, scale_5_13.f);
486
487 // Apply the transforms to points step by step.
488 CFX_PointF origin_transformed(0, 0);
489 CFX_PointF p_10_20_transformed(10, 20);
490
491 origin_transformed = rotate_90.Transform(origin_transformed);
492 EXPECT_FLOAT_EQ(0.0f, origin_transformed.x);
493 EXPECT_FLOAT_EQ(0.0f, origin_transformed.y);
494 p_10_20_transformed = rotate_90.Transform(p_10_20_transformed);
495 EXPECT_FLOAT_EQ(-20.0f, p_10_20_transformed.x);
496 EXPECT_FLOAT_EQ(10.0f, p_10_20_transformed.y);
497
498 origin_transformed = translate_23_11.Transform(origin_transformed);
499 EXPECT_FLOAT_EQ(23.0f, origin_transformed.x);
500 EXPECT_FLOAT_EQ(11.0f, origin_transformed.y);
501 p_10_20_transformed = translate_23_11.Transform(p_10_20_transformed);
502 EXPECT_FLOAT_EQ(3.0f, p_10_20_transformed.x);
503 EXPECT_FLOAT_EQ(21.0f, p_10_20_transformed.y);
504
505 origin_transformed = scale_5_13.Transform(origin_transformed);
506 EXPECT_FLOAT_EQ(115.0f, origin_transformed.x);
507 EXPECT_FLOAT_EQ(143.0f, origin_transformed.y);
508 p_10_20_transformed = scale_5_13.Transform(p_10_20_transformed);
509 EXPECT_FLOAT_EQ(15.0f, p_10_20_transformed.x);
510 EXPECT_FLOAT_EQ(273.0f, p_10_20_transformed.y);
511
512 // Apply the transforms to points in the reverse order.
513 origin_transformed = CFX_PointF(0, 0);
514 p_10_20_transformed = CFX_PointF(10, 20);
515
516 origin_transformed = scale_5_13.Transform(origin_transformed);
517 EXPECT_FLOAT_EQ(0.0f, origin_transformed.x);
518 EXPECT_FLOAT_EQ(0.0f, origin_transformed.y);
519 p_10_20_transformed = scale_5_13.Transform(p_10_20_transformed);
520 EXPECT_FLOAT_EQ(50.0f, p_10_20_transformed.x);
521 EXPECT_FLOAT_EQ(260.0f, p_10_20_transformed.y);
522
523 origin_transformed = translate_23_11.Transform(origin_transformed);
524 EXPECT_FLOAT_EQ(23.0f, origin_transformed.x);
525 EXPECT_FLOAT_EQ(11.0f, origin_transformed.y);
526 p_10_20_transformed = translate_23_11.Transform(p_10_20_transformed);
527 EXPECT_FLOAT_EQ(73.0f, p_10_20_transformed.x);
528 EXPECT_FLOAT_EQ(271.0f, p_10_20_transformed.y);
529
530 origin_transformed = rotate_90.Transform(origin_transformed);
531 EXPECT_FLOAT_EQ(-11.0f, origin_transformed.x);
532 EXPECT_FLOAT_EQ(23.0f, origin_transformed.y);
533 p_10_20_transformed = rotate_90.Transform(p_10_20_transformed);
534 EXPECT_FLOAT_EQ(-271.0f, p_10_20_transformed.x);
535 EXPECT_FLOAT_EQ(73.0f, p_10_20_transformed.y);
536
537 // Compose all transforms.
538 CFX_Matrix m;
539 m.Concat(rotate_90);
540 m.Concat(translate_23_11);
541 m.Concat(scale_5_13);
546 EXPECT_FLOAT_EQ(115.0, m.e);
547 EXPECT_FLOAT_EQ(143.0, m.f);
548
549 // Note how the results using the combined matrix are equal to the results
550 // when applying the three original matrices step-by-step.
551 origin_transformed = m.Transform(CFX_PointF(0, 0));
552 EXPECT_FLOAT_EQ(115.0f, origin_transformed.x);
553 EXPECT_FLOAT_EQ(143.0f, origin_transformed.y);
554
555 p_10_20_transformed = m.Transform(CFX_PointF(10, 20));
556 EXPECT_FLOAT_EQ(15.0f, p_10_20_transformed.x);
557 EXPECT_FLOAT_EQ(273.0f, p_10_20_transformed.y);
558
559 // Now compose all transforms prepending.
560 m = CFX_Matrix();
561 m = rotate_90 * m;
562 m = translate_23_11 * m;
563 m = scale_5_13 * m;
566 EXPECT_NEAR_FIVE_PLACES(-13.0f, m.c);
568 EXPECT_FLOAT_EQ(-11.0, m.e);
569 EXPECT_FLOAT_EQ(23.0, m.f);
570
571 // Note how the results using the combined matrix are equal to the results
572 // when applying the three original matrices step-by-step in the reverse
573 // order.
574 origin_transformed = m.Transform(CFX_PointF(0, 0));
575 EXPECT_FLOAT_EQ(-11.0f, origin_transformed.x);
576 EXPECT_FLOAT_EQ(23.0f, origin_transformed.y);
577
578 p_10_20_transformed = m.Transform(CFX_PointF(10, 20));
579 EXPECT_FLOAT_EQ(-271.0f, p_10_20_transformed.x);
580 EXPECT_FLOAT_EQ(73.0f, p_10_20_transformed.y);
581}
582
584 CFX_Matrix rotate_90;
585 rotate_90.Rotate(FXSYS_PI / 2);
586
587 CFX_Matrix scale_5_13;
588 scale_5_13.Scale(5, 13);
589
590 CFX_RectF rect(10.5f, 20.5f, 4.25f, 3.25f);
591 rect = rotate_90.TransformRect(rect);
592 EXPECT_FLOAT_EQ(-23.75f, rect.Left());
593 EXPECT_FLOAT_EQ(10.5f, rect.Top());
594 EXPECT_FLOAT_EQ(3.25f, rect.Width());
595 EXPECT_FLOAT_EQ(4.25f, rect.Height());
596
597 rect = scale_5_13.TransformRect(rect);
598 EXPECT_FLOAT_EQ(-118.75f, rect.Left());
599 EXPECT_FLOAT_EQ(136.5f, rect.Top());
600 EXPECT_FLOAT_EQ(16.25f, rect.Width());
601 EXPECT_FLOAT_EQ(55.25f, rect.Height());
602}
603
605 CFX_Matrix rotate_90;
606 rotate_90.Rotate(FXSYS_PI / 2);
607
608 CFX_Matrix scale_5_13;
609 scale_5_13.Scale(5, 13);
610
611 CFX_FloatRect rect(5.5f, 0.0f, 12.25f, 2.7f);
612 rect = rotate_90.TransformRect(rect);
613 EXPECT_FLOAT_EQ(-2.7f, rect.Left());
614 EXPECT_FLOAT_EQ(5.5f, rect.Bottom());
615 EXPECT_NEAR(0.0f, rect.Right(), 0.00001f);
616 EXPECT_FLOAT_EQ(12.25f, rect.Top());
617
618 rect = scale_5_13.TransformRect(rect);
619 EXPECT_FLOAT_EQ(-13.5f, rect.Left());
620 EXPECT_FLOAT_EQ(71.5f, rect.Bottom());
621 EXPECT_NEAR(0.0f, rect.Right(), 0.00001f);
622 EXPECT_FLOAT_EQ(159.25f, rect.Top());
623}
float Left() const
constexpr CFX_FloatRect(float l, float b, float r, float t)
float Top() const
float Bottom() const
CFX_FloatRect(const FX_RECT &rect)
void ScaleFromCenterPoint(float fScale)
FX_RECT GetInnerRect() const
CFX_FloatRect & operator=(const CFX_FloatRect &that)=default
FX_RECT GetOuterRect() const
float Right() const
void Scale(float fScale)
constexpr CFX_Matrix()=default
CFX_Matrix & operator=(const CFX_Matrix &other)=default
CFX_FloatRect TransformRect(const CFX_FloatRect &rect) const
CFX_RectF TransformRect(const CFX_RectF &rect) const
CFX_Matrix operator*(const CFX_Matrix &right) const
CFX_PointF Transform(const CFX_PointF &point) const
void Translate(int32_t x, int32_t y)
CFX_Matrix GetInverse() const
void Rotate(float fRadian)
constexpr CFX_Matrix(float a1, float b1, float c1, float d1, float e1, float f1)
bool IsIdentity() const
void Scale(float sx, float sy)
void Concat(const CFX_Matrix &right)
float Left() const
float Width() const
CFX_RectF & operator=(const CFX_RectF &other)=default
float Height() const
float Top() const
constexpr CFX_RectF(float dst_left, float dst_top, float dst_width, float dst_height)
CFX_PTemplate< float > CFX_PointF
TEST(CFX_FloatRect, FromFXRect)
#define EXPECT_NEAR_FIVE_PLACES(a, b)
TEST(CFX_Matrix, ReverseIdentity)
TEST(CFX_RectF, Print)
#define FXSYS_PI
Definition fx_system.h:44
FX_RECT & operator=(const FX_RECT &that)=default
int32_t bottom
int32_t right
int32_t top
int32_t left
constexpr FX_RECT(int l, int t, int r, int b)