| // 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(CFXPath, BasicTest) { | |
| CFX_Path path; | |
| path.AppendRect(/*left=*/1, /*bottom=*/2, /*right=*/3, /*top=*/5); | |
| EXPECT_EQ(5u, path.GetPoints().size()); | |
| EXPECT_TRUE(path.IsRect()); | |
| std::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(CFXPath, 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()); | |
| std::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(CFXPath, 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(CFXPath, 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()); | |
| std::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(CFXPath, 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()); | |
| std::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(CFXPath, 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()); | |
| std::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(CFXPath, 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()); | |
| std::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(CFXPath, 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()); | |
| std::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(CFXPath, 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(CFXPath, 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)); | |
| } | |
| } |