Parcourir la source

LibWeb: Forward CRC2D's ref count to HTMLCanvasElement

This allows HTMLCanvasElement and CRC2D to share their lifetime, as JS
allows them to arbitrarily access them at any time and CRC2D.canvas
expects a non-null return value.
Luke Wilde il y a 3 ans
Parent
commit
adf8341c4e

+ 23 - 13
Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp

@@ -25,12 +25,27 @@
 namespace Web::HTML {
 
 CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement& element)
-    : m_element(element)
+    : RefCountForwarder(element)
 {
 }
 
 CanvasRenderingContext2D::~CanvasRenderingContext2D() = default;
 
+HTMLCanvasElement& CanvasRenderingContext2D::canvas_element()
+{
+    return ref_count_target();
+}
+
+HTMLCanvasElement const& CanvasRenderingContext2D::canvas_element() const
+{
+    return ref_count_target();
+}
+
+NonnullRefPtr<HTMLCanvasElement> CanvasRenderingContext2D::canvas_for_binding() const
+{
+    return canvas_element();
+}
+
 void CanvasRenderingContext2D::set_fill_style(String style)
 {
     // FIXME: 2. If the given value is a CanvasPattern object that is marked as not origin-clean, then set this's origin-clean flag to false.
@@ -263,24 +278,19 @@ void CanvasRenderingContext2D::rotate(float radians)
 void CanvasRenderingContext2D::did_draw(Gfx::FloatRect const&)
 {
     // FIXME: Make use of the rect to reduce the invalidated area when possible.
-    if (!m_element)
+    if (!canvas_element().layout_node())
         return;
-    if (!m_element->layout_node())
-        return;
-    m_element->layout_node()->set_needs_display();
+    canvas_element().layout_node()->set_needs_display();
 }
 
 OwnPtr<Gfx::Painter> CanvasRenderingContext2D::painter()
 {
-    if (!m_element)
-        return {};
-
-    if (!m_element->bitmap()) {
-        if (!m_element->create_bitmap())
+    if (!canvas_element().bitmap()) {
+        if (!canvas_element().create_bitmap())
             return {};
     }
 
-    return make<Gfx::Painter>(*m_element->bitmap());
+    return make<Gfx::Painter>(*canvas_element().bitmap());
 }
 
 void CanvasRenderingContext2D::fill_text(String const& text, float x, float y, Optional<double> max_width)
@@ -468,9 +478,9 @@ DOM::ExceptionOr<RefPtr<ImageData>> CanvasRenderingContext2D::get_image_data(int
     auto image_data = ImageData::create_with_size(wrapper()->global_object(), width, height);
 
     // NOTE: We don't attempt to create the underlying bitmap here; if it doesn't exist, it's like copying only transparent black pixels (which is a no-op).
-    if (!m_element || !m_element->bitmap())
+    if (!canvas_element().bitmap())
         return image_data;
-    auto const& bitmap = *m_element->bitmap();
+    auto const& bitmap = *canvas_element().bitmap();
 
     // 5. Let the source rectangle be the rectangle whose corners are the four points (sx, sy), (sx+sw, sy), (sx+sw, sy+sh), (sx, sy+sh).
     auto source_rect = Gfx::Rect { x, y, width, height };

+ 5 - 4
Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.h

@@ -7,7 +7,7 @@
 
 #pragma once
 
-#include <AK/RefCounted.h>
+#include <AK/RefCountForwarder.h>
 #include <AK/Variant.h>
 #include <LibGfx/AffineTransform.h>
 #include <LibGfx/Color.h>
@@ -27,7 +27,7 @@ namespace Web::HTML {
 using CanvasImageSource = Variant<NonnullRefPtr<HTMLImageElement>, NonnullRefPtr<HTMLCanvasElement>>;
 
 class CanvasRenderingContext2D
-    : public RefCounted<CanvasRenderingContext2D>
+    : public RefCountForwarder<HTMLCanvasElement>
     , public Bindings::Wrappable {
 
     AK_MAKE_NONCOPYABLE(CanvasRenderingContext2D);
@@ -90,7 +90,7 @@ public:
 
     void reset_to_default_state();
 
-    HTMLCanvasElement* canvas() { return m_element; }
+    NonnullRefPtr<HTMLCanvasElement> canvas_for_binding() const;
 
     RefPtr<TextMetrics> measure_text(String const& text);
 
@@ -122,7 +122,8 @@ private:
 
     OwnPtr<Gfx::Painter> painter();
 
-    WeakPtr<HTMLCanvasElement> m_element;
+    HTMLCanvasElement& canvas_element();
+    HTMLCanvasElement const& canvas_element() const;
 
     // https://html.spec.whatwg.org/multipage/canvas.html#drawing-state
     struct DrawingState {

+ 1 - 1
Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.idl

@@ -47,7 +47,7 @@ interface CanvasRenderingContext2D {
     undefined reset();
     boolean isContextLost();
 
-    readonly attribute HTMLCanvasElement canvas;
+    [ImplementedAs=canvas_for_binding] readonly attribute HTMLCanvasElement canvas;
 
     TextMetrics measureText(DOMString text);