Add helper functions in CFX_PathData::GetZeroAreaPath().
Create helper function CheckSimpleLinePath() which handles 3-point
simple line path and CheckPalindromicPath() which handles palindromic
path in CFX_PathData::GetZeroAreaPath().
Bug: pdfium:1638
Change-Id: I98c298df04c65a626a0d9cbc9c6f0804993d511a
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/77873
Commit-Queue: Hui Yingst <nigi@chromium.org>
Reviewed-by: Daniel Hosseinian <dhoss@chromium.org>
diff --git a/core/fxge/cfx_pathdata.cpp b/core/fxge/cfx_pathdata.cpp
index 7e08205..682fc56 100644
--- a/core/fxge/cfx_pathdata.cpp
+++ b/core/fxge/cfx_pathdata.cpp
@@ -12,6 +12,77 @@
namespace {
+// Returns true if the simple path contains 3 points which draw a line from
+// A->B->A and form a zero area.
+bool CheckSimpleLinePath(const std::vector<FX_PATHPOINT>& points,
+ const CFX_Matrix* matrix,
+ bool adjust,
+ CFX_PathData* new_path,
+ bool* thin,
+ bool* set_identity) {
+ if (points.size() != 3)
+ return false;
+
+ if (points[0].m_Type != FXPT_TYPE::MoveTo ||
+ points[1].m_Type != FXPT_TYPE::LineTo ||
+ points[2].m_Type != FXPT_TYPE::LineTo ||
+ points[0].m_Point != points[2].m_Point) {
+ return false;
+ }
+
+ for (size_t i = 0; i < 2; i++) {
+ CFX_PointF point = points[i].m_Point;
+ if (adjust) {
+ if (matrix)
+ point = matrix->Transform(point);
+
+ point = CFX_PointF(static_cast<int>(point.x) + 0.5f,
+ static_cast<int>(point.y) + 0.5f);
+ }
+ new_path->AppendPoint(point,
+ i == 0 ? FXPT_TYPE::MoveTo : FXPT_TYPE::LineTo);
+ }
+ if (adjust && matrix)
+ *set_identity = true;
+
+ // Note, both x and y coordinates of the end points need to be different.
+ if (points[0].m_Point.x != points[1].m_Point.x &&
+ points[0].m_Point.y != points[1].m_Point.y) {
+ *thin = true;
+ }
+ return true;
+}
+
+// Returns true if `points` is palindromic and forms zero area. Otherwise,
+// returns false.
+bool CheckPalindromicPath(const std::vector<FX_PATHPOINT>& points,
+ CFX_PathData* new_path,
+ bool* thin) {
+ if (points.size() <= 3 || !(points.size() % 2))
+ return false;
+
+ const int mid = points.size() / 2;
+ bool zero_area = true;
+ CFX_PathData temp_path;
+ for (int i = 0; i < mid; i++) {
+ if (!(points[mid - i - 1].m_Point == points[mid + i + 1].m_Point &&
+ points[mid - i - 1].m_Type != FXPT_TYPE::BezierTo &&
+ points[mid + i + 1].m_Type != FXPT_TYPE::BezierTo)) {
+ zero_area = false;
+ break;
+ }
+
+ temp_path.AppendPoint(points[mid - i].m_Point, FXPT_TYPE::MoveTo);
+ temp_path.AppendPoint(points[mid - i - 1].m_Point, FXPT_TYPE::LineTo);
+ }
+ if (!zero_area)
+ return false;
+
+ new_path->Append(&temp_path, nullptr);
+ *thin = true;
+ return true;
+}
+
bool IsFoldingVerticalLine(const CFX_PointF& a,
const CFX_PointF& b,
const CFX_PointF& c) {
@@ -327,57 +398,19 @@
bool* thin,
bool* set_identity) const {
*set_identity = false;
+
+ // TODO(crbug.com/pdfium/1639): Need to handle the case when there are
+ // only 2 points in the path that forms a zero area.
if (m_Points.size() < 3)
return false;
- if (m_Points.size() == 3 && m_Points[0].m_Type == FXPT_TYPE::MoveTo &&
- m_Points[1].m_Type == FXPT_TYPE::LineTo &&
- m_Points[2].m_Type == FXPT_TYPE::LineTo &&
- m_Points[0].m_Point == m_Points[2].m_Point) {
- for (size_t i = 0; i < 2; i++) {
- CFX_PointF point = m_Points[i].m_Point;
- if (adjust) {
- if (matrix)
- point = matrix->Transform(point);
-
- point = CFX_PointF(static_cast<int>(point.x) + 0.5f,
- static_cast<int>(point.y) + 0.5f);
- }
- new_path->AppendPoint(point,
- i == 0 ? FXPT_TYPE::MoveTo : FXPT_TYPE::LineTo);
- }
- if (adjust && matrix)
- *set_identity = true;
-
- // Note, they both have to be not equal.
- if (m_Points[0].m_Point.x != m_Points[1].m_Point.x &&
- m_Points[0].m_Point.y != m_Points[1].m_Point.y) {
- *thin = true;
- }
+ if (CheckSimpleLinePath(m_Points, matrix, adjust, new_path, thin,
+ set_identity)) {
return true;
}
- if (((m_Points.size() > 3) && (m_Points.size() % 2))) {
- int mid = m_Points.size() / 2;
- bool zero_area = true;
- CFX_PathData temp_path;
- for (int i = 0; i < mid; i++) {
- if (!(m_Points[mid - i - 1].m_Point == m_Points[mid + i + 1].m_Point &&
- m_Points[mid - i - 1].m_Type != FXPT_TYPE::BezierTo &&
- m_Points[mid + i + 1].m_Type != FXPT_TYPE::BezierTo)) {
- zero_area = false;
- break;
- }
-
- temp_path.AppendPoint(m_Points[mid - i].m_Point, FXPT_TYPE::MoveTo);
- temp_path.AppendPoint(m_Points[mid - i - 1].m_Point, FXPT_TYPE::LineTo);
- }
- if (zero_area) {
- new_path->Append(&temp_path, nullptr);
- *thin = true;
- return true;
- }
- }
+ if (CheckPalindromicPath(m_Points, new_path, thin))
+ return true;
int start_point = 0;
for (size_t i = 0; i < m_Points.size(); i++) {