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.
This commit is contained in:
Nico Weber 2024-02-20 21:38:45 -05:00 committed by Jelle Raaijmakers
parent 0dde88d714
commit fa95e5ec0e
Notes: sideshowbarker 2024-07-17 23:00:03 +09:00
2 changed files with 17 additions and 6 deletions

View file

@ -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

View file

@ -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&);