Sfoglia il codice sorgente

LibPDF: Fix paths with negatively sized `re` (rect) commands

Turns out the width/height in a `re` command can be negative. This
results in rectangles with different winding orders. For example, a
negative width results in a reversed winding order.

Previously, this was lost by passing the rect through an
`AffineTransform` before constructing the path. So instead, this
constructs the rect path, and then transforms the resulting path.
MacDue 1 anno fa
parent
commit
d55867e563

+ 9 - 1
Userland/Libraries/LibPDF/Renderer.cpp

@@ -283,7 +283,10 @@ RENDERER_HANDLER(path_close)
 RENDERER_HANDLER(path_append_rect)
 {
     auto rect = Gfx::FloatRect(args[0].to_float(), args[1].to_float(), args[2].to_float(), args[3].to_float());
-    rect_path(m_current_path, map(rect));
+    // Note: The path of the rectangle is mapped (rather than the rectangle).
+    // This is because negative width/heights are possible, and result in different
+    // winding orders, but this is lost by Gfx::AffineTransform::map().
+    m_current_path.append_path(map(rect_path(rect)));
     return {};
 }
 
@@ -933,6 +936,11 @@ Gfx::Rect<T> Renderer::map(Gfx::Rect<T> rect) const
     return state().ctm.map(rect);
 }
 
+Gfx::Path Renderer::map(Gfx::Path const& path) const
+{
+    return path.copy_transformed(state().ctm);
+}
+
 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

@@ -155,6 +155,8 @@ private:
     template<typename T>
     ALWAYS_INLINE Gfx::Rect<T> map(Gfx::Rect<T>) const;
 
+    Gfx::Path map(Gfx::Path const&) const;
+
     Gfx::AffineTransform calculate_image_space_transformation(int width, int height);
 
     PDFErrorOr<NonnullRefPtr<PDFFont>> get_font(FontCacheKey const&);