mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 15:57:45 +00:00
LibWeb: Generate HTMLCanvasElement bindings from IDL :^)
This commit is contained in:
parent
119dd2c541
commit
b959d06ace
8 changed files with 30 additions and 175 deletions
|
@ -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 {};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,7 +2,6 @@ set(SOURCES
|
||||||
Bindings/CanvasRenderingContext2DWrapper.cpp
|
Bindings/CanvasRenderingContext2DWrapper.cpp
|
||||||
Bindings/EventListenerWrapper.cpp
|
Bindings/EventListenerWrapper.cpp
|
||||||
Bindings/EventWrapper.cpp
|
Bindings/EventWrapper.cpp
|
||||||
Bindings/HTMLCanvasElementWrapper.cpp
|
|
||||||
Bindings/ImageDataWrapper.cpp
|
Bindings/ImageDataWrapper.cpp
|
||||||
Bindings/LocationObject.cpp
|
Bindings/LocationObject.cpp
|
||||||
Bindings/MouseEventWrapper.cpp
|
Bindings/MouseEventWrapper.cpp
|
||||||
|
@ -158,6 +157,7 @@ libweb_js_wrapper(Document)
|
||||||
libweb_js_wrapper(Element)
|
libweb_js_wrapper(Element)
|
||||||
libweb_js_wrapper(HTMLElement)
|
libweb_js_wrapper(HTMLElement)
|
||||||
libweb_js_wrapper(HTMLImageElement)
|
libweb_js_wrapper(HTMLImageElement)
|
||||||
|
libweb_js_wrapper(HTMLCanvasElement)
|
||||||
|
|
||||||
get_property(WRAPPER_SOURCES GLOBAL PROPERTY wrapper_sources)
|
get_property(WRAPPER_SOURCES GLOBAL PROPERTY wrapper_sources)
|
||||||
set(SOURCES ${SOURCES} ${WRAPPER_SOURCES})
|
set(SOURCES ${SOURCES} ${WRAPPER_SOURCES})
|
||||||
|
|
|
@ -75,6 +75,7 @@ struct Function {
|
||||||
|
|
||||||
struct Attribute {
|
struct Attribute {
|
||||||
bool readonly { false };
|
bool readonly { false };
|
||||||
|
bool unsigned_ { false };
|
||||||
Type type;
|
Type type;
|
||||||
String name;
|
String name;
|
||||||
|
|
||||||
|
@ -175,6 +176,7 @@ OwnPtr<Interface> parse_interface(const StringView& input)
|
||||||
|
|
||||||
auto parse_attribute = [&] {
|
auto parse_attribute = [&] {
|
||||||
bool readonly = false;
|
bool readonly = false;
|
||||||
|
bool unsigned_ = false;
|
||||||
if (next_is("readonly")) {
|
if (next_is("readonly")) {
|
||||||
consume_string("readonly");
|
consume_string("readonly");
|
||||||
readonly = true;
|
readonly = true;
|
||||||
|
@ -184,12 +186,18 @@ OwnPtr<Interface> parse_interface(const StringView& input)
|
||||||
consume_string("attribute");
|
consume_string("attribute");
|
||||||
consume_whitespace();
|
consume_whitespace();
|
||||||
}
|
}
|
||||||
|
if (next_is("unsigned")) {
|
||||||
|
consume_string("unsigned");
|
||||||
|
unsigned_ = true;
|
||||||
|
consume_whitespace();
|
||||||
|
}
|
||||||
auto type = parse_type();
|
auto type = parse_type();
|
||||||
consume_whitespace();
|
consume_whitespace();
|
||||||
auto name = consume_while([](auto ch) { return !isspace(ch) && ch != ';'; });
|
auto name = consume_while([](auto ch) { return !isspace(ch) && ch != ';'; });
|
||||||
consume_specific(';');
|
consume_specific(';');
|
||||||
Attribute attribute;
|
Attribute attribute;
|
||||||
attribute.readonly = readonly;
|
attribute.readonly = readonly;
|
||||||
|
attribute.unsigned_ = unsigned_;
|
||||||
attribute.type = type;
|
attribute.type = type;
|
||||||
attribute.name = name;
|
attribute.name = name;
|
||||||
attribute.getter_callback_name = String::format("%s_getter", snake_name(attribute.name).characters());
|
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/Element.h>";
|
||||||
out() << "#include <LibWeb/DOM/HTMLElement.h>";
|
out() << "#include <LibWeb/DOM/HTMLElement.h>";
|
||||||
out() << "#include <LibWeb/DOM/EventListener.h>";
|
out() << "#include <LibWeb/DOM/EventListener.h>";
|
||||||
|
out() << "#include <LibWeb/Bindings/CanvasRenderingContext2DWrapper.h>";
|
||||||
|
|
||||||
out() << "namespace Web {";
|
out() << "namespace Web {";
|
||||||
out() << "namespace Bindings {";
|
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() << " new_array->indexed_properties().append(wrap(interpreter.heap(), element));";
|
||||||
out() << " }";
|
out() << " }";
|
||||||
out() << " return new_array;";
|
out() << " return new_array;";
|
||||||
|
} else if (return_type.name == "long") {
|
||||||
|
out() << " return JS::Value(retval);";
|
||||||
} else {
|
} else {
|
||||||
out() << " return wrap(interpreter.heap(), const_cast<" << return_type.name << "&>(*retval));";
|
out() << " return wrap(interpreter.heap(), const_cast<" << return_type.name << "&>(*retval));";
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
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)
|
static Gfx::IntSize bitmap_size_for_canvas(const HTMLCanvasElement& canvas)
|
||||||
{
|
{
|
||||||
int width = canvas.requested_width();
|
auto width = canvas.width();
|
||||||
int height = canvas.requested_height();
|
auto height = canvas.height();
|
||||||
if (width < 0 || height < 0) {
|
|
||||||
dbg() << "Refusing to create canvas with negative size";
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Checked<size_t> area = width;
|
Checked<size_t> area = width;
|
||||||
area *= height;
|
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)";
|
dbg() << "Refusing to create " << width << "x" << height << " canvas (exceeds maximum size)";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
return { width, height };
|
return Gfx::IntSize(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HTMLCanvasElement::create_bitmap()
|
bool HTMLCanvasElement::create_bitmap()
|
||||||
|
|
|
@ -47,8 +47,8 @@ public:
|
||||||
|
|
||||||
CanvasRenderingContext2D* get_context(String type);
|
CanvasRenderingContext2D* get_context(String type);
|
||||||
|
|
||||||
int requested_width() const;
|
unsigned width() const;
|
||||||
int requested_height() const;
|
unsigned height() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override;
|
virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override;
|
||||||
|
|
7
Libraries/LibWeb/DOM/HTMLCanvasElement.idl
Normal file
7
Libraries/LibWeb/DOM/HTMLCanvasElement.idl
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
interface HTMLCanvasElement : HTMLElement {
|
||||||
|
|
||||||
|
CanvasRenderingContext2D? getContext(DOMString contextId);
|
||||||
|
readonly attribute unsigned long width;
|
||||||
|
readonly attribute unsigned long height;
|
||||||
|
|
||||||
|
}
|
|
@ -44,8 +44,8 @@ void LayoutCanvas::layout(LayoutMode layout_mode)
|
||||||
{
|
{
|
||||||
set_has_intrinsic_width(true);
|
set_has_intrinsic_width(true);
|
||||||
set_has_intrinsic_height(true);
|
set_has_intrinsic_height(true);
|
||||||
set_intrinsic_width(node().requested_width());
|
set_intrinsic_width(node().width());
|
||||||
set_intrinsic_height(node().requested_height());
|
set_intrinsic_height(node().height());
|
||||||
LayoutReplaced::layout(layout_mode);
|
LayoutReplaced::layout(layout_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue