瀏覽代碼

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.
Nico Weber 1 年之前
父節點
當前提交
24951a039e
共有 1 個文件被更改,包括 18 次插入2 次删除
  1. 18 2
      Userland/Libraries/LibPDF/Renderer.cpp

+ 18 - 2
Userland/Libraries/LibPDF/Renderer.cpp

@@ -388,22 +388,38 @@ RENDERER_HANDLER(path_fill_evenodd)
 
 
 RENDERER_HANDLER(path_fill_stroke_nonzero)
 RENDERER_HANDLER(path_fill_stroke_nonzero)
 {
 {
+    begin_path_paint();
     if (state().stroke_style.has<NonnullRefPtr<Gfx::PaintStyle>>()) {
     if (state().stroke_style.has<NonnullRefPtr<Gfx::PaintStyle>>()) {
         m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<NonnullRefPtr<Gfx::PaintStyle>>(), line_width());
         m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<NonnullRefPtr<Gfx::PaintStyle>>(), line_width());
     } else {
     } else {
         m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<Color>(), line_width());
         m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<Color>(), line_width());
     }
     }
-    return handle_path_fill_nonzero(args);
+    m_current_path.close_all_subpaths();
+    if (state().paint_style.has<NonnullRefPtr<Gfx::PaintStyle>>()) {
+        m_anti_aliasing_painter.fill_path(m_current_path, state().paint_style.get<NonnullRefPtr<Gfx::PaintStyle>>(), 1.0, Gfx::Painter::WindingRule::Nonzero);
+    } else {
+        m_anti_aliasing_painter.fill_path(m_current_path, state().paint_style.get<Color>(), Gfx::Painter::WindingRule::Nonzero);
+    }
+    end_path_paint();
+    return {};
 }
 }
 
 
 RENDERER_HANDLER(path_fill_stroke_evenodd)
 RENDERER_HANDLER(path_fill_stroke_evenodd)
 {
 {
+    begin_path_paint();
     if (state().stroke_style.has<NonnullRefPtr<Gfx::PaintStyle>>()) {
     if (state().stroke_style.has<NonnullRefPtr<Gfx::PaintStyle>>()) {
         m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<NonnullRefPtr<Gfx::PaintStyle>>(), line_width());
         m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<NonnullRefPtr<Gfx::PaintStyle>>(), line_width());
     } else {
     } else {
         m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<Color>(), line_width());
         m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<Color>(), line_width());
     }
     }
-    return handle_path_fill_evenodd(args);
+    m_current_path.close_all_subpaths();
+    if (state().paint_style.has<NonnullRefPtr<Gfx::PaintStyle>>()) {
+        m_anti_aliasing_painter.fill_path(m_current_path, state().paint_style.get<NonnullRefPtr<Gfx::PaintStyle>>(), 1.0, Gfx::Painter::WindingRule::EvenOdd);
+    } else {
+        m_anti_aliasing_painter.fill_path(m_current_path, state().paint_style.get<Color>(), Gfx::Painter::WindingRule::EvenOdd);
+    }
+    end_path_paint();
+    return {};
 }
 }
 
 
 RENDERER_HANDLER(path_close_fill_stroke_nonzero)
 RENDERER_HANDLER(path_close_fill_stroke_nonzero)