Pārlūkot izejas kodu

LibWeb: Generate HTMLCanvasElement bindings from IDL :^)

Andreas Kling 5 gadi atpakaļ
vecāks
revīzija
b959d06ace

+ 0 - 106
Libraries/LibWeb/Bindings/HTMLCanvasElementWrapper.cpp

@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <AK/FlyString.h>
-#include <AK/Function.h>
-#include <LibJS/Interpreter.h>
-#include <LibJS/Runtime/GlobalObject.h>
-#include <LibJS/Runtime/PrimitiveString.h>
-#include <LibJS/Runtime/Value.h>
-#include <LibWeb/Bindings/CanvasRenderingContext2DWrapper.h>
-#include <LibWeb/Bindings/HTMLCanvasElementWrapper.h>
-#include <LibWeb/DOM/CanvasRenderingContext2D.h>
-#include <LibWeb/DOM/HTMLCanvasElement.h>
-
-namespace Web {
-namespace Bindings {
-
-HTMLCanvasElementWrapper::HTMLCanvasElementWrapper(JS::GlobalObject& global_object, HTMLCanvasElement& element)
-    : HTMLElementWrapper(global_object, element)
-{
-}
-
-void HTMLCanvasElementWrapper::initialize(JS::Interpreter& interpreter, JS::GlobalObject& global_object)
-{
-    ElementWrapper::initialize(interpreter, global_object);
-    define_native_function("getContext", get_context, 1);
-    define_native_property("width", width_getter, nullptr);
-    define_native_property("height", height_getter, nullptr);
-}
-
-HTMLCanvasElementWrapper::~HTMLCanvasElementWrapper()
-{
-}
-
-HTMLCanvasElement& HTMLCanvasElementWrapper::node()
-{
-    return static_cast<HTMLCanvasElement&>(NodeWrapper::impl());
-}
-
-const HTMLCanvasElement& HTMLCanvasElementWrapper::node() const
-{
-    return static_cast<const HTMLCanvasElement&>(NodeWrapper::impl());
-}
-
-static HTMLCanvasElement* impl_from(JS::Interpreter& interpreter, JS::GlobalObject& global_object)
-{
-    auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
-    if (!this_object)
-        return nullptr;
-    // FIXME: Verify that it's a HTMLCanvasElementWrapper somehow!
-    return &static_cast<HTMLCanvasElementWrapper*>(this_object)->node();
-}
-
-JS_DEFINE_NATIVE_FUNCTION(HTMLCanvasElementWrapper::get_context)
-{
-    auto* impl = impl_from(interpreter, global_object);
-    if (!impl)
-        return {};
-    auto context_type = interpreter.argument(0).to_string(interpreter);
-    if (interpreter.exception())
-        return {};
-    if (context_type != "2d")
-        return JS::js_null();
-    auto* context = impl->get_context(context_type);
-    return wrap(interpreter.heap(), *context);
-}
-
-JS_DEFINE_NATIVE_GETTER(HTMLCanvasElementWrapper::width_getter)
-{
-    if (auto* impl = impl_from(interpreter, global_object))
-        return JS::Value(impl->requested_width());
-    return {};
-}
-
-JS_DEFINE_NATIVE_GETTER(HTMLCanvasElementWrapper::height_getter)
-{
-    if (auto* impl = impl_from(interpreter, global_object))
-        return JS::Value(impl->requested_height());
-    return {};
-}
-
-}
-}

+ 0 - 53
Libraries/LibWeb/Bindings/HTMLCanvasElementWrapper.h

@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#include <LibWeb/Bindings/HTMLElementWrapper.h>
-
-namespace Web {
-namespace Bindings {
-
-class HTMLCanvasElementWrapper : public HTMLElementWrapper {
-public:
-    HTMLCanvasElementWrapper(JS::GlobalObject&, HTMLCanvasElement&);
-    virtual void initialize(JS::Interpreter&, JS::GlobalObject&) override;
-    virtual ~HTMLCanvasElementWrapper() override;
-
-    HTMLCanvasElement& node();
-    const HTMLCanvasElement& node() const;
-
-private:
-    virtual const char* class_name() const override { return "HTMLCanvasElementWrapper"; }
-
-    JS_DECLARE_NATIVE_FUNCTION(get_context);
-
-    JS_DECLARE_NATIVE_GETTER(width_getter);
-    JS_DECLARE_NATIVE_GETTER(height_getter);
-};
-
-}
-}

+ 1 - 1
Libraries/LibWeb/CMakeLists.txt

@@ -2,7 +2,6 @@ set(SOURCES
     Bindings/CanvasRenderingContext2DWrapper.cpp
     Bindings/EventListenerWrapper.cpp
     Bindings/EventWrapper.cpp
-    Bindings/HTMLCanvasElementWrapper.cpp
     Bindings/ImageDataWrapper.cpp
     Bindings/LocationObject.cpp
     Bindings/MouseEventWrapper.cpp
@@ -158,6 +157,7 @@ libweb_js_wrapper(Document)
 libweb_js_wrapper(Element)
 libweb_js_wrapper(HTMLElement)
 libweb_js_wrapper(HTMLImageElement)
+libweb_js_wrapper(HTMLCanvasElement)
 
 get_property(WRAPPER_SOURCES GLOBAL PROPERTY wrapper_sources)
 set(SOURCES ${SOURCES} ${WRAPPER_SOURCES})

+ 11 - 0
Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp

@@ -75,6 +75,7 @@ struct Function {
 
 struct Attribute {
     bool readonly { false };
+    bool unsigned_ { false };
     Type type;
     String name;
 
@@ -175,6 +176,7 @@ OwnPtr<Interface> parse_interface(const StringView& input)
 
     auto parse_attribute = [&] {
         bool readonly = false;
+        bool unsigned_ = false;
         if (next_is("readonly")) {
             consume_string("readonly");
             readonly = true;
@@ -184,12 +186,18 @@ OwnPtr<Interface> parse_interface(const StringView& input)
             consume_string("attribute");
             consume_whitespace();
         }
+        if (next_is("unsigned")) {
+            consume_string("unsigned");
+            unsigned_ = true;
+            consume_whitespace();
+        }
         auto type = parse_type();
         consume_whitespace();
         auto name = consume_while([](auto ch) { return !isspace(ch) && ch != ';'; });
         consume_specific(';');
         Attribute attribute;
         attribute.readonly = readonly;
+        attribute.unsigned_ = unsigned_;
         attribute.type = type;
         attribute.name = name;
         attribute.getter_callback_name = String::format("%s_getter", snake_name(attribute.name).characters());
@@ -370,6 +378,7 @@ void generate_implementation(const IDL::Interface& interface)
     out() << "#include <LibWeb/DOM/Element.h>";
     out() << "#include <LibWeb/DOM/HTMLElement.h>";
     out() << "#include <LibWeb/DOM/EventListener.h>";
+    out() << "#include <LibWeb/Bindings/CanvasRenderingContext2DWrapper.h>";
 
     out() << "namespace Web {";
     out() << "namespace Bindings {";
@@ -488,6 +497,8 @@ void generate_implementation(const IDL::Interface& interface)
             out() << "        new_array->indexed_properties().append(wrap(interpreter.heap(), element));";
             out() << "    }";
             out() << "    return new_array;";
+        } else if (return_type.name == "long") {
+            out() << "    return JS::Value(retval);";
         } else {
             out() << "    return wrap(interpreter.heap(), const_cast<" << return_type.name << "&>(*retval));";
         }

+ 7 - 11
Libraries/LibWeb/DOM/HTMLCanvasElement.cpp

@@ -45,14 +45,14 @@ HTMLCanvasElement::~HTMLCanvasElement()
 {
 }
 
-int HTMLCanvasElement::requested_width() const
+unsigned HTMLCanvasElement::width() const
 {
-    return attribute(HTML::AttributeNames::width).to_int().value_or(300);
+    return attribute(HTML::AttributeNames::width).to_uint().value_or(300);
 }
 
-int HTMLCanvasElement::requested_height() const
+unsigned HTMLCanvasElement::height() const
 {
-    return attribute(HTML::AttributeNames::height).to_int().value_or(150);
+    return attribute(HTML::AttributeNames::height).to_uint().value_or(150);
 }
 
 RefPtr<LayoutNode> HTMLCanvasElement::create_layout_node(const StyleProperties* parent_style) const
@@ -74,12 +74,8 @@ CanvasRenderingContext2D* HTMLCanvasElement::get_context(String type)
 
 static Gfx::IntSize bitmap_size_for_canvas(const HTMLCanvasElement& canvas)
 {
-    int width = canvas.requested_width();
-    int height = canvas.requested_height();
-    if (width < 0 || height < 0) {
-        dbg() << "Refusing to create canvas with negative size";
-        return {};
-    }
+    auto width = canvas.width();
+    auto height = canvas.height();
 
     Checked<size_t> area = width;
     area *= height;
@@ -92,7 +88,7 @@ static Gfx::IntSize bitmap_size_for_canvas(const HTMLCanvasElement& canvas)
         dbg() << "Refusing to create " << width << "x" << height << " canvas (exceeds maximum size)";
         return {};
     }
-    return { width, height };
+    return Gfx::IntSize(width, height);
 }
 
 bool HTMLCanvasElement::create_bitmap()

+ 2 - 2
Libraries/LibWeb/DOM/HTMLCanvasElement.h

@@ -47,8 +47,8 @@ public:
 
     CanvasRenderingContext2D* get_context(String type);
 
-    int requested_width() const;
-    int requested_height() const;
+    unsigned width() const;
+    unsigned height() const;
 
 private:
     virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override;

+ 7 - 0
Libraries/LibWeb/DOM/HTMLCanvasElement.idl

@@ -0,0 +1,7 @@
+interface HTMLCanvasElement : HTMLElement {
+
+    CanvasRenderingContext2D? getContext(DOMString contextId);
+    readonly attribute unsigned long width;
+    readonly attribute unsigned long height;
+
+}

+ 2 - 2
Libraries/LibWeb/Layout/LayoutCanvas.cpp

@@ -44,8 +44,8 @@ void LayoutCanvas::layout(LayoutMode layout_mode)
 {
     set_has_intrinsic_width(true);
     set_has_intrinsic_height(true);
-    set_intrinsic_width(node().requested_width());
-    set_intrinsic_height(node().requested_height());
+    set_intrinsic_width(node().width());
+    set_intrinsic_height(node().height());
     LayoutReplaced::layout(layout_mode);
 }