aboutsummaryrefslogtreecommitdiff
path: root/core/fxge/cfx_path_unittest.cpp
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-12-13 18:05:38 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-12-13 18:05:38 +0000
commite03171e52ec4232369ab3b46e11d3a0abe1eb630 (patch)
tree6a57f6a0948032e6ec387c22d8b462215e6ca1e4 /core/fxge/cfx_path_unittest.cpp
parent8bbfdf2fca7197a0eccfef7b6fc27c590a44e7f7 (diff)
parent326d96bf5d52fdcf790b467b13f58ba3df3e81e4 (diff)
downloadpdfium-e03171e52ec4232369ab3b46e11d3a0abe1eb630.tar.gz
Change-Id: If925f85c6a039b56ff549fd5327795f57b9cd12c
Diffstat (limited to 'core/fxge/cfx_path_unittest.cpp')
-rw-r--r--core/fxge/cfx_path_unittest.cpp407
1 files changed, 407 insertions, 0 deletions
diff --git a/core/fxge/cfx_path_unittest.cpp b/core/fxge/cfx_path_unittest.cpp
new file mode 100644
index 000000000..4ccb1c2df
--- /dev/null
+++ b/core/fxge/cfx_path_unittest.cpp
@@ -0,0 +1,407 @@
+// Copyright 2021 The PDFium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/fxge/cfx_path.h"
+
+#include "core/fxcrt/fx_coordinates.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(CFX_Path, BasicTest) {
+ CFX_Path path;
+ path.AppendRect(/*left=*/1, /*bottom=*/2, /*right=*/3, /*top=*/5);
+ EXPECT_EQ(5u, path.GetPoints().size());
+ EXPECT_TRUE(path.IsRect());
+ absl::optional<CFX_FloatRect> rect = path.GetRect(nullptr);
+ ASSERT_TRUE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(1, 2, 3, 5), rect.value());
+ EXPECT_EQ(CFX_FloatRect(1, 2, 3, 5), path.GetBoundingBox());
+
+ const CFX_Matrix kScaleMatrix(1, 0, 0, 2, 60, 70);
+ rect = path.GetRect(&kScaleMatrix);
+ ASSERT_TRUE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(61, 74, 63, 80), rect.value());
+ EXPECT_EQ(CFX_FloatRect(1, 2, 3, 5), path.GetBoundingBox());
+
+ path.Clear();
+ EXPECT_EQ(0u, path.GetPoints().size());
+ EXPECT_FALSE(path.IsRect());
+ EXPECT_EQ(CFX_FloatRect(), path.GetBoundingBox());
+
+ // 4 points without a closed path makes a rect.
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kMove);
+ path.AppendPoint({0, 1}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({1, 1}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({1, 0}, CFX_Path::Point::Type::kLine);
+ EXPECT_EQ(4u, path.GetPoints().size());
+ EXPECT_TRUE(path.IsRect());
+ rect = path.GetRect(nullptr);
+ ASSERT_TRUE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 1, 1), rect.value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 1, 1), path.GetBoundingBox());
+
+ // 4 points with a closed path also makes a rect.
+ path.ClosePath();
+ EXPECT_EQ(4u, path.GetPoints().size());
+ EXPECT_TRUE(path.IsRect());
+ rect = path.GetRect(nullptr);
+ ASSERT_TRUE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 1, 1), rect.value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 1, 1), path.GetBoundingBox());
+
+ path.Transform(kScaleMatrix);
+ EXPECT_TRUE(path.IsRect());
+ rect = path.GetRect(nullptr);
+ ASSERT_TRUE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(60, 70, 61, 72), rect.value());
+ EXPECT_EQ(CFX_FloatRect(60, 70, 61, 72), path.GetBoundingBox());
+
+ path.Clear();
+ path.AppendFloatRect({1, 2, 3, 5});
+ EXPECT_TRUE(path.IsRect());
+ rect = path.GetRect(nullptr);
+ ASSERT_TRUE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(1, 2, 3, 5), rect.value());
+ EXPECT_EQ(CFX_FloatRect(1, 2, 3, 5), path.GetBoundingBox());
+}
+
+TEST(CFX_Path, ShearTransform) {
+ CFX_Path path;
+ path.AppendRect(/*left=*/1, /*bottom=*/2, /*right=*/3, /*top=*/5);
+
+ const CFX_Matrix kShearMatrix(1, 2, 0, 1, 0, 0);
+ EXPECT_TRUE(path.IsRect());
+ absl::optional<CFX_FloatRect> rect = path.GetRect(&kShearMatrix);
+ EXPECT_FALSE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(1, 2, 3, 5), path.GetBoundingBox());
+
+ path.Transform(kShearMatrix);
+ EXPECT_FALSE(path.IsRect());
+ rect = path.GetRect(nullptr);
+ EXPECT_FALSE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(1, 4, 3, 11), path.GetBoundingBox());
+
+ const CFX_Matrix shear_inverse_matrix = kShearMatrix.GetInverse();
+ rect = path.GetRect(&shear_inverse_matrix);
+ ASSERT_TRUE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(1, 2, 3, 5), rect.value());
+ EXPECT_EQ(CFX_FloatRect(1, 4, 3, 11), path.GetBoundingBox());
+
+ path.Transform(shear_inverse_matrix);
+ EXPECT_TRUE(path.IsRect());
+ rect = path.GetRect(nullptr);
+ ASSERT_TRUE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(1, 2, 3, 5), rect.value());
+ EXPECT_EQ(CFX_FloatRect(1, 2, 3, 5), path.GetBoundingBox());
+}
+
+TEST(CFX_Path, Hexagon) {
+ CFX_Path path;
+ path.AppendPoint({1, 0}, CFX_Path::Point::Type::kMove);
+ path.AppendPoint({2, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({3, 1}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({2, 2}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({1, 2}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 1}, CFX_Path::Point::Type::kLine);
+ ASSERT_EQ(6u, path.GetPoints().size());
+ EXPECT_EQ(CFX_Path::Point::Type::kLine, path.GetType(5));
+ EXPECT_FALSE(path.IsClosingFigure(5));
+ EXPECT_FALSE(path.IsRect());
+ EXPECT_FALSE(path.GetRect(nullptr).has_value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 3, 2), path.GetBoundingBox());
+
+ path.ClosePath();
+ ASSERT_EQ(6u, path.GetPoints().size());
+ EXPECT_EQ(CFX_Path::Point::Type::kLine, path.GetType(5));
+ EXPECT_TRUE(path.IsClosingFigure(5));
+ EXPECT_FALSE(path.IsRect());
+ EXPECT_FALSE(path.GetRect(nullptr).has_value());
+
+ // Calling ClosePath() repeatedly makes no difference.
+ path.ClosePath();
+ ASSERT_EQ(6u, path.GetPoints().size());
+ EXPECT_EQ(CFX_Path::Point::Type::kLine, path.GetType(5));
+ EXPECT_TRUE(path.IsClosingFigure(5));
+ EXPECT_FALSE(path.IsRect());
+ EXPECT_FALSE(path.GetRect(nullptr).has_value());
+
+ // A hexagon with the same start/end point is still not a rectangle.
+ path.Clear();
+ path.AppendPoint({1, 0}, CFX_Path::Point::Type::kMove);
+ path.AppendPoint({2, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({3, 1}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({2, 2}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({1, 2}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 1}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({1, 0}, CFX_Path::Point::Type::kLine);
+ EXPECT_FALSE(path.IsRect());
+ EXPECT_FALSE(path.GetRect(nullptr).has_value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 3, 2), path.GetBoundingBox());
+}
+
+TEST(CFX_Path, ClosePath) {
+ CFX_Path path;
+ path.AppendLine({0, 0}, {0, 1});
+ path.AppendLine({0, 1}, {1, 1});
+ path.AppendLine({1, 1}, {1, 0});
+ ASSERT_EQ(4u, path.GetPoints().size());
+ EXPECT_EQ(CFX_Path::Point::Type::kLine, path.GetType(3));
+ EXPECT_FALSE(path.IsClosingFigure(3));
+ EXPECT_TRUE(path.IsRect());
+ absl::optional<CFX_FloatRect> rect = path.GetRect(nullptr);
+ ASSERT_TRUE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 1, 1), rect.value());
+
+ const CFX_Matrix kIdentityMatrix;
+ ASSERT_TRUE(kIdentityMatrix.IsIdentity());
+ rect = path.GetRect(&kIdentityMatrix);
+ ASSERT_TRUE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 1, 1), rect.value());
+
+ path.ClosePath();
+ ASSERT_EQ(4u, path.GetPoints().size());
+ EXPECT_EQ(CFX_Path::Point::Type::kLine, path.GetType(3));
+ EXPECT_TRUE(path.IsClosingFigure(3));
+ EXPECT_TRUE(path.IsRect());
+ rect = path.GetRect(nullptr);
+ ASSERT_TRUE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 1, 1), rect.value());
+
+ // Calling ClosePath() repeatedly makes no difference.
+ path.ClosePath();
+ ASSERT_EQ(4u, path.GetPoints().size());
+ EXPECT_EQ(CFX_Path::Point::Type::kLine, path.GetType(3));
+ EXPECT_TRUE(path.IsClosingFigure(3));
+ EXPECT_TRUE(path.IsRect());
+ rect = path.GetRect(nullptr);
+ ASSERT_TRUE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 1, 1), rect.value());
+
+ path.AppendPointAndClose({0, 0}, CFX_Path::Point::Type::kLine);
+ ASSERT_EQ(5u, path.GetPoints().size());
+ EXPECT_EQ(CFX_Path::Point::Type::kLine, path.GetType(3));
+ EXPECT_TRUE(path.IsClosingFigure(3));
+ EXPECT_EQ(CFX_Path::Point::Type::kLine, path.GetType(4));
+ EXPECT_TRUE(path.IsClosingFigure(4));
+ EXPECT_TRUE(path.IsRect());
+ rect = path.GetRect(nullptr);
+ ASSERT_TRUE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 1, 1), rect.value());
+}
+
+TEST(CFX_Path, FivePointRect) {
+ CFX_Path path;
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kMove);
+ path.AppendPoint({2, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({2, 1}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 1}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kLine);
+ ASSERT_EQ(5u, path.GetPoints().size());
+ EXPECT_EQ(CFX_Path::Point::Type::kLine, path.GetType(4));
+ EXPECT_FALSE(path.IsClosingFigure(4));
+ EXPECT_TRUE(path.IsRect());
+ absl::optional<CFX_FloatRect> rect = path.GetRect(nullptr);
+ ASSERT_TRUE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 2, 1), rect.value());
+
+ path.ClosePath();
+ ASSERT_EQ(5u, path.GetPoints().size());
+ EXPECT_EQ(CFX_Path::Point::Type::kLine, path.GetType(4));
+ EXPECT_TRUE(path.IsClosingFigure(4));
+ EXPECT_TRUE(path.IsRect());
+ rect = path.GetRect(nullptr);
+ ASSERT_TRUE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 2, 1), rect.value());
+}
+
+TEST(CFX_Path, SixPlusPointRect) {
+ CFX_Path path;
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kMove);
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({2, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({2, 1}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 1}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kLine);
+ EXPECT_TRUE(path.IsRect());
+ absl::optional<CFX_FloatRect> rect = path.GetRect(nullptr);
+ ASSERT_TRUE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 2, 1), rect.value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 2, 1), path.GetBoundingBox());
+
+ path.Clear();
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kMove);
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({2, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({2, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({2, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({2, 1}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 1}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kLine);
+ EXPECT_TRUE(path.IsRect());
+ rect = path.GetRect(nullptr);
+ ASSERT_TRUE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 2, 1), rect.value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 2, 1), path.GetBoundingBox());
+}
+
+TEST(CFX_Path, NotRect) {
+ CFX_Path path;
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kMove);
+ path.AppendPoint({2, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({2, 1}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 1}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 0.1f}, CFX_Path::Point::Type::kLine);
+ EXPECT_FALSE(path.IsRect());
+ absl::optional<CFX_FloatRect> rect = path.GetRect(nullptr);
+ EXPECT_FALSE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 2, 1), path.GetBoundingBox());
+
+ path.ClosePath();
+ EXPECT_FALSE(path.IsRect());
+ rect = path.GetRect(nullptr);
+ EXPECT_FALSE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 2, 1), path.GetBoundingBox());
+
+ path.Clear();
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kMove);
+ path.AppendPoint({2, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({3, 1}, CFX_Path::Point::Type::kLine);
+ path.AppendPointAndClose({0, 1}, CFX_Path::Point::Type::kLine);
+ EXPECT_FALSE(path.IsRect());
+ rect = path.GetRect(nullptr);
+ EXPECT_FALSE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 3, 1), path.GetBoundingBox());
+
+ path.Clear();
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kMove);
+ path.AppendPoint({2, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({2, 1}, CFX_Path::Point::Type::kLine);
+ path.AppendPointAndClose({0, 1}, CFX_Path::Point::Type::kMove);
+ EXPECT_FALSE(path.IsRect());
+ rect = path.GetRect(nullptr);
+ EXPECT_FALSE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 2, 1), path.GetBoundingBox());
+
+ path.Clear();
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kMove);
+ path.AppendPoint({2, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({3, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPointAndClose({0, 1}, CFX_Path::Point::Type::kLine);
+ EXPECT_FALSE(path.IsRect());
+ rect = path.GetRect(nullptr);
+ EXPECT_FALSE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 3, 1), path.GetBoundingBox());
+
+ path.Clear();
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kMove);
+ path.AppendPoint({2, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 1}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kLine);
+ EXPECT_FALSE(path.IsRect());
+ rect = path.GetRect(nullptr);
+ EXPECT_FALSE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 2, 1), path.GetBoundingBox());
+
+ path.Clear();
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kMove);
+ path.AppendPoint({2, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({2, 1}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({2, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kLine);
+ EXPECT_FALSE(path.IsRect());
+ rect = path.GetRect(nullptr);
+ EXPECT_FALSE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 2, 1), path.GetBoundingBox());
+
+ path.Clear();
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kMove);
+ path.AppendPoint({2, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({2, 1}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({2, 2}, CFX_Path::Point::Type::kLine);
+ EXPECT_FALSE(path.IsRect());
+ rect = path.GetRect(nullptr);
+ EXPECT_FALSE(rect.has_value());
+ const CFX_Matrix kScaleMatrix(1, 0, 0, 2, 60, 70);
+ rect = path.GetRect(&kScaleMatrix);
+ EXPECT_FALSE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 2, 2), path.GetBoundingBox());
+}
+
+TEST(CFX_Path, EmptyRect) {
+ // Document existing behavior where an empty rect is still considered a rect.
+ CFX_Path path;
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kMove);
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 1}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 1}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kLine);
+ EXPECT_TRUE(path.IsRect());
+ absl::optional<CFX_FloatRect> rect = path.GetRect(nullptr);
+ ASSERT_TRUE(rect.has_value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 0, 1), rect.value());
+ EXPECT_EQ(CFX_FloatRect(0, 0, 0, 1), path.GetBoundingBox());
+}
+
+TEST(CFX_Path, Append) {
+ CFX_Path path;
+ path.AppendPoint({5, 6}, CFX_Path::Point::Type::kMove);
+ ASSERT_EQ(1u, path.GetPoints().size());
+ EXPECT_EQ(CFX_PointF(5, 6), path.GetPoint(0));
+
+ CFX_Path empty_path;
+ path.Append(empty_path, nullptr);
+ ASSERT_EQ(1u, path.GetPoints().size());
+ EXPECT_EQ(CFX_PointF(5, 6), path.GetPoint(0));
+
+ path.Append(path, nullptr);
+ ASSERT_EQ(2u, path.GetPoints().size());
+ EXPECT_EQ(CFX_PointF(5, 6), path.GetPoint(0));
+ EXPECT_EQ(CFX_PointF(5, 6), path.GetPoint(1));
+
+ const CFX_Matrix kScaleMatrix(1, 0, 0, 2, 60, 70);
+ path.Append(path, &kScaleMatrix);
+ ASSERT_EQ(4u, path.GetPoints().size());
+ EXPECT_EQ(CFX_PointF(5, 6), path.GetPoint(0));
+ EXPECT_EQ(CFX_PointF(5, 6), path.GetPoint(1));
+ EXPECT_EQ(CFX_PointF(65, 82), path.GetPoint(2));
+ EXPECT_EQ(CFX_PointF(65, 82), path.GetPoint(3));
+}
+
+TEST(CFX_Path, GetBoundingBoxForStrokePath) {
+ static constexpr float kLineWidth = 1.0f;
+ static constexpr float kMiterLimit = 1.0f;
+
+ {
+ // Test the case that the first/last point is "move" and it closes the
+ // paths.
+ CFX_Path path;
+ path.AppendPoint({2, 0}, CFX_Path::Point::Type::kMove);
+ path.ClosePath();
+ EXPECT_EQ(CFX_FloatRect(2, 0, 2, 0),
+ path.GetBoundingBoxForStrokePath(kLineWidth, kMiterLimit));
+ }
+
+ {
+ // Test on a regular rect path.
+ CFX_Path path;
+ path.AppendPoint({2, 0}, CFX_Path::Point::Type::kMove);
+ path.AppendPoint({2, 1}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 1}, CFX_Path::Point::Type::kLine);
+ path.AppendPoint({0, 0}, CFX_Path::Point::Type::kLine);
+ path.ClosePath();
+ EXPECT_EQ(CFX_FloatRect(-1, -1, 3, 2),
+ path.GetBoundingBoxForStrokePath(kLineWidth, kMiterLimit));
+
+ // If the final point is "move" and the path remains open, it should not
+ // affect the bounding rect.
+ path.AppendPoint({20, 20}, CFX_Path::Point::Type::kMove);
+ EXPECT_EQ(CFX_FloatRect(-1, -1, 3, 2),
+ path.GetBoundingBoxForStrokePath(kLineWidth, kMiterLimit));
+ }
+}