From a37c29e35381bc2560515b384b442dab81a35fee Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 19 Mar 2020 19:07:56 +0100 Subject: LibWeb: Add element and start fleshing out CRC2D This patch adds HTMLCanvasElement along with a LayoutCanvas object. The DOM and layout parts are very similar to elements. The element holds a Gfx::Bitmap which is sized according to the "width" and "height" attributes on the element. Calling .getContext("2d") on a element gives you a context object that draws into the underlying Gfx::Bitmap of the . The context weakly points to the which allows it to outlive the canvas element if needed. This is really quite cool. :^) --- .../Bindings/CanvasRenderingContext2DWrapper.cpp | 65 +++++++++++++++ .../Bindings/CanvasRenderingContext2DWrapper.h | 51 ++++++++++++ .../LibWeb/Bindings/HTMLCanvasElementWrapper.cpp | 67 ++++++++++++++++ .../LibWeb/Bindings/HTMLCanvasElementWrapper.h | 47 +++++++++++ Libraries/LibWeb/Bindings/NodeWrapper.cpp | 13 +++ Libraries/LibWeb/Bindings/NodeWrapper.h | 2 + Libraries/LibWeb/Bindings/Wrappable.h | 2 +- Libraries/LibWeb/DOM/CanvasRenderingContext2D.cpp | 44 +++++++++++ Libraries/LibWeb/DOM/CanvasRenderingContext2D.h | 38 +++++++++ Libraries/LibWeb/DOM/ElementFactory.cpp | 3 + Libraries/LibWeb/DOM/HTMLCanvasElement.cpp | 92 ++++++++++++++++++++++ Libraries/LibWeb/DOM/HTMLCanvasElement.h | 66 ++++++++++++++++ Libraries/LibWeb/Forward.h | 5 ++ Libraries/LibWeb/Layout/LayoutCanvas.cpp | 64 +++++++++++++++ Libraries/LibWeb/Layout/LayoutCanvas.h | 57 ++++++++++++++ Libraries/LibWeb/Layout/LayoutNode.h | 1 + Libraries/LibWeb/Makefile | 5 ++ 17 files changed, 621 insertions(+), 1 deletion(-) create mode 100644 Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.cpp create mode 100644 Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.h create mode 100644 Libraries/LibWeb/Bindings/HTMLCanvasElementWrapper.cpp create mode 100644 Libraries/LibWeb/Bindings/HTMLCanvasElementWrapper.h create mode 100644 Libraries/LibWeb/DOM/CanvasRenderingContext2D.cpp create mode 100644 Libraries/LibWeb/DOM/CanvasRenderingContext2D.h create mode 100644 Libraries/LibWeb/DOM/HTMLCanvasElement.cpp create mode 100644 Libraries/LibWeb/DOM/HTMLCanvasElement.h create mode 100644 Libraries/LibWeb/Layout/LayoutCanvas.cpp create mode 100644 Libraries/LibWeb/Layout/LayoutCanvas.h (limited to 'Libraries') diff --git a/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.cpp b/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.cpp new file mode 100644 index 0000000000..5944001880 --- /dev/null +++ b/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.cpp @@ -0,0 +1,65 @@ +/* + * 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 + +namespace Web { +namespace Bindings { + +CanvasRenderingContext2DWrapper* wrap(JS::Heap& heap, CanvasRenderingContext2D& impl) +{ + return static_cast(wrap_impl(heap, impl)); +} + +CanvasRenderingContext2DWrapper::CanvasRenderingContext2DWrapper(CanvasRenderingContext2D& impl) + : m_impl(impl) +{ + put_native_property( + "fillStyle", + [this](JS::Object*) { + return JS::js_string(heap(), m_impl->fill_style()); + }, + [this](JS::Object*, JS::Value value) { + m_impl->set_fill_style(value.to_string()); + }); + put_native_function("fillRect", [this](JS::Object*, const Vector& arguments) { + if (arguments.size() >= 4) { + m_impl->fill_rect(arguments[0].to_i32(), arguments[1].to_i32(), arguments[2].to_i32(), arguments[3].to_i32()); + } + return JS::js_undefined(); + }); +} + +CanvasRenderingContext2DWrapper::~CanvasRenderingContext2DWrapper() +{ +} + +} +} diff --git a/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.h b/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.h new file mode 100644 index 0000000000..569e5952e0 --- /dev/null +++ b/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.h @@ -0,0 +1,51 @@ +/* + * 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 : public Wrapper { +public: + explicit CanvasRenderingContext2DWrapper(CanvasRenderingContext2D&); + virtual ~CanvasRenderingContext2DWrapper() override; + + CanvasRenderingContext2D& impl() { return m_impl; } + const CanvasRenderingContext2D& impl() const { return m_impl; } + +private: + virtual const char* class_name() const override { return "CanvasRenderingContext2DWrapper"; } + + NonnullRefPtr m_impl; +}; + +CanvasRenderingContext2DWrapper* wrap(JS::Heap&, CanvasRenderingContext2D&); + +} +} diff --git a/Libraries/LibWeb/Bindings/HTMLCanvasElementWrapper.cpp b/Libraries/LibWeb/Bindings/HTMLCanvasElementWrapper.cpp new file mode 100644 index 0000000000..9ac28e412e --- /dev/null +++ b/Libraries/LibWeb/Bindings/HTMLCanvasElementWrapper.cpp @@ -0,0 +1,67 @@ +/* + * 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 + +namespace Web { +namespace Bindings { + +HTMLCanvasElementWrapper::HTMLCanvasElementWrapper(HTMLCanvasElement& element) + : NodeWrapper(element) +{ + put_native_function("getContext", [this](JS::Object*, const Vector& arguments) -> JS::Value { + if (arguments.size() >= 1) { + dbg() << "Calling getContext on " << node().tag_name(); + auto* context = node().get_context(arguments[0].to_string()); + dbg() << "getContext got 2D context=" << context; + return wrap(heap(), *context); + } + return JS::js_undefined(); + }); +} + +HTMLCanvasElementWrapper::~HTMLCanvasElementWrapper() +{ +} + +HTMLCanvasElement& HTMLCanvasElementWrapper::node() +{ + return static_cast(NodeWrapper::node()); +} + +const HTMLCanvasElement& HTMLCanvasElementWrapper::node() const +{ + return static_cast(NodeWrapper::node()); +} + +} +} diff --git a/Libraries/LibWeb/Bindings/HTMLCanvasElementWrapper.h b/Libraries/LibWeb/Bindings/HTMLCanvasElementWrapper.h new file mode 100644 index 0000000000..ae46fa8914 --- /dev/null +++ b/Libraries/LibWeb/Bindings/HTMLCanvasElementWrapper.h @@ -0,0 +1,47 @@ +/* + * 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 HTMLCanvasElementWrapper : public NodeWrapper { +public: + explicit HTMLCanvasElementWrapper(HTMLCanvasElement&); + virtual ~HTMLCanvasElementWrapper() override; + + HTMLCanvasElement& node(); + const HTMLCanvasElement& node() const; + +private: + virtual const char* class_name() const override { return "HTMLCanvasElementWrapper"; } +}; + +} +} diff --git a/Libraries/LibWeb/Bindings/NodeWrapper.cpp b/Libraries/LibWeb/Bindings/NodeWrapper.cpp index ef80dbe8f1..aeb84b4e3d 100644 --- a/Libraries/LibWeb/Bindings/NodeWrapper.cpp +++ b/Libraries/LibWeb/Bindings/NodeWrapper.cpp @@ -26,12 +26,25 @@ #include #include +#include +#include #include +#include +#include #include namespace Web { namespace Bindings { +NodeWrapper* wrap(JS::Heap& heap, Node& node) +{ + if (is(node)) + return static_cast(wrap_impl(heap, to(node))); + if (is(node)) + return static_cast(wrap_impl(heap, to(node))); + return static_cast(wrap_impl(heap, node)); +} + NodeWrapper::NodeWrapper(Node& node) : EventTargetWrapper(node) { diff --git a/Libraries/LibWeb/Bindings/NodeWrapper.h b/Libraries/LibWeb/Bindings/NodeWrapper.h index 0d93b6870b..e39f2f1a8c 100644 --- a/Libraries/LibWeb/Bindings/NodeWrapper.h +++ b/Libraries/LibWeb/Bindings/NodeWrapper.h @@ -43,5 +43,7 @@ private: virtual const char* class_name() const override { return "NodeWrapper"; } }; +NodeWrapper* wrap(JS::Heap&, Node&); + } } diff --git a/Libraries/LibWeb/Bindings/Wrappable.h b/Libraries/LibWeb/Bindings/Wrappable.h index 35073f4333..fd14d908ff 100644 --- a/Libraries/LibWeb/Bindings/Wrappable.h +++ b/Libraries/LibWeb/Bindings/Wrappable.h @@ -46,7 +46,7 @@ private: }; template -inline Wrapper* wrap(JS::Heap& heap, NativeObject& native_object) +inline Wrapper* wrap_impl(JS::Heap& heap, NativeObject& native_object) { if (!native_object.wrapper()) native_object.set_wrapper(*heap.allocate(native_object)); diff --git a/Libraries/LibWeb/DOM/CanvasRenderingContext2D.cpp b/Libraries/LibWeb/DOM/CanvasRenderingContext2D.cpp new file mode 100644 index 0000000000..4e2bc49d7b --- /dev/null +++ b/Libraries/LibWeb/DOM/CanvasRenderingContext2D.cpp @@ -0,0 +1,44 @@ +#include +#include +#include +#include + +namespace Web { + +CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement& element) + : m_element(element.make_weak_ptr()) +{ +} + +CanvasRenderingContext2D::~CanvasRenderingContext2D() +{ +} + +void CanvasRenderingContext2D::set_fill_style(String style) +{ + m_fill_style = Gfx::Color::from_string(style).value_or(Color::Black); +} + +String CanvasRenderingContext2D::fill_style() const +{ + return m_fill_style.to_string(); +} + +void CanvasRenderingContext2D::fill_rect(int x, int y, int width, int height) +{ + auto painter = this->painter(); + if (!painter) + return; + + painter->fill_rect({ x, y, width, height }, m_fill_style); +} + +OwnPtr CanvasRenderingContext2D::painter() +{ + if (!m_element) + return nullptr; + + return make(m_element->ensure_bitmap()); +} + +} diff --git a/Libraries/LibWeb/DOM/CanvasRenderingContext2D.h b/Libraries/LibWeb/DOM/CanvasRenderingContext2D.h new file mode 100644 index 0000000000..8a36742015 --- /dev/null +++ b/Libraries/LibWeb/DOM/CanvasRenderingContext2D.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include +#include + +namespace Web { + +class CanvasRenderingContext2D + : public RefCounted + , public Bindings::Wrappable { + + AK_MAKE_NONCOPYABLE(CanvasRenderingContext2D); + AK_MAKE_NONMOVABLE(CanvasRenderingContext2D); + +public: + using WrapperType = Bindings::CanvasRenderingContext2DWrapper; + + static NonnullRefPtr create(HTMLCanvasElement& element) { return adopt(*new CanvasRenderingContext2D(element)); } + ~CanvasRenderingContext2D(); + + void set_fill_style(String); + String fill_style() const; + + void fill_rect(int x, int y, int width, int height); + +private: + explicit CanvasRenderingContext2D(HTMLCanvasElement&); + + OwnPtr painter(); + + WeakPtr m_element; + + Gfx::Color m_fill_style; +}; + +} diff --git a/Libraries/LibWeb/DOM/ElementFactory.cpp b/Libraries/LibWeb/DOM/ElementFactory.cpp index 3eef44c953..6d0998d719 100644 --- a/Libraries/LibWeb/DOM/ElementFactory.cpp +++ b/Libraries/LibWeb/DOM/ElementFactory.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -85,6 +86,8 @@ NonnullRefPtr create_element(Document& document, const String& tag_name } if (lowercase_tag_name == "script") return adopt(*new HTMLScriptElement(document, lowercase_tag_name)); + if (lowercase_tag_name == "canvas") + return adopt(*new HTMLCanvasElement(document, lowercase_tag_name)); return adopt(*new Element(document, lowercase_tag_name)); } diff --git a/Libraries/LibWeb/DOM/HTMLCanvasElement.cpp b/Libraries/LibWeb/DOM/HTMLCanvasElement.cpp new file mode 100644 index 0000000000..106f17bdbf --- /dev/null +++ b/Libraries/LibWeb/DOM/HTMLCanvasElement.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018-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 + +namespace Web { + +HTMLCanvasElement::HTMLCanvasElement(Document& document, const String& tag_name) + : HTMLElement(document, tag_name) +{ +} + +HTMLCanvasElement::~HTMLCanvasElement() +{ +} + +int HTMLCanvasElement::preferred_width() const +{ + bool ok = false; + int width = attribute("width").to_int(ok); + if (ok) + return width; + + return 300; +} + +int HTMLCanvasElement::preferred_height() const +{ + bool ok = false; + int height = attribute("height").to_int(ok); + if (ok) + return height; + + return 300; +} + +RefPtr HTMLCanvasElement::create_layout_node(const StyleProperties* parent_style) const +{ + auto style = document().style_resolver().resolve_style(*this, parent_style); + auto display = style->string_or_fallback(CSS::PropertyID::Display, "inline"); + if (display == "none") + return nullptr; + return adopt(*new LayoutCanvas(*this, move(style))); +} + +CanvasRenderingContext2D* HTMLCanvasElement::get_context(String type) +{ + ASSERT(type.to_lowercase() == "2d"); + dbg() << "get_context with m_context=" << m_context.ptr(); + if (!m_context) + m_context = CanvasRenderingContext2D::create(*this); + dbg() << "get_context returning m_context=" << m_context.ptr(); + return m_context; +} + +Gfx::Bitmap& HTMLCanvasElement::ensure_bitmap() +{ + if (!m_bitmap || m_bitmap->size() != Gfx::Size(preferred_width(), preferred_height())) { + m_bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::RGBA32, { preferred_width(), preferred_height() }); + } + return *m_bitmap; +} + +} diff --git a/Libraries/LibWeb/DOM/HTMLCanvasElement.h b/Libraries/LibWeb/DOM/HTMLCanvasElement.h new file mode 100644 index 0000000000..7407d6d9b9 --- /dev/null +++ b/Libraries/LibWeb/DOM/HTMLCanvasElement.h @@ -0,0 +1,66 @@ +/* + * 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 +#include +#include + +namespace Web { + +class LayoutDocument; + +class HTMLCanvasElement : public HTMLElement { +public: + using WrapperType = Bindings::HTMLCanvasElementWrapper; + + HTMLCanvasElement(Document&, const String& tag_name); + virtual ~HTMLCanvasElement() override; + + int preferred_width() const; + int preferred_height() const; + + const Gfx::Bitmap* bitmap() const { return m_bitmap; } + Gfx::Bitmap& ensure_bitmap(); + + CanvasRenderingContext2D* get_context(String type); + +private: + virtual RefPtr create_layout_node(const StyleProperties* parent_style) const override; + + RefPtr m_bitmap; + RefPtr m_context; +}; + +template<> +inline bool is(const Node& node) +{ + return is(node) && to(node).tag_name().to_lowercase() == "canvas"; +} + + +} diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index fda55c53f5..2e2e5f437a 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -28,19 +28,24 @@ namespace Web { +class CanvasRenderingContext2D; class Document; class Element; class EventListener; class EventTarget; class Frame; +class HTMLElement; +class HTMLCanvasElement; class HtmlView; class Node; namespace Bindings { +class CanvasRenderingContext2DWrapper; class DocumentWrapper; class EventListenerWrapper; class EventTargetWrapper; +class HTMLCanvasElementWrapper; class NodeWrapper; class Wrappable; class Wrapper; diff --git a/Libraries/LibWeb/Layout/LayoutCanvas.cpp b/Libraries/LibWeb/Layout/LayoutCanvas.cpp new file mode 100644 index 0000000000..39b81f8454 --- /dev/null +++ b/Libraries/LibWeb/Layout/LayoutCanvas.cpp @@ -0,0 +1,64 @@ +/* + * 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 + +namespace Web { + +LayoutCanvas::LayoutCanvas(const HTMLCanvasElement& element, NonnullRefPtr style) + : LayoutReplaced(element, move(style)) +{ +} + +LayoutCanvas::~LayoutCanvas() +{ +} + +void LayoutCanvas::layout() +{ + rect().set_width(node().preferred_width()); + rect().set_height(node().preferred_height()); + LayoutReplaced::layout(); +} + +void LayoutCanvas::render(RenderingContext& context) +{ + if (!is_visible()) + return; + + // FIXME: This should be done at a different level. Also rect() does not include padding etc! + if (!context.viewport_rect().intersects(enclosing_int_rect(rect()))) + return; + + if (node().bitmap()) + context.painter().draw_scaled_bitmap(enclosing_int_rect(rect()), *node().bitmap(), node().bitmap()->rect()); + LayoutReplaced::render(context); +} + +} diff --git a/Libraries/LibWeb/Layout/LayoutCanvas.h b/Libraries/LibWeb/Layout/LayoutCanvas.h new file mode 100644 index 0000000000..e2613fc780 --- /dev/null +++ b/Libraries/LibWeb/Layout/LayoutCanvas.h @@ -0,0 +1,57 @@ +/* + * 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 +#include + +namespace Web { + +class HTMLCanvasElement; + +class LayoutCanvas : public LayoutReplaced { +public: + LayoutCanvas(const HTMLCanvasElement&, NonnullRefPtr); + virtual ~LayoutCanvas() override; + + virtual void layout() override; + virtual void render(RenderingContext&) override; + + const HTMLCanvasElement& node() const { return static_cast(LayoutReplaced::node()); } + +private: + virtual const char* class_name() const override { return "LayoutCanvas"; } + virtual bool is_canvas() const override { return true; } +}; + +template<> +inline bool is(const LayoutNode& node) +{ + return node.is_canvas(); +} + +} diff --git a/Libraries/LibWeb/Layout/LayoutNode.h b/Libraries/LibWeb/Layout/LayoutNode.h index 9d4f0a05c7..22557a9fce 100644 --- a/Libraries/LibWeb/Layout/LayoutNode.h +++ b/Libraries/LibWeb/Layout/LayoutNode.h @@ -87,6 +87,7 @@ public: virtual bool is_replaced() const { return false; } virtual bool is_widget() const { return false; } virtual bool is_image() const { return false; } + virtual bool is_canvas() const { return false; } virtual bool is_box() const { return false; } virtual bool is_table() const { return false; } virtual bool is_table_row() const { return false; } diff --git a/Libraries/LibWeb/Makefile b/Libraries/LibWeb/Makefile index e4d060a084..2b6a5f9d9a 100644 --- a/Libraries/LibWeb/Makefile +++ b/Libraries/LibWeb/Makefile @@ -1,7 +1,9 @@ LIBWEB_OBJS = \ + Bindings/CanvasRenderingContext2DWrapper.o \ Bindings/DocumentWrapper.o \ Bindings/EventListenerWrapper.o \ Bindings/EventTargetWrapper.o \ + Bindings/HTMLCanvasElementWrapper.o \ Bindings/NodeWrapper.o \ Bindings/Wrappable.o \ CSS/DefaultStyleSheetSource.o \ @@ -14,6 +16,7 @@ LIBWEB_OBJS = \ CSS/StyleRule.o \ CSS/StyleSheet.o \ CSS/StyleValue.o \ + DOM/CanvasRenderingContext2D.o \ DOM/CharacterData.o \ DOM/Comment.o \ DOM/Document.o \ @@ -26,6 +29,7 @@ LIBWEB_OBJS = \ DOM/HTMLBRElement.o \ DOM/HTMLBlinkElement.o \ DOM/HTMLBodyElement.o \ + DOM/HTMLCanvasElement.o \ DOM/HTMLElement.o \ DOM/HTMLFontElement.o \ DOM/HTMLFormElement.o \ @@ -52,6 +56,7 @@ LIBWEB_OBJS = \ Layout/LayoutBlock.o \ Layout/LayoutBox.o \ Layout/LayoutBreak.o \ + Layout/LayoutCanvas.o \ Layout/LayoutDocument.o \ Layout/LayoutImage.o \ Layout/LayoutInline.o \ -- cgit v1.2.3