Split a path into sub paths for drawing zero area. Currently GetZeroAreaPath() is used to calculate the zero areas formed by a whole path. However, its output parameter `thin` `set_identity` can be set due to a sub path (a subset of the whole path that started with "move to" action), while affecting the rendering results of all the zero areas formed by the whole path. This CL adds the process to split the whole path into sub paths, and calls DrawZeroAreaPath() to process each sub path individually. Also add a pixel test to make sure that `set_identity` is being set for each sub path separately. Bug: pdfium:1638 Change-Id: I5492870e5c7e9254de346cc7d7c9255661e3abd2 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/78030 Commit-Queue: Hui Yingst <nigi@chromium.org> Reviewed-by: Daniel Hosseinian <dhoss@chromium.org>
diff --git a/DEPS b/DEPS index f265f12..eebc457 100644 --- a/DEPS +++ b/DEPS
@@ -89,7 +89,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling pdfium_tests # and whatever else without interference from each other. - 'pdfium_tests_revision': 'db1faf0ee5ab4e8be140dc1c0fc0031ab70a817c', + 'pdfium_tests_revision': '7adedee8c61163fb68005fdbd968f16532bb04d4', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling skia # and whatever else without interference from each other.
diff --git a/core/fxge/cfx_renderdevice.cpp b/core/fxge/cfx_renderdevice.cpp index 7130649..dcba015 100644 --- a/core/fxge/cfx_renderdevice.cpp +++ b/core/fxge/cfx_renderdevice.cpp
@@ -30,6 +30,7 @@ #include "core/fxge/text_char_pos.h" #include "core/fxge/text_glyph_pos.h" #include "third_party/base/check.h" +#include "third_party/base/check_op.h" #include "third_party/base/notreached.h" #include "third_party/base/span.h" @@ -332,6 +333,11 @@ return false; } + // A special case that all points are identical, zero area is formed and no + // thin line needs to be drawn. + if (points[0].m_Point == points[1].m_Point) + return true; + for (size_t i = 0; i < 2; i++) { CFX_PointF point = points[i].m_Point; if (adjust) { @@ -425,22 +431,21 @@ if (CheckPalindromicPath(points, new_path, thin)) return true; - int start_point = 0; for (size_t i = 0; i < points.size(); i++) { FXPT_TYPE point_type = points[i].m_Type; if (point_type == FXPT_TYPE::MoveTo) { - start_point = i; + DCHECK_EQ(0, i); continue; } if (point_type == FXPT_TYPE::BezierTo) { i += 2; + DCHECK(i < points.size()); continue; } DCHECK(point_type == FXPT_TYPE::LineTo); - int next_index = - (i + 1 - start_point) % (points.size() - start_point) + start_point; + int next_index = (i + 1) % (points.size()); const FX_PATHPOINT& next = points[next_index]; if (next.m_Type == FXPT_TYPE::BezierTo || next.m_Type == FXPT_TYPE::MoveTo) continue; @@ -691,12 +696,39 @@ return true; } } + if (fill && stroke_alpha == 0 && !fill_options.stroke && !fill_options.text_mode) { - // TODO(crbug.com/pdfium/1638): Make DrawZeroAreaPath() only process a sub - // path instead the whole path. - DrawZeroAreaPath(pPathData->GetPoints(), pObject2Device, - !!m_pDeviceDriver->GetDriverType(), + bool adjust = !!m_pDeviceDriver->GetDriverType(); + std::vector<FX_PATHPOINT> sub_path; + for (size_t i = 0; i < points.size(); i++) { + FXPT_TYPE point_type = points[i].m_Type; + if (point_type == FXPT_TYPE::MoveTo) { + // Process the exisitng sub path. + DrawZeroAreaPath(sub_path, pObject2Device, adjust, + fill_options.aliased_path, fill_color, fill_alpha, + blend_type); + sub_path.clear(); + + // Start forming the next sub path. + sub_path.push_back(points[i]); + continue; + } + + if (point_type == FXPT_TYPE::BezierTo) { + sub_path.push_back(points[i]); + sub_path.push_back(points[i + 1]); + sub_path.push_back(points[i + 2]); + i += 2; + continue; + } + + DCHECK(point_type == FXPT_TYPE::LineTo); + sub_path.push_back(points[i]); + continue; + } + // Process the last sub paths. + DrawZeroAreaPath(sub_path, pObject2Device, adjust, fill_options.aliased_path, fill_color, fill_alpha, blend_type); }
diff --git a/testing/resources/pixel/bug_1638.in b/testing/resources/pixel/bug_1638.in new file mode 100644 index 0000000..f6dea38 --- /dev/null +++ b/testing/resources/pixel/bug_1638.in
@@ -0,0 +1,57 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R +>> +endobj +{{object 2 0}} << + /Type /Pages + /Count 1 + /Kids [3 0 R] +>> +endobj +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Contents 4 0 R + /MediaBox [0 0 400 400] + /Resources << + /ExtGState << + /GS1 << + /ca 1.0 + >> + >> + >> +>> +endobj +{{object 4 0}} << + {{streamlen}} +>> +stream +q +/GS1 gs +0 0 1 rg +% The 1st sub path. +50 350 m +200 320 l +50 350 l +% The 2nd sub path. +100 300 m +50 300 l +200 300 l +300 200 l +270 230 l +% The 3rd sub path. +200 50 m +350 50 l +200 50 l +200 100 l +200 50 l +f +Q +endstream +endobj +{{xref}} +{{trailer}} +{{startxref}} +%%EOF
diff --git a/testing/resources/pixel/bug_1638_expected.pdf.0.png b/testing/resources/pixel/bug_1638_expected.pdf.0.png new file mode 100644 index 0000000..23a39d5 --- /dev/null +++ b/testing/resources/pixel/bug_1638_expected.pdf.0.png Binary files differ