From 24951a039e5c66c6ff2a524be479045cce84a4d6 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Thu, 7 Mar 2024 20:02:23 -0500 Subject: [PATCH] LibPDF: Clip stroke for B / B* operators Fixes pages 17-19 on https://www.iro.umontreal.ca/~feeley/papers/ChevalierBoisvertFeeleyECOOP15.pdf Calling the fill handler after painting the stroke as previously doesn't work, since we need to set up the clip before both stroke and fill, and unset it after both. The duplication is a bit unfortunate, but also minor. --- Userland/Libraries/LibPDF/Renderer.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/Userland/Libraries/LibPDF/Renderer.cpp b/Userland/Libraries/LibPDF/Renderer.cpp index 40e121cb95..1c46b3af86 100644 --- a/Userland/Libraries/LibPDF/Renderer.cpp +++ b/Userland/Libraries/LibPDF/Renderer.cpp @@ -388,22 +388,38 @@ RENDERER_HANDLER(path_fill_evenodd) RENDERER_HANDLER(path_fill_stroke_nonzero) { + begin_path_paint(); if (state().stroke_style.has>()) { m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get>(), line_width()); } else { m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get(), line_width()); } - return handle_path_fill_nonzero(args); + m_current_path.close_all_subpaths(); + if (state().paint_style.has>()) { + m_anti_aliasing_painter.fill_path(m_current_path, state().paint_style.get>(), 1.0, Gfx::Painter::WindingRule::Nonzero); + } else { + m_anti_aliasing_painter.fill_path(m_current_path, state().paint_style.get(), Gfx::Painter::WindingRule::Nonzero); + } + end_path_paint(); + return {}; } RENDERER_HANDLER(path_fill_stroke_evenodd) { + begin_path_paint(); if (state().stroke_style.has>()) { m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get>(), line_width()); } else { m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get(), line_width()); } - return handle_path_fill_evenodd(args); + m_current_path.close_all_subpaths(); + if (state().paint_style.has>()) { + m_anti_aliasing_painter.fill_path(m_current_path, state().paint_style.get>(), 1.0, Gfx::Painter::WindingRule::EvenOdd); + } else { + m_anti_aliasing_painter.fill_path(m_current_path, state().paint_style.get(), Gfx::Painter::WindingRule::EvenOdd); + } + end_path_paint(); + return {}; } RENDERER_HANDLER(path_close_fill_stroke_nonzero)