Quellcode durchsuchen

LibPDF: Fix line drawing when line_width is 0

We used to skip lines with width 0. The correct behavior per spec
is to draw them one pixel wide instead.
Nico Weber vor 1 Jahr
Ursprung
Commit
fa95e5ec0e
2 geänderte Dateien mit 17 neuen und 6 gelöschten Zeilen
  1. 15 6
      Userland/Libraries/LibPDF/Renderer.cpp
  2. 2 0
      Userland/Libraries/LibPDF/Renderer.h

+ 15 - 6
Userland/Libraries/LibPDF/Renderer.cpp

@@ -327,9 +327,9 @@ RENDERER_HANDLER(path_stroke)
 {
     begin_path_paint();
     if (state().stroke_style.has<NonnullRefPtr<Gfx::PaintStyle>>()) {
-        m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<NonnullRefPtr<Gfx::PaintStyle>>(), state().ctm.x_scale() * state().line_width);
+        m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<NonnullRefPtr<Gfx::PaintStyle>>(), line_width());
     } else {
-        m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<Color>(), state().ctm.x_scale() * state().line_width);
+        m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<Color>(), line_width());
     }
     end_path_paint();
     return {};
@@ -376,9 +376,9 @@ RENDERER_HANDLER(path_fill_evenodd)
 RENDERER_HANDLER(path_fill_stroke_nonzero)
 {
     if (state().stroke_style.has<NonnullRefPtr<Gfx::PaintStyle>>()) {
-        m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<NonnullRefPtr<Gfx::PaintStyle>>(), state().ctm.x_scale() * state().line_width);
+        m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<NonnullRefPtr<Gfx::PaintStyle>>(), line_width());
     } else {
-        m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<Color>(), state().ctm.x_scale() * state().line_width);
+        m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<Color>(), line_width());
     }
     return handle_path_fill_nonzero(args);
 }
@@ -386,9 +386,9 @@ RENDERER_HANDLER(path_fill_stroke_nonzero)
 RENDERER_HANDLER(path_fill_stroke_evenodd)
 {
     if (state().stroke_style.has<NonnullRefPtr<Gfx::PaintStyle>>()) {
-        m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<NonnullRefPtr<Gfx::PaintStyle>>(), state().ctm.x_scale() * state().line_width);
+        m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<NonnullRefPtr<Gfx::PaintStyle>>(), line_width());
     } else {
-        m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<Color>(), state().ctm.x_scale() * state().line_width);
+        m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<Color>(), line_width());
     }
     return handle_path_fill_evenodd(args);
 }
@@ -953,6 +953,15 @@ Gfx::Path Renderer::map(Gfx::Path const& path) const
     return path.copy_transformed(state().ctm);
 }
 
+float Renderer::line_width() const
+{
+    // PDF 1.7 spec, 4.3.2 Details of Graphics State Parameters, Line Width:
+    // "A line width of 0 denotes the thinnest line that can be rendered at device resolution: 1 device pixel wide."
+    if (state().line_width == 0)
+        return 1;
+    return state().ctm.x_scale() * state().line_width;
+}
+
 PDFErrorOr<void> Renderer::set_graphics_state_from_dict(NonnullRefPtr<DictObject> dict)
 {
     // ISO 32000 (PDF 2.0), 8.4.5 Graphics state parameter dictionaries

+ 2 - 0
Userland/Libraries/LibPDF/Renderer.h

@@ -176,6 +176,8 @@ private:
 
     Gfx::Path map(Gfx::Path const&) const;
 
+    float line_width() const;
+
     Gfx::AffineTransform calculate_image_space_transformation(int width, int height);
 
     PDFErrorOr<NonnullRefPtr<PDFFont>> get_font(FontCacheKey const&);