From 9ce25bbf1d473b911c4bedaa6e7e2d52f8d7d6b9 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 22 Jun 2020 18:39:22 +0200 Subject: [PATCH] LibWeb: Generate CanvasRenderingContext2D bindings from IDL :^) We're still missing optional argument support, so this implementation doesn't support fill(), only fill(fill_rule). Still it's really nice to get rid of so much hand-written wrapper code. --- Libraries/LibJS/Runtime/ErrorTypes.h | 7 +- .../CanvasRenderingContext2DWrapper.cpp | 413 ------------------ .../CanvasRenderingContext2DWrapper.h | 77 ---- Libraries/LibWeb/CMakeLists.txt | 2 +- .../CodeGenerators/WrapperGenerator.cpp | 37 +- .../LibWeb/DOM/CanvasRenderingContext2D.cpp | 16 +- .../LibWeb/DOM/CanvasRenderingContext2D.h | 9 +- .../LibWeb/DOM/CanvasRenderingContext2D.idl | 28 ++ 8 files changed, 84 insertions(+), 505 deletions(-) delete mode 100644 Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.cpp delete mode 100644 Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.h create mode 100644 Libraries/LibWeb/DOM/CanvasRenderingContext2D.idl diff --git a/Libraries/LibJS/Runtime/ErrorTypes.h b/Libraries/LibJS/Runtime/ErrorTypes.h index 34353de0f8..3dfaccdc95 100644 --- a/Libraries/LibJS/Runtime/ErrorTypes.h +++ b/Libraries/LibJS/Runtime/ErrorTypes.h @@ -143,12 +143,7 @@ /* LibWeb bindings */ \ M(BadArgCountOne, "%s() needs one argument") \ M(BadArgCountAtLeastOne, "%s() needs at least one argument") \ - M(BadArgCountMany, "%s() needs %s arguments") \ - M(DrawImageArgumentCount, "drawImage() needs three arguments") \ - M(FillBadWindingRule, "fill() winding rule must be either 'nonzero' or 'evenodd'") \ - M(FillNonString, "fill() called with non-string") \ - M(ImageIsAn, "Image is not an HTMLImageElement, it's an %s") \ - M(PutImageDataBadCall, "putImageData() called with non-ImageData") \ + M(BadArgCountMany, "%s() needs %s arguments") namespace JS { diff --git a/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.cpp b/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.cpp deleted file mode 100644 index 62259bfed0..0000000000 --- a/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.cpp +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Web { -namespace Bindings { - -CanvasRenderingContext2DWrapper* wrap(JS::Heap& heap, CanvasRenderingContext2D& impl) -{ - return static_cast(wrap_impl(heap, impl)); -} - -CanvasRenderingContext2DWrapper::CanvasRenderingContext2DWrapper(JS::GlobalObject& global_object, CanvasRenderingContext2D& impl) - : Wrapper(*global_object.object_prototype()) - , m_impl(impl) -{ -} - -void CanvasRenderingContext2DWrapper::initialize(JS::Interpreter& interpreter, JS::GlobalObject& global_object) -{ - Wrapper::initialize(interpreter, global_object); - define_native_function("fillRect", fill_rect, 4); - define_native_function("scale", scale, 2); - define_native_function("translate", translate, 2); - define_native_function("strokeRect", stroke_rect, 4); - define_native_function("drawImage", draw_image, 3); - define_native_function("beginPath", begin_path, 0); - define_native_function("closePath", close_path, 0); - define_native_function("stroke", stroke, 0); - define_native_function("fill", fill, 0); - define_native_function("moveTo", move_to, 2); - define_native_function("lineTo", line_to, 2); - define_native_function("quadraticCurveTo", quadratic_curve_to, 4); - define_native_function("createImageData", create_image_data, 1); - define_native_function("putImageData", put_image_data, 3); - - define_native_property("fillStyle", fill_style_getter, fill_style_setter); - define_native_property("strokeStyle", stroke_style_getter, stroke_style_setter); - define_native_property("lineWidth", line_width_getter, line_width_setter); - define_native_property("canvas", canvas_getter, nullptr); -} - -CanvasRenderingContext2DWrapper::~CanvasRenderingContext2DWrapper() -{ -} - -static CanvasRenderingContext2D* 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 CanvasRenderingContext2DWrapper somehow! - return &static_cast(this_object)->impl(); -} - -JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DWrapper::fill_rect) -{ - auto* impl = impl_from(interpreter, global_object); - if (!impl) - return {}; - if (interpreter.argument_count() >= 4) { - auto x = interpreter.argument(0).to_double(interpreter); - if (interpreter.exception()) - return {}; - auto y = interpreter.argument(1).to_double(interpreter); - if (interpreter.exception()) - return {}; - auto width = interpreter.argument(2).to_double(interpreter); - if (interpreter.exception()) - return {}; - auto height = interpreter.argument(3).to_double(interpreter); - if (interpreter.exception()) - return {}; - impl->fill_rect(x, y, width, height); - } - return JS::js_undefined(); -} - -JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DWrapper::stroke_rect) -{ - auto* impl = impl_from(interpreter, global_object); - if (!impl) - return {}; - if (interpreter.argument_count() >= 4) { - auto x = interpreter.argument(0).to_double(interpreter); - if (interpreter.exception()) - return {}; - auto y = interpreter.argument(1).to_double(interpreter); - if (interpreter.exception()) - return {}; - auto width = interpreter.argument(2).to_double(interpreter); - if (interpreter.exception()) - return {}; - auto height = interpreter.argument(3).to_double(interpreter); - if (interpreter.exception()) - return {}; - impl->stroke_rect(x, y, width, height); - } - return JS::js_undefined(); -} - -JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DWrapper::draw_image) -{ - auto* impl = impl_from(interpreter, global_object); - if (!impl) - return {}; - if (interpreter.argument_count() < 3) - return interpreter.throw_exception(JS::ErrorType::DrawImageArgumentCount); - auto* image_argument = interpreter.argument(0).to_object(interpreter, global_object); - if (!image_argument) - return {}; - if (StringView(image_argument->class_name()) != "HTMLImageElementWrapper") - return interpreter.throw_exception(JS::ErrorType::ImageIsAn, image_argument->class_name()); - - auto x = interpreter.argument(1).to_double(interpreter); - if (interpreter.exception()) - return {}; - auto y = interpreter.argument(2).to_double(interpreter); - if (interpreter.exception()) - return {}; - impl->draw_image(static_cast(*image_argument).impl(), x, y); - return JS::js_undefined(); -} - -JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DWrapper::scale) -{ - auto* impl = impl_from(interpreter, global_object); - if (!impl) - return {}; - if (interpreter.argument_count() >= 2) { - auto sx = interpreter.argument(0).to_number(interpreter); - if (interpreter.exception()) - return {}; - auto sy = interpreter.argument(1).to_number(interpreter); - if (interpreter.exception()) - return {}; - if (sx.is_finite_number() && sy.is_finite_number()) - impl->scale(sx.as_double(), sy.as_double()); - } - return JS::js_undefined(); -} - -JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DWrapper::translate) -{ - auto* impl = impl_from(interpreter, global_object); - if (!impl) - return {}; - if (interpreter.argument_count() >= 2) { - auto tx = interpreter.argument(0).to_number(interpreter); - if (interpreter.exception()) - return {}; - auto ty = interpreter.argument(1).to_number(interpreter); - if (interpreter.exception()) - return {}; - if (tx.is_finite_number() && ty.is_finite_number()) - impl->translate(tx.as_double(), ty.as_double()); - } - return JS::js_undefined(); -} - -JS_DEFINE_NATIVE_GETTER(CanvasRenderingContext2DWrapper::fill_style_getter) -{ - auto* impl = impl_from(interpreter, global_object); - if (!impl) - return {}; - return JS::js_string(interpreter, impl->fill_style()); -} - -JS_DEFINE_NATIVE_SETTER(CanvasRenderingContext2DWrapper::fill_style_setter) -{ - auto* impl = impl_from(interpreter, global_object); - if (!impl) - return; - auto string = value.to_string(interpreter); - if (interpreter.exception()) - return; - impl->set_fill_style(string); -} - -JS_DEFINE_NATIVE_GETTER(CanvasRenderingContext2DWrapper::stroke_style_getter) -{ - auto* impl = impl_from(interpreter, global_object); - if (!impl) - return {}; - return JS::js_string(interpreter, impl->stroke_style()); -} - -JS_DEFINE_NATIVE_SETTER(CanvasRenderingContext2DWrapper::stroke_style_setter) -{ - auto* impl = impl_from(interpreter, global_object); - if (!impl) - return; - auto string = value.to_string(interpreter); - if (interpreter.exception()) - return; - impl->set_stroke_style(string); -} - -JS_DEFINE_NATIVE_GETTER(CanvasRenderingContext2DWrapper::line_width_getter) -{ - auto* impl = impl_from(interpreter, global_object); - if (!impl) - return {}; - return JS::Value(impl->line_width()); -} - -JS_DEFINE_NATIVE_SETTER(CanvasRenderingContext2DWrapper::line_width_setter) -{ - auto* impl = impl_from(interpreter, global_object); - if (!impl) - return; - auto line_width = value.to_double(interpreter); - if (interpreter.exception()) - return; - impl->set_line_width(line_width); -} - -JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DWrapper::begin_path) -{ - auto* impl = impl_from(interpreter, global_object); - if (!impl) - return {}; - impl->begin_path(); - return JS::js_undefined(); -} - -JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DWrapper::close_path) -{ - auto* impl = impl_from(interpreter, global_object); - if (!impl) - return {}; - impl->close_path(); - return JS::js_undefined(); -} - -JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DWrapper::stroke) -{ - auto* impl = impl_from(interpreter, global_object); - if (!impl) - return {}; - impl->stroke(); - return JS::js_undefined(); -} - -JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DWrapper::fill) -{ - auto* impl = impl_from(interpreter, global_object); - if (!impl) - return {}; - auto winding = Gfx::Painter::WindingRule::Nonzero; - - if (interpreter.argument_count() == 1) { - auto arg0 = interpreter.argument(0); - if (arg0.is_string()) { - const auto& winding_name = arg0.as_string().string(); - if (winding_name == "evenodd") { - winding = Gfx::Painter::WindingRule::EvenOdd; - } else if (winding_name != "nonzero") { - return interpreter.throw_exception(JS::ErrorType::FillBadWindingRule); - } - } else { - return interpreter.throw_exception(JS::ErrorType::FillNonString); - } - } else { - // FIXME: Path2D object - return JS::js_undefined(); - } - impl->fill(winding); - return JS::js_undefined(); -} - -JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DWrapper::move_to) -{ - auto* impl = impl_from(interpreter, global_object); - if (!impl) - return {}; - auto x = interpreter.argument(0).to_double(interpreter); - if (interpreter.exception()) - return {}; - auto y = interpreter.argument(1).to_double(interpreter); - if (interpreter.exception()) - return {}; - impl->move_to(x, y); - return JS::js_undefined(); -} - -JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DWrapper::line_to) -{ - auto* impl = impl_from(interpreter, global_object); - if (!impl) - return {}; - auto x = interpreter.argument(0).to_double(interpreter); - if (interpreter.exception()) - return {}; - auto y = interpreter.argument(1).to_double(interpreter); - if (interpreter.exception()) - return {}; - impl->line_to(x, y); - return JS::js_undefined(); -} - -JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DWrapper::quadratic_curve_to) -{ - auto* impl = impl_from(interpreter, global_object); - if (!impl) - return {}; - auto cx = interpreter.argument(0).to_double(interpreter); - if (interpreter.exception()) - return {}; - auto cy = interpreter.argument(1).to_double(interpreter); - if (interpreter.exception()) - return {}; - auto x = interpreter.argument(2).to_double(interpreter); - if (interpreter.exception()) - return {}; - auto y = interpreter.argument(3).to_double(interpreter); - if (interpreter.exception()) - return {}; - impl->quadratic_curve_to(cx, cy, x, y); - return JS::js_undefined(); -} - -JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DWrapper::create_image_data) -{ - auto* impl = impl_from(interpreter, global_object); - if (!impl) - return {}; - auto width = interpreter.argument(0).to_i32(interpreter); - if (interpreter.exception()) - return {}; - auto height = interpreter.argument(1).to_i32(interpreter); - if (interpreter.exception()) - return {}; - auto image_data = impl->create_image_data(global_object, width, height); - return wrap(interpreter.heap(), *image_data); -} - -JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DWrapper::put_image_data) -{ - auto* impl = impl_from(interpreter, global_object); - if (!impl) - return {}; - - auto* image_data_object = interpreter.argument(0).to_object(interpreter, global_object); - if (!image_data_object) - return {}; - - if (StringView(image_data_object->class_name()) != "ImageDataWrapper") { - return interpreter.throw_exception(JS::ErrorType::PutImageDataBadCall); - } - - auto& image_data = static_cast(image_data_object)->impl(); - auto x = interpreter.argument(1).to_double(interpreter); - if (interpreter.exception()) - return {}; - auto y = interpreter.argument(2).to_double(interpreter); - if (interpreter.exception()) - return {}; - impl->put_image_data(image_data, x, y); - return JS::js_undefined(); -} - -JS_DEFINE_NATIVE_GETTER(CanvasRenderingContext2DWrapper::canvas_getter) -{ - auto* impl = impl_from(interpreter, global_object); - if (!impl) - return {}; - auto* element = impl->element(); - if (!element) - return JS::js_null(); - return wrap(interpreter.heap(), *element); -} - -} -} diff --git a/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.h b/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.h deleted file mode 100644 index 2fe903858b..0000000000 --- a/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling - * 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 - -namespace Web { -namespace Bindings { - -class CanvasRenderingContext2DWrapper final : public Wrapper { - JS_OBJECT(CanvasRenderingContext2DWrapper, Wrapper); -public: - CanvasRenderingContext2DWrapper(JS::GlobalObject&, CanvasRenderingContext2D&); - virtual void initialize(JS::Interpreter&, JS::GlobalObject&) override; - virtual ~CanvasRenderingContext2DWrapper() override; - - CanvasRenderingContext2D& impl() { return m_impl; } - const CanvasRenderingContext2D& impl() const { return m_impl; } - -private: - JS_DECLARE_NATIVE_FUNCTION(fill_rect); - JS_DECLARE_NATIVE_FUNCTION(stroke_rect); - JS_DECLARE_NATIVE_FUNCTION(draw_image); - JS_DECLARE_NATIVE_FUNCTION(scale); - JS_DECLARE_NATIVE_FUNCTION(translate); - JS_DECLARE_NATIVE_FUNCTION(begin_path); - JS_DECLARE_NATIVE_FUNCTION(close_path); - JS_DECLARE_NATIVE_FUNCTION(stroke); - JS_DECLARE_NATIVE_FUNCTION(fill); - JS_DECLARE_NATIVE_FUNCTION(move_to); - JS_DECLARE_NATIVE_FUNCTION(line_to); - JS_DECLARE_NATIVE_FUNCTION(quadratic_curve_to); - JS_DECLARE_NATIVE_FUNCTION(create_image_data); - JS_DECLARE_NATIVE_FUNCTION(put_image_data); - - JS_DECLARE_NATIVE_GETTER(fill_style_getter); - JS_DECLARE_NATIVE_SETTER(fill_style_setter); - - JS_DECLARE_NATIVE_GETTER(stroke_style_getter); - JS_DECLARE_NATIVE_SETTER(stroke_style_setter); - - JS_DECLARE_NATIVE_GETTER(line_width_getter); - JS_DECLARE_NATIVE_SETTER(line_width_setter); - - JS_DECLARE_NATIVE_GETTER(canvas_getter); - - NonnullRefPtr m_impl; -}; - -CanvasRenderingContext2DWrapper* wrap(JS::Heap&, CanvasRenderingContext2D&); - -} -} diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index 9c36c2cc49..fb3cf7c7d0 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -1,5 +1,4 @@ set(SOURCES - Bindings/CanvasRenderingContext2DWrapper.cpp Bindings/EventListenerWrapper.cpp Bindings/EventWrapperFactory.cpp Bindings/LocationObject.cpp @@ -159,6 +158,7 @@ libweb_js_wrapper(HTMLCanvasElement) libweb_js_wrapper(ImageData) libweb_js_wrapper(Event) libweb_js_wrapper(MouseEvent) +libweb_js_wrapper(CanvasRenderingContext2D) get_property(WRAPPER_SOURCES GLOBAL PROPERTY wrapper_sources) set(SOURCES ${SOURCES} ${WRAPPER_SOURCES}) diff --git a/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp b/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp index ec47efa551..89df442390 100644 --- a/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp +++ b/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp @@ -214,6 +214,8 @@ OwnPtr parse_interface(const StringView& input) Vector parameters; for (;;) { + if (consume_if(')')) + break; auto type = parse_type(); consume_whitespace(); auto name = consume_while([](auto ch) { return !isspace(ch) && ch != ',' && ch != ')'; }); @@ -327,6 +329,23 @@ static bool should_emit_wrapper_factory(const IDL::Interface& interface) return true; } +static bool is_wrappable_type(const IDL::Type& type) +{ + if (type.name == "Node") + return true; + if (type.name == "Document") + return true; + if (type.name == "Text") + return true; + if (type.name == "DocumentType") + return true; + if (type.name.ends_with("Element")) + return true; + if (type.name == "ImageData") + return true; + return false; +} + static void generate_header(const IDL::Interface& interface) { auto& wrapper_class = interface.wrapper_class; @@ -404,6 +423,9 @@ void generate_implementation(const IDL::Interface& interface) out() << "#include "; out() << "#include "; out() << "#include "; + out() << "#include "; + out() << "#include "; + out() << "#include "; out() << "#include "; out() << "namespace Web {"; @@ -473,7 +495,7 @@ void generate_implementation(const IDL::Interface& interface) generate_return(); out() << " }"; out() << " auto " << cpp_name << " = adopt(*new EventListener(JS::make_handle(&" << js_name << js_suffix << ".as_function())));"; - } else if (parameter.type.name == "Node") { + } else if (is_wrappable_type(parameter.type)) { out() << " auto " << cpp_name << "_object = " << js_name << js_suffix << ".to_object(interpreter, global_object);"; out() << " if (interpreter.exception())"; generate_return(); @@ -482,6 +504,13 @@ void generate_implementation(const IDL::Interface& interface) generate_return(); out() << " }"; out() << " auto& " << cpp_name << " = static_cast<" << parameter.type.name << "Wrapper*>(" << cpp_name << "_object)->impl();"; + } else if (parameter.type.name == "double") { + out() << " auto " << cpp_name << " = " << js_name << js_suffix << ".to_double(interpreter);"; + out() << " if (interpreter.exception())"; + generate_return(); + } else { + dbg() << "Unimplemented JS-to-C++ conversion: " << parameter.type.name; + ASSERT_NOT_REACHED(); } }; @@ -564,8 +593,10 @@ void generate_implementation(const IDL::Interface& interface) out() << " auto* impl = impl_from(interpreter, global_object);"; out() << " if (!impl)"; out() << " return {};"; - out() << " if (interpreter.argument_count() < " << function.length() << ")"; - out() << " return interpreter.throw_exception(JS::ErrorType::BadArgCountMany, \"" << function.name << "\", \"" << function.length() << "\");"; + if (function.length() > 0) { + out() << " if (interpreter.argument_count() < " << function.length() << ")"; + out() << " return interpreter.throw_exception(JS::ErrorType::BadArgCountMany, \"" << function.name << "\", \"" << function.length() << "\");"; + } StringBuilder arguments_builder; generate_arguments(function.parameters, arguments_builder); diff --git a/Libraries/LibWeb/DOM/CanvasRenderingContext2D.cpp b/Libraries/LibWeb/DOM/CanvasRenderingContext2D.cpp index 3b61eee85b..c210e36458 100644 --- a/Libraries/LibWeb/DOM/CanvasRenderingContext2D.cpp +++ b/Libraries/LibWeb/DOM/CanvasRenderingContext2D.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -190,9 +191,20 @@ void CanvasRenderingContext2D::fill(Gfx::Painter::WindingRule winding) painter->fill_path(path, m_fill_style, winding); } -RefPtr CanvasRenderingContext2D::create_image_data(JS::GlobalObject& global_object, int width, int height) const +void CanvasRenderingContext2D::fill(const String& fill_rule) { - return ImageData::create_with_size(global_object, width, height); + if (fill_rule == "evenodd") + return fill(Gfx::Painter::WindingRule::EvenOdd); + return fill(Gfx::Painter::WindingRule::Nonzero); +} + +RefPtr CanvasRenderingContext2D::create_image_data(int width, int height) const +{ + if (!wrapper()) { + dbg() << "Hmm! Attempted to create ImageData for wrapper-less CRC2D."; + return nullptr; + } + return ImageData::create_with_size(wrapper()->global_object(), width, height); } void CanvasRenderingContext2D::put_image_data(const ImageData& image_data, float x, float y) diff --git a/Libraries/LibWeb/DOM/CanvasRenderingContext2D.h b/Libraries/LibWeb/DOM/CanvasRenderingContext2D.h index 618187ea77..1b68f13fc4 100644 --- a/Libraries/LibWeb/DOM/CanvasRenderingContext2D.h +++ b/Libraries/LibWeb/DOM/CanvasRenderingContext2D.h @@ -72,12 +72,15 @@ public: void line_to(float x, float y); void quadratic_curve_to(float cx, float cy, float x, float y); void stroke(); - void fill(Gfx::Painter::WindingRule); - RefPtr create_image_data(JS::GlobalObject&, int width, int height) const; + // FIXME: We should only have one fill(), really. Fix the wrapper generator! + void fill(Gfx::Painter::WindingRule); + void fill(const String& fill_rule); + + RefPtr create_image_data(int width, int height) const; void put_image_data(const ImageData&, float x, float y); - HTMLCanvasElement* element() { return m_element; } + HTMLCanvasElement* canvas() { return m_element; } private: explicit CanvasRenderingContext2D(HTMLCanvasElement&); diff --git a/Libraries/LibWeb/DOM/CanvasRenderingContext2D.idl b/Libraries/LibWeb/DOM/CanvasRenderingContext2D.idl new file mode 100644 index 0000000000..98861cc8ec --- /dev/null +++ b/Libraries/LibWeb/DOM/CanvasRenderingContext2D.idl @@ -0,0 +1,28 @@ +interface CanvasRenderingContext2D { + + void fillRect(double x, double y, double w, double h); + void strokeRect(double x, double y, double w, double h); + + void scale(double x, double y); + void translate(double x, double y); + + void beginPath(); + void closePath(); + void fill(DOMString fillRule); + void stroke(); + void moveTo(double x, double y); + void lineTo(double x, double y); + void quadraticCurveTo(double cpx, double cpy, double x, double y); + + void drawImage(HTMLImageElement image, double dx, double dy); + + attribute DOMString fillStyle; + attribute DOMString strokeStyle; + attribute double lineWidth; + + ImageData createImageData(double sw, double sh); + void putImageData(ImageData imagedata, double dx, double dy); + + readonly attribute HTMLCanvasElement canvas; + +}