From d4d7feffcaa8f1dd691c19cf46187ce3bb2ad235 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 17 Aug 2024 08:19:30 +0200 Subject: [PATCH] LibWeb: Compensate for CRC2D transform in internal stored path The CRC2D path should be unaffected by the CRC2D transform changing. To achieve this, we transform the path to compensate whenever the CRC2D transform is changed. --- .../LibWeb/HTML/Canvas/CanvasTransform.h | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasTransform.h b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasTransform.h index 1c59062c498..a938b90a2e2 100644 --- a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasTransform.h +++ b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasTransform.h @@ -11,6 +11,7 @@ #include #include #include +#include #include namespace Web::HTML { @@ -21,6 +22,8 @@ class CanvasTransform { public: ~CanvasTransform() = default; + Gfx::Path& mutable_path() { return static_cast(*this).path(); } + void scale(float sx, float sy) { dbgln_if(CANVAS_RENDERING_CONTEXT_2D_DEBUG, "CanvasTransform::scale({}, {})", sx, sy); @@ -28,6 +31,7 @@ public: return; my_drawing_state().transform.scale(sx, sy); flush_transform(); + mutable_path().transform(Gfx::AffineTransform().scale(1.0 / sx, 1.0 / sy)); } void translate(float tx, float ty) @@ -37,6 +41,7 @@ public: return; my_drawing_state().transform.translate(tx, ty); flush_transform(); + mutable_path().transform(Gfx::AffineTransform().translate(-tx, -ty)); } void rotate(float radians) @@ -46,6 +51,7 @@ public: return; my_drawing_state().transform.rotate_radians(radians); flush_transform(); + mutable_path().transform(Gfx::AffineTransform().rotate_radians(-radians)); } // https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-transform @@ -59,7 +65,12 @@ public: // a c e // b d f // 0 0 1 - my_drawing_state().transform.multiply({ static_cast(a), static_cast(b), static_cast(c), static_cast(d), static_cast(e), static_cast(f) }); + auto transform = Gfx::AffineTransform(a, b, c, d, e, f); + my_drawing_state().transform.multiply(transform); + + if (auto inverse = transform.inverse(); inverse.has_value()) { + mutable_path().transform(inverse.value()); + } flush_transform(); } @@ -98,9 +109,14 @@ public: if (!isfinite(matrix->m11()) || !isfinite(matrix->m12()) || !isfinite(matrix->m21()) || !isfinite(matrix->m22()) || !isfinite(matrix->m41()) || !isfinite(matrix->m42())) return {}; + auto original_transform = my_drawing_state().transform; + // 3. Reset the current transformation matrix to matrix. auto transform = Gfx::AffineTransform { static_cast(matrix->a()), static_cast(matrix->b()), static_cast(matrix->c()), static_cast(matrix->d()), static_cast(matrix->e()), static_cast(matrix->f()) }; my_drawing_state().transform = transform; + + mutable_path().transform(original_transform); + flush_transform(); return {}; }