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