mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 16:37:35 +00:00
LibWeb: Extract CanvasTransform class from CRC2D
The implementation of this got a little funky, because it has to access methods from CanvasState.
This commit is contained in:
parent
08e6071ebb
commit
aa87b9699e
5 changed files with 101 additions and 69 deletions
84
Userland/Libraries/LibWeb/HTML/Canvas/CanvasTransform.h
Normal file
84
Userland/Libraries/LibWeb/HTML/Canvas/CanvasTransform.h
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020-2022, Andreas Kling <kling@serenityos.org>
|
||||||
|
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
|
||||||
|
* Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/Debug.h>
|
||||||
|
#include <LibWeb/HTML/Canvas/CanvasState.h>
|
||||||
|
|
||||||
|
namespace Web::HTML {
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/canvas.html#canvastransform
|
||||||
|
template<typename IncludingClass>
|
||||||
|
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<float>(a), static_cast<float>(b), static_cast<float>(c), static_cast<float>(d), static_cast<float>(e), static_cast<float>(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<IncludingClass&>(*this).drawing_state(); }
|
||||||
|
CanvasState::DrawingState const& my_drawing_state() const { return reinterpret_cast<IncludingClass const&>(*this).drawing_state(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
12
Userland/Libraries/LibWeb/HTML/Canvas/CanvasTransform.idl
Normal file
12
Userland/Libraries/LibWeb/HTML/Canvas/CanvasTransform.idl
Normal file
|
@ -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();
|
||||||
|
};
|
|
@ -263,24 +263,6 @@ DOM::ExceptionOr<void> CanvasRenderingContext2D::draw_image(CanvasImageSource co
|
||||||
return {};
|
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&)
|
void CanvasRenderingContext2D::did_draw(Gfx::FloatRect const&)
|
||||||
{
|
{
|
||||||
// FIXME: Make use of the rect to reduce the invalidated area when possible.
|
// FIXME: Make use of the rect to reduce the invalidated area when possible.
|
||||||
|
@ -601,41 +583,6 @@ NonnullRefPtr<CanvasGradient> CanvasRenderingContext2D::create_conic_gradient(do
|
||||||
return CanvasGradient::create_conic(start_angle, x, y);
|
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<float>(a), static_cast<float>(b), static_cast<float>(c), static_cast<float>(d), static_cast<float>(e), static_cast<float>(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()
|
void CanvasRenderingContext2D::clip()
|
||||||
{
|
{
|
||||||
// FIXME: Implement.
|
// FIXME: Implement.
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <LibWeb/DOM/ExceptionOr.h>
|
#include <LibWeb/DOM/ExceptionOr.h>
|
||||||
#include <LibWeb/HTML/Canvas/CanvasPath.h>
|
#include <LibWeb/HTML/Canvas/CanvasPath.h>
|
||||||
#include <LibWeb/HTML/Canvas/CanvasState.h>
|
#include <LibWeb/HTML/Canvas/CanvasState.h>
|
||||||
|
#include <LibWeb/HTML/Canvas/CanvasTransform.h>
|
||||||
#include <LibWeb/HTML/CanvasGradient.h>
|
#include <LibWeb/HTML/CanvasGradient.h>
|
||||||
#include <LibWeb/Layout/InlineNode.h>
|
#include <LibWeb/Layout/InlineNode.h>
|
||||||
#include <LibWeb/Layout/LineBox.h>
|
#include <LibWeb/Layout/LineBox.h>
|
||||||
|
@ -32,7 +33,8 @@ class CanvasRenderingContext2D
|
||||||
: public RefCountForwarder<HTMLCanvasElement>
|
: public RefCountForwarder<HTMLCanvasElement>
|
||||||
, public Bindings::Wrappable
|
, public Bindings::Wrappable
|
||||||
, public CanvasPath
|
, public CanvasPath
|
||||||
, public CanvasState {
|
, public CanvasState
|
||||||
|
, public CanvasTransform<CanvasRenderingContext2D> {
|
||||||
|
|
||||||
AK_MAKE_NONCOPYABLE(CanvasRenderingContext2D);
|
AK_MAKE_NONCOPYABLE(CanvasRenderingContext2D);
|
||||||
AK_MAKE_NONMOVABLE(CanvasRenderingContext2D);
|
AK_MAKE_NONMOVABLE(CanvasRenderingContext2D);
|
||||||
|
@ -57,10 +59,6 @@ public:
|
||||||
DOM::ExceptionOr<void> draw_image(CanvasImageSource const&, float destination_x, float destination_y, float destination_width, float destination_height);
|
DOM::ExceptionOr<void> draw_image(CanvasImageSource const&, float destination_x, float destination_y, float destination_width, float destination_height);
|
||||||
DOM::ExceptionOr<void> 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);
|
DOM::ExceptionOr<void> 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; }
|
void set_line_width(float line_width) { drawing_state().line_width = line_width; }
|
||||||
float line_width() const { return drawing_state().line_width; }
|
float line_width() const { return drawing_state().line_width; }
|
||||||
|
|
||||||
|
@ -88,9 +86,6 @@ public:
|
||||||
NonnullRefPtr<CanvasGradient> create_linear_gradient(double x0, double y0, double x1, double y1);
|
NonnullRefPtr<CanvasGradient> create_linear_gradient(double x0, double y0, double x1, double y1);
|
||||||
NonnullRefPtr<CanvasGradient> create_conic_gradient(double start_angle, double x, double y);
|
NonnullRefPtr<CanvasGradient> 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();
|
void clip();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#import <HTML/CanvasGradient.idl>
|
#import <HTML/CanvasGradient.idl>
|
||||||
#import <HTML/Canvas/CanvasPath.idl>
|
#import <HTML/Canvas/CanvasPath.idl>
|
||||||
#import <HTML/Canvas/CanvasState.idl>
|
#import <HTML/Canvas/CanvasState.idl>
|
||||||
|
#import <HTML/Canvas/CanvasTransform.idl>
|
||||||
#import <HTML/Path2D.idl>
|
#import <HTML/Path2D.idl>
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/canvas.html#canvasrenderingcontext2d
|
// 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 strokeRect(double x, double y, double w, double h);
|
||||||
undefined clearRect(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();
|
undefined beginPath();
|
||||||
// FIXME: `DOMString` should be `CanvasFillRule`
|
// FIXME: `DOMString` should be `CanvasFillRule`
|
||||||
undefined fill(optional DOMString fillRule = "nonzero");
|
undefined fill(optional DOMString fillRule = "nonzero");
|
||||||
|
@ -50,10 +47,6 @@ interface CanvasRenderingContext2D {
|
||||||
CanvasGradient createLinearGradient(double x0, double y0, double x1, double y1);
|
CanvasGradient createLinearGradient(double x0, double y0, double x1, double y1);
|
||||||
CanvasGradient createConicGradient(double startAngle, double x, double y);
|
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(optional CanvasFillRule fillRule = "nonzero");
|
||||||
// undefined clip(Path2D path, optional CanvasFillRule fillRule = "nonzero");
|
// undefined clip(Path2D path, optional CanvasFillRule fillRule = "nonzero");
|
||||||
// FIXME: Replace this with the two definitions above.
|
// FIXME: Replace this with the two definitions above.
|
||||||
|
@ -62,4 +55,5 @@ interface CanvasRenderingContext2D {
|
||||||
};
|
};
|
||||||
|
|
||||||
CanvasRenderingContext2D includes CanvasState;
|
CanvasRenderingContext2D includes CanvasState;
|
||||||
|
CanvasRenderingContext2D includes CanvasTransform;
|
||||||
CanvasRenderingContext2D includes CanvasPath;
|
CanvasRenderingContext2D includes CanvasPath;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue