diff --git a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasTransform.h b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasTransform.h new file mode 100644 index 0000000000..6a73a5939b --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasTransform.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2020-2022, Andreas Kling + * Copyright (c) 2021-2022, Linus Groh + * Copyright (c) 2022, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Web::HTML { + +// https://html.spec.whatwg.org/multipage/canvas.html#canvastransform +template +class CanvasTransform { +public: + ~CanvasTransform() = default; + + void scale(float sx, float sy) + { + dbgln_if(CANVAS_RENDERING_CONTEXT_2D_DEBUG, "CanvasTransform::scale({}, {})", sx, sy); + + my_drawing_state().transform.scale(sx, sy); + } + + void translate(float tx, float ty) + { + dbgln_if(CANVAS_RENDERING_CONTEXT_2D_DEBUG, "CanvasTransform::translate({}, {})", tx, ty); + my_drawing_state().transform.translate(tx, ty); + } + + void rotate(float radians) + { + dbgln_if(CANVAS_RENDERING_CONTEXT_2D_DEBUG, "CanvasTransform::rotate({})", radians); + my_drawing_state().transform.rotate_radians(radians); + } + + // https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-transform + void transform(double a, double b, double c, double d, double e, double f) + { + // 1. If any of the arguments are infinite or NaN, then return. + if (!isfinite(a) || !isfinite(b) || !isfinite(c) || !isfinite(d) || !isfinite(e) || !isfinite(f)) + return; + + // 2. Replace the current transformation matrix with the result of multiplying the current transformation matrix with the matrix described by: + // 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) }); + } + + // https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-settransform + void set_transform(double a, double b, double c, double d, double e, double f) + { + // 1. If any of the arguments are infinite or NaN, then return. + if (!isfinite(a) || !isfinite(b) || !isfinite(c) || !isfinite(d) || !isfinite(e) || !isfinite(f)) + return; + + // 2. Reset the current transformation matrix to the identity matrix. + my_drawing_state().transform = {}; + + // 3. Invoke the transform(a, b, c, d, e, f) method with the same arguments. + transform(a, b, c, d, e, f); + } + + // https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-resettransform + void reset_transform() + { + // The resetTransform() method, when invoked, must reset the current transformation matrix to the identity matrix. + my_drawing_state().transform = {}; + } + +protected: + CanvasTransform() = default; + +private: + CanvasState::DrawingState& my_drawing_state() { return reinterpret_cast(*this).drawing_state(); } + CanvasState::DrawingState const& my_drawing_state() const { return reinterpret_cast(*this).drawing_state(); } +}; + +} diff --git a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasTransform.idl b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasTransform.idl new file mode 100644 index 0000000000..423b10ba86 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasTransform.idl @@ -0,0 +1,12 @@ +// https://html.spec.whatwg.org/multipage/canvas.html#canvastransform +interface mixin CanvasTransform { + undefined scale(unrestricted double x, unrestricted double y); + undefined rotate(unrestricted double radians); + undefined translate(unrestricted double x, unrestricted double y); + undefined transform(unrestricted double a, unrestricted double b, unrestricted double c, unrestricted double d, unrestricted double e, unrestricted double f); + + // FIXME: [NewObject] DOMMatrix getTransform(); + undefined setTransform(unrestricted double a, unrestricted double b, unrestricted double c, unrestricted double d, unrestricted double e, unrestricted double f); + // FIXME: undefined setTransform(optional DOMMatrix2DInit transform = {}); + undefined resetTransform(); +}; diff --git a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp index 08d42cb396..d20449d17e 100644 --- a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp +++ b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp @@ -263,24 +263,6 @@ DOM::ExceptionOr CanvasRenderingContext2D::draw_image(CanvasImageSource co return {}; } -void CanvasRenderingContext2D::scale(float sx, float sy) -{ - dbgln_if(CANVAS_RENDERING_CONTEXT_2D_DEBUG, "CanvasRenderingContext2D::scale({}, {})", sx, sy); - drawing_state().transform.scale(sx, sy); -} - -void CanvasRenderingContext2D::translate(float tx, float ty) -{ - dbgln_if(CANVAS_RENDERING_CONTEXT_2D_DEBUG, "CanvasRenderingContext2D::translate({}, {})", tx, ty); - drawing_state().transform.translate(tx, ty); -} - -void CanvasRenderingContext2D::rotate(float radians) -{ - dbgln_if(CANVAS_RENDERING_CONTEXT_2D_DEBUG, "CanvasRenderingContext2D::rotate({})", radians); - drawing_state().transform.rotate_radians(radians); -} - void CanvasRenderingContext2D::did_draw(Gfx::FloatRect const&) { // FIXME: Make use of the rect to reduce the invalidated area when possible. @@ -601,41 +583,6 @@ NonnullRefPtr CanvasRenderingContext2D::create_conic_gradient(do return CanvasGradient::create_conic(start_angle, x, y); } -// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-transform -void CanvasRenderingContext2D::transform(double a, double b, double c, double d, double e, double f) -{ - // 1. If any of the arguments are infinite or NaN, then return. - if (!isfinite(a) || !isfinite(b) || !isfinite(c) || !isfinite(d) || !isfinite(e) || !isfinite(f)) - return; - - // 2. Replace the current transformation matrix with the result of multiplying the current transformation matrix with the matrix described by: - // a c e - // b d f - // 0 0 1 - drawing_state().transform.multiply({ static_cast(a), static_cast(b), static_cast(c), static_cast(d), static_cast(e), static_cast(f) }); -} - -// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-settransform -void CanvasRenderingContext2D::set_transform(double a, double b, double c, double d, double e, double f) -{ - // 1. If any of the arguments are infinite or NaN, then return. - if (!isfinite(a) || !isfinite(b) || !isfinite(c) || !isfinite(d) || !isfinite(e) || !isfinite(f)) - return; - - // 2. Reset the current transformation matrix to the identity matrix. - drawing_state().transform = {}; - - // 3. Invoke the transform(a, b, c, d, e, f) method with the same arguments. - transform(a, b, c, d, e, f); -} - -// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-resettransform -void CanvasRenderingContext2D::reset_transform() -{ - // The resetTransform() method, when invoked, must reset the current transformation matrix to the identity matrix. - drawing_state().transform = {}; -} - void CanvasRenderingContext2D::clip() { // FIXME: Implement. diff --git a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.h b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.h index 9951dd5973..ee4c1f2b9c 100644 --- a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.h +++ b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -32,7 +33,8 @@ class CanvasRenderingContext2D : public RefCountForwarder , public Bindings::Wrappable , public CanvasPath - , public CanvasState { + , public CanvasState + , public CanvasTransform { AK_MAKE_NONCOPYABLE(CanvasRenderingContext2D); AK_MAKE_NONMOVABLE(CanvasRenderingContext2D); @@ -57,10 +59,6 @@ public: DOM::ExceptionOr draw_image(CanvasImageSource const&, float destination_x, float destination_y, float destination_width, float destination_height); DOM::ExceptionOr draw_image(CanvasImageSource const&, float source_x, float source_y, float source_width, float source_height, float destination_x, float destination_y, float destination_width, float destination_height); - void scale(float sx, float sy); - void translate(float x, float y); - void rotate(float degrees); - void set_line_width(float line_width) { drawing_state().line_width = line_width; } float line_width() const { return drawing_state().line_width; } @@ -88,9 +86,6 @@ public: NonnullRefPtr create_linear_gradient(double x0, double y0, double x1, double y1); NonnullRefPtr create_conic_gradient(double start_angle, double x, double y); - void transform(double a, double b, double c, double d, double e, double f); - void set_transform(double a, double b, double c, double d, double e, double f); - void reset_transform(); void clip(); private: diff --git a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.idl b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.idl index 041c00b770..8191f524ae 100644 --- a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.idl +++ b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.idl @@ -5,6 +5,7 @@ #import #import #import +#import #import // https://html.spec.whatwg.org/multipage/canvas.html#canvasrenderingcontext2d @@ -15,10 +16,6 @@ interface CanvasRenderingContext2D { undefined strokeRect(double x, double y, double w, double h); undefined clearRect(double x, double y, double w, double h); - undefined scale(double x, double y); - undefined translate(double x, double y); - undefined rotate(double radians); - undefined beginPath(); // FIXME: `DOMString` should be `CanvasFillRule` undefined fill(optional DOMString fillRule = "nonzero"); @@ -50,10 +47,6 @@ interface CanvasRenderingContext2D { CanvasGradient createLinearGradient(double x0, double y0, double x1, double y1); CanvasGradient createConicGradient(double startAngle, double x, double y); - undefined transform(unrestricted double a, unrestricted double b, unrestricted double c, unrestricted double d, unrestricted double e, unrestricted double f); - undefined setTransform(unrestricted double a, unrestricted double b, unrestricted double c, unrestricted double d, unrestricted double e, unrestricted double f); - undefined resetTransform(); - // undefined clip(optional CanvasFillRule fillRule = "nonzero"); // undefined clip(Path2D path, optional CanvasFillRule fillRule = "nonzero"); // FIXME: Replace this with the two definitions above. @@ -62,4 +55,5 @@ interface CanvasRenderingContext2D { }; CanvasRenderingContext2D includes CanvasState; +CanvasRenderingContext2D includes CanvasTransform; CanvasRenderingContext2D includes CanvasPath;