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
cfx_path_unittest.cpp
Go to the documentation of this file.
1// Copyright 2021 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/fxge/cfx_path.h"
6
7#include "core/fxcrt/fx_coordinates.h"
8#include "testing/gtest/include/gtest/gtest.h"
9
11 CFX_Path path;
12 path.AppendRect(/*left=*/1, /*bottom=*/2, /*right=*/3, /*top=*/5);
13 EXPECT_EQ(5u, path.GetPoints().size());
14 EXPECT_TRUE(path.IsRect());
15 absl::optional<CFX_FloatRect> rect = path.GetRect(nullptr);
16 ASSERT_TRUE(rect.has_value());
17 EXPECT_EQ(CFX_FloatRect(1, 2, 3, 5), rect.value());
18 EXPECT_EQ(CFX_FloatRect(1, 2, 3, 5), path.GetBoundingBox());
19
20 const CFX_Matrix kScaleMatrix(1, 0, 0, 2, 60, 70);
21 rect = path.GetRect(&kScaleMatrix);
22 ASSERT_TRUE(rect.has_value());
23 EXPECT_EQ(CFX_FloatRect(61, 74, 63, 80), rect.value());
24 EXPECT_EQ(CFX_FloatRect(1, 2, 3, 5), path.GetBoundingBox());
25
26 path.Clear();
27 EXPECT_EQ(0u, path.GetPoints().size());
28 EXPECT_FALSE(path.IsRect());
29 EXPECT_EQ(CFX_FloatRect(), path.GetBoundingBox());
30
31 // 4 points without a closed path makes a rect.
36 EXPECT_EQ(4u, path.GetPoints().size());
37 EXPECT_TRUE(path.IsRect());
38 rect = path.GetRect(nullptr);
39 ASSERT_TRUE(rect.has_value());
40 EXPECT_EQ(CFX_FloatRect(0, 0, 1, 1), rect.value());
41 EXPECT_EQ(CFX_FloatRect(0, 0, 1, 1), path.GetBoundingBox());
42
43 // 4 points with a closed path also makes a rect.
44 path.ClosePath();
45 EXPECT_EQ(4u, path.GetPoints().size());
46 EXPECT_TRUE(path.IsRect());
47 rect = path.GetRect(nullptr);
48 ASSERT_TRUE(rect.has_value());
49 EXPECT_EQ(CFX_FloatRect(0, 0, 1, 1), rect.value());
50 EXPECT_EQ(CFX_FloatRect(0, 0, 1, 1), path.GetBoundingBox());
51
52 path.Transform(kScaleMatrix);
53 EXPECT_TRUE(path.IsRect());
54 rect = path.GetRect(nullptr);
55 ASSERT_TRUE(rect.has_value());
56 EXPECT_EQ(CFX_FloatRect(60, 70, 61, 72), rect.value());
57 EXPECT_EQ(CFX_FloatRect(60, 70, 61, 72), path.GetBoundingBox());
58
59 path.Clear();
60 path.AppendFloatRect({1, 2, 3, 5});
61 EXPECT_TRUE(path.IsRect());
62 rect = path.GetRect(nullptr);
63 ASSERT_TRUE(rect.has_value());
64 EXPECT_EQ(CFX_FloatRect(1, 2, 3, 5), rect.value());
65 EXPECT_EQ(CFX_FloatRect(1, 2, 3, 5), path.GetBoundingBox());
66}
67
69 CFX_Path path;
70 path.AppendRect(/*left=*/1, /*bottom=*/2, /*right=*/3, /*top=*/5);
71
72 const CFX_Matrix kShearMatrix(1, 2, 0, 1, 0, 0);
73 EXPECT_TRUE(path.IsRect());
74 absl::optional<CFX_FloatRect> rect = path.GetRect(&kShearMatrix);
75 EXPECT_FALSE(rect.has_value());
76 EXPECT_EQ(CFX_FloatRect(1, 2, 3, 5), path.GetBoundingBox());
77
78 path.Transform(kShearMatrix);
79 EXPECT_FALSE(path.IsRect());
80 rect = path.GetRect(nullptr);
81 EXPECT_FALSE(rect.has_value());
82 EXPECT_EQ(CFX_FloatRect(1, 4, 3, 11), path.GetBoundingBox());
83
84 const CFX_Matrix shear_inverse_matrix = kShearMatrix.GetInverse();
85 rect = path.GetRect(&shear_inverse_matrix);
86 ASSERT_TRUE(rect.has_value());
87 EXPECT_EQ(CFX_FloatRect(1, 2, 3, 5), rect.value());
88 EXPECT_EQ(CFX_FloatRect(1, 4, 3, 11), path.GetBoundingBox());
89
90 path.Transform(shear_inverse_matrix);
91 EXPECT_TRUE(path.IsRect());
92 rect = path.GetRect(nullptr);
93 ASSERT_TRUE(rect.has_value());
94 EXPECT_EQ(CFX_FloatRect(1, 2, 3, 5), rect.value());
95 EXPECT_EQ(CFX_FloatRect(1, 2, 3, 5), path.GetBoundingBox());
96}
97
99 CFX_Path path;
106 ASSERT_EQ(6u, path.GetPoints().size());
107 EXPECT_EQ(CFX_Path::Point::Type::kLine, path.GetType(5));
108 EXPECT_FALSE(path.IsClosingFigure(5));
109 EXPECT_FALSE(path.IsRect());
110 EXPECT_FALSE(path.GetRect(nullptr).has_value());
111 EXPECT_EQ(CFX_FloatRect(0, 0, 3, 2), path.GetBoundingBox());
112
113 path.ClosePath();
114 ASSERT_EQ(6u, path.GetPoints().size());
115 EXPECT_EQ(CFX_Path::Point::Type::kLine, path.GetType(5));
116 EXPECT_TRUE(path.IsClosingFigure(5));
117 EXPECT_FALSE(path.IsRect());
118 EXPECT_FALSE(path.GetRect(nullptr).has_value());
119
120 // Calling ClosePath() repeatedly makes no difference.
121 path.ClosePath();
122 ASSERT_EQ(6u, path.GetPoints().size());
123 EXPECT_EQ(CFX_Path::Point::Type::kLine, path.GetType(5));
124 EXPECT_TRUE(path.IsClosingFigure(5));
125 EXPECT_FALSE(path.IsRect());
126 EXPECT_FALSE(path.GetRect(nullptr).has_value());
127
128 // A hexagon with the same start/end point is still not a rectangle.
129 path.Clear();
137 EXPECT_FALSE(path.IsRect());
138 EXPECT_FALSE(path.GetRect(nullptr).has_value());
139 EXPECT_EQ(CFX_FloatRect(0, 0, 3, 2), path.GetBoundingBox());
140}
141
143 CFX_Path path;
144 path.AppendLine({0, 0}, {0, 1});
145 path.AppendLine({0, 1}, {1, 1});
146 path.AppendLine({1, 1}, {1, 0});
147 ASSERT_EQ(4u, path.GetPoints().size());
148 EXPECT_EQ(CFX_Path::Point::Type::kLine, path.GetType(3));
149 EXPECT_FALSE(path.IsClosingFigure(3));
150 EXPECT_TRUE(path.IsRect());
151 absl::optional<CFX_FloatRect> rect = path.GetRect(nullptr);
152 ASSERT_TRUE(rect.has_value());
153 EXPECT_EQ(CFX_FloatRect(0, 0, 1, 1), rect.value());
154
155 const CFX_Matrix kIdentityMatrix;
156 ASSERT_TRUE(kIdentityMatrix.IsIdentity());
157 rect = path.GetRect(&kIdentityMatrix);
158 ASSERT_TRUE(rect.has_value());
159 EXPECT_EQ(CFX_FloatRect(0, 0, 1, 1), rect.value());
160
161 path.ClosePath();
162 ASSERT_EQ(4u, path.GetPoints().size());
163 EXPECT_EQ(CFX_Path::Point::Type::kLine, path.GetType(3));
164 EXPECT_TRUE(path.IsClosingFigure(3));
165 EXPECT_TRUE(path.IsRect());
166 rect = path.GetRect(nullptr);
167 ASSERT_TRUE(rect.has_value());
168 EXPECT_EQ(CFX_FloatRect(0, 0, 1, 1), rect.value());
169
170 // Calling ClosePath() repeatedly makes no difference.
171 path.ClosePath();
172 ASSERT_EQ(4u, path.GetPoints().size());
173 EXPECT_EQ(CFX_Path::Point::Type::kLine, path.GetType(3));
174 EXPECT_TRUE(path.IsClosingFigure(3));
175 EXPECT_TRUE(path.IsRect());
176 rect = path.GetRect(nullptr);
177 ASSERT_TRUE(rect.has_value());
178 EXPECT_EQ(CFX_FloatRect(0, 0, 1, 1), rect.value());
179
181 ASSERT_EQ(5u, path.GetPoints().size());
182 EXPECT_EQ(CFX_Path::Point::Type::kLine, path.GetType(3));
183 EXPECT_TRUE(path.IsClosingFigure(3));
184 EXPECT_EQ(CFX_Path::Point::Type::kLine, path.GetType(4));
185 EXPECT_TRUE(path.IsClosingFigure(4));
186 EXPECT_TRUE(path.IsRect());
187 rect = path.GetRect(nullptr);
188 ASSERT_TRUE(rect.has_value());
189 EXPECT_EQ(CFX_FloatRect(0, 0, 1, 1), rect.value());
190}
191
193 CFX_Path path;
199 ASSERT_EQ(5u, path.GetPoints().size());
200 EXPECT_EQ(CFX_Path::Point::Type::kLine, path.GetType(4));
201 EXPECT_FALSE(path.IsClosingFigure(4));
202 EXPECT_TRUE(path.IsRect());
203 absl::optional<CFX_FloatRect> rect = path.GetRect(nullptr);
204 ASSERT_TRUE(rect.has_value());
205 EXPECT_EQ(CFX_FloatRect(0, 0, 2, 1), rect.value());
206
207 path.ClosePath();
208 ASSERT_EQ(5u, path.GetPoints().size());
209 EXPECT_EQ(CFX_Path::Point::Type::kLine, path.GetType(4));
210 EXPECT_TRUE(path.IsClosingFigure(4));
211 EXPECT_TRUE(path.IsRect());
212 rect = path.GetRect(nullptr);
213 ASSERT_TRUE(rect.has_value());
214 EXPECT_EQ(CFX_FloatRect(0, 0, 2, 1), rect.value());
215}
216
218 CFX_Path path;
225 EXPECT_TRUE(path.IsRect());
226 absl::optional<CFX_FloatRect> rect = path.GetRect(nullptr);
227 ASSERT_TRUE(rect.has_value());
228 EXPECT_EQ(CFX_FloatRect(0, 0, 2, 1), rect.value());
229 EXPECT_EQ(CFX_FloatRect(0, 0, 2, 1), path.GetBoundingBox());
230
231 path.Clear();
245 EXPECT_TRUE(path.IsRect());
246 rect = path.GetRect(nullptr);
247 ASSERT_TRUE(rect.has_value());
248 EXPECT_EQ(CFX_FloatRect(0, 0, 2, 1), rect.value());
249 EXPECT_EQ(CFX_FloatRect(0, 0, 2, 1), path.GetBoundingBox());
250}
251
253 CFX_Path path;
259 EXPECT_FALSE(path.IsRect());
260 absl::optional<CFX_FloatRect> rect = path.GetRect(nullptr);
261 EXPECT_FALSE(rect.has_value());
262 EXPECT_EQ(CFX_FloatRect(0, 0, 2, 1), path.GetBoundingBox());
263
264 path.ClosePath();
265 EXPECT_FALSE(path.IsRect());
266 rect = path.GetRect(nullptr);
267 EXPECT_FALSE(rect.has_value());
268 EXPECT_EQ(CFX_FloatRect(0, 0, 2, 1), path.GetBoundingBox());
269
270 path.Clear();
275 EXPECT_FALSE(path.IsRect());
276 rect = path.GetRect(nullptr);
277 EXPECT_FALSE(rect.has_value());
278 EXPECT_EQ(CFX_FloatRect(0, 0, 3, 1), path.GetBoundingBox());
279
280 path.Clear();
285 EXPECT_FALSE(path.IsRect());
286 rect = path.GetRect(nullptr);
287 EXPECT_FALSE(rect.has_value());
288 EXPECT_EQ(CFX_FloatRect(0, 0, 2, 1), path.GetBoundingBox());
289
290 path.Clear();
295 EXPECT_FALSE(path.IsRect());
296 rect = path.GetRect(nullptr);
297 EXPECT_FALSE(rect.has_value());
298 EXPECT_EQ(CFX_FloatRect(0, 0, 3, 1), path.GetBoundingBox());
299
300 path.Clear();
306 EXPECT_FALSE(path.IsRect());
307 rect = path.GetRect(nullptr);
308 EXPECT_FALSE(rect.has_value());
309 EXPECT_EQ(CFX_FloatRect(0, 0, 2, 1), path.GetBoundingBox());
310
311 path.Clear();
317 EXPECT_FALSE(path.IsRect());
318 rect = path.GetRect(nullptr);
319 EXPECT_FALSE(rect.has_value());
320 EXPECT_EQ(CFX_FloatRect(0, 0, 2, 1), path.GetBoundingBox());
321
322 path.Clear();
327 EXPECT_FALSE(path.IsRect());
328 rect = path.GetRect(nullptr);
329 EXPECT_FALSE(rect.has_value());
330 const CFX_Matrix kScaleMatrix(1, 0, 0, 2, 60, 70);
331 rect = path.GetRect(&kScaleMatrix);
332 EXPECT_FALSE(rect.has_value());
333 EXPECT_EQ(CFX_FloatRect(0, 0, 2, 2), path.GetBoundingBox());
334}
335
337 // Document existing behavior where an empty rect is still considered a rect.
338 CFX_Path path;
344 EXPECT_TRUE(path.IsRect());
345 absl::optional<CFX_FloatRect> rect = path.GetRect(nullptr);
346 ASSERT_TRUE(rect.has_value());
347 EXPECT_EQ(CFX_FloatRect(0, 0, 0, 1), rect.value());
348 EXPECT_EQ(CFX_FloatRect(0, 0, 0, 1), path.GetBoundingBox());
349}
350
352 CFX_Path path;
354 ASSERT_EQ(1u, path.GetPoints().size());
355 EXPECT_EQ(CFX_PointF(5, 6), path.GetPoint(0));
356
357 CFX_Path empty_path;
358 path.Append(empty_path, nullptr);
359 ASSERT_EQ(1u, path.GetPoints().size());
360 EXPECT_EQ(CFX_PointF(5, 6), path.GetPoint(0));
361
362 path.Append(path, nullptr);
363 ASSERT_EQ(2u, path.GetPoints().size());
364 EXPECT_EQ(CFX_PointF(5, 6), path.GetPoint(0));
365 EXPECT_EQ(CFX_PointF(5, 6), path.GetPoint(1));
366
367 const CFX_Matrix kScaleMatrix(1, 0, 0, 2, 60, 70);
368 path.Append(path, &kScaleMatrix);
369 ASSERT_EQ(4u, path.GetPoints().size());
370 EXPECT_EQ(CFX_PointF(5, 6), path.GetPoint(0));
371 EXPECT_EQ(CFX_PointF(5, 6), path.GetPoint(1));
372 EXPECT_EQ(CFX_PointF(65, 82), path.GetPoint(2));
373 EXPECT_EQ(CFX_PointF(65, 82), path.GetPoint(3));
374}
375
377 static constexpr float kLineWidth = 1.0f;
378 static constexpr float kMiterLimit = 1.0f;
379
380 {
381 // Test the case that the first/last point is "move" and it closes the
382 // paths.
383 CFX_Path path;
385 path.ClosePath();
386 EXPECT_EQ(CFX_FloatRect(2, 0, 2, 0),
387 path.GetBoundingBoxForStrokePath(kLineWidth, kMiterLimit));
388 }
389
390 {
391 // Test on a regular rect path.
392 CFX_Path path;
397 path.ClosePath();
398 EXPECT_EQ(CFX_FloatRect(-1, -1, 3, 2),
399 path.GetBoundingBoxForStrokePath(kLineWidth, kMiterLimit));
400
401 // If the final point is "move" and the path remains open, it should not
402 // affect the bounding rect.
404 EXPECT_EQ(CFX_FloatRect(-1, -1, 3, 2),
405 path.GetBoundingBoxForStrokePath(kLineWidth, kMiterLimit));
406 }
407}
TEST(CFX_Path, BasicTest)
constexpr CFX_FloatRect(float l, float b, float r, float t)
constexpr CFX_FloatRect()=default
CFX_Matrix(float a1, float b1, float c1, float d1, float e1, float f1)
CFX_Matrix GetInverse() const
bool IsIdentity() const
CFX_FloatRect GetBoundingBox() const
Definition cfx_path.cpp:322
void Transform(const CFX_Matrix &matrix)
Definition cfx_path.cpp:392
void Clear()
Definition cfx_path.cpp:265
void AppendRect(float left, float bottom, float right, float top)
Definition cfx_path.cpp:309
void Append(const CFX_Path &src, const CFX_Matrix *matrix)
Definition cfx_path.cpp:275
CFX_FloatRect GetBoundingBoxForStrokePath(float line_width, float miter_limit) const
Definition cfx_path.cpp:332
void AppendFloatRect(const CFX_FloatRect &rect)
Definition cfx_path.cpp:305
void AppendPointAndClose(const CFX_PointF &point, Point::Type type)
Definition cfx_path.cpp:293
void AppendLine(const CFX_PointF &pt1, const CFX_PointF &pt2)
Definition cfx_path.cpp:297
void ClosePath()
Definition cfx_path.cpp:269
void AppendPoint(const CFX_PointF &point, Point::Type type)
Definition cfx_path.cpp:289
bool IsRect() const
Definition cfx_path.cpp:397