diff options
author | Andreas Kling <kling@serenityos.org> | 2020-04-21 23:49:51 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-04-21 23:49:51 +0200 |
commit | 2d4c91df8ef30f248b0220cf431aac364a713bbf (patch) | |
tree | 52751ce7536fd87797bbe247929dd4f94c82100e | |
parent | 54133c683d3c62c1561552b1f7e6b3d262ae8011 (diff) | |
download | serenity-2d4c91df8ef30f248b0220cf431aac364a713bbf.zip |
LibWeb: Add ImageData objects and implement 2D context putImageData()
An ImageData is a wrapper around a Bitmap wrapper around a
JS::Uint8ClampedArray.
-rw-r--r-- | Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.cpp | 37 | ||||
-rw-r--r-- | Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.h | 3 | ||||
-rw-r--r-- | Libraries/LibWeb/Bindings/ImageDataWrapper.cpp | 95 | ||||
-rw-r--r-- | Libraries/LibWeb/Bindings/ImageDataWrapper.h | 55 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/CanvasRenderingContext2D.cpp | 15 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/CanvasRenderingContext2D.h | 3 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/ImageData.cpp | 86 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/ImageData.h | 61 | ||||
-rw-r--r-- | Libraries/LibWeb/Forward.h | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/Makefile | 2 |
10 files changed, 359 insertions, 0 deletions
diff --git a/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.cpp b/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.cpp index a3cef02712..fab041d662 100644 --- a/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.cpp +++ b/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.cpp @@ -33,8 +33,10 @@ #include <LibJS/Runtime/Value.h> #include <LibWeb/Bindings/CanvasRenderingContext2DWrapper.h> #include <LibWeb/Bindings/HTMLImageElementWrapper.h> +#include <LibWeb/Bindings/ImageDataWrapper.h> #include <LibWeb/DOM/CanvasRenderingContext2D.h> #include <LibWeb/DOM/HTMLImageElement.h> +#include <LibWeb/DOM/ImageData.h> namespace Web { namespace Bindings { @@ -62,6 +64,9 @@ CanvasRenderingContext2DWrapper::CanvasRenderingContext2DWrapper(CanvasRendering put_native_function("moveTo", move_to, 0); put_native_function("lineTo", line_to, 0); + put_native_function("createImageData", create_image_data, 2); + put_native_function("putImageData", put_image_data, 3); + put_native_property("lineWidth", line_width_getter, line_width_setter); } @@ -235,5 +240,37 @@ JS::Value CanvasRenderingContext2DWrapper::line_to(JS::Interpreter& interpreter) return JS::js_undefined(); } +JS::Value CanvasRenderingContext2DWrapper::create_image_data(JS::Interpreter& interpreter) +{ + auto* impl = impl_from(interpreter); + if (!impl) + return {}; + i32 width = interpreter.argument(0).to_i32(); + i32 height = interpreter.argument(1).to_i32(); + auto image_data = impl->create_image_data(interpreter.global_object(), width, height); + return wrap(interpreter.heap(), *image_data); +} + +JS::Value CanvasRenderingContext2DWrapper::put_image_data(JS::Interpreter& interpreter) +{ + auto* impl = impl_from(interpreter); + if (!impl) + return {}; + + auto* image_data_object = interpreter.argument(0).to_object(interpreter.heap()); + if (!image_data_object) + return {}; + + if (StringView(image_data_object->class_name()) != "ImageDataWrapper") { + return interpreter.throw_exception<JS::TypeError>("putImageData called with non-ImageData"); + } + + auto& image_data = static_cast<ImageDataWrapper*>(image_data_object)->impl(); + auto x = interpreter.argument(1).to_double(); + auto y = interpreter.argument(2).to_double(); + impl->put_image_data(image_data, x, y); + return JS::js_undefined(); +} + } } diff --git a/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.h b/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.h index ba5205714b..310f0c2588 100644 --- a/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.h +++ b/Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.h @@ -59,6 +59,9 @@ private: static JS::Value move_to(JS::Interpreter&); static JS::Value line_to(JS::Interpreter&); + static JS::Value create_image_data(JS::Interpreter&); + static JS::Value put_image_data(JS::Interpreter&); + NonnullRefPtr<CanvasRenderingContext2D> m_impl; }; diff --git a/Libraries/LibWeb/Bindings/ImageDataWrapper.cpp b/Libraries/LibWeb/Bindings/ImageDataWrapper.cpp new file mode 100644 index 0000000000..c57b96be6f --- /dev/null +++ b/Libraries/LibWeb/Bindings/ImageDataWrapper.cpp @@ -0,0 +1,95 @@ +/* + * 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/Function.h> +#include <LibJS/Interpreter.h> +#include <LibJS/Runtime/Error.h> +#include <LibJS/Runtime/GlobalObject.h> +#include <LibJS/Runtime/Uint8ClampedArray.h> +#include <LibWeb/Bindings/ImageDataWrapper.h> +#include <LibWeb/DOM/ImageData.h> + +namespace Web { +namespace Bindings { + +ImageDataWrapper* wrap(JS::Heap& heap, ImageData& event) +{ + return static_cast<ImageDataWrapper*>(wrap_impl(heap, event)); +} + +ImageDataWrapper::ImageDataWrapper(ImageData& impl) + : Wrapper(*interpreter().global_object().object_prototype()) + , m_impl(impl) +{ + put_native_property("width", width_getter, nullptr); + put_native_property("height", height_getter, nullptr); + put_native_property("data", data_getter, nullptr); +} + +ImageDataWrapper::~ImageDataWrapper() +{ +} + +static ImageData* impl_from(JS::Interpreter& interpreter) +{ + auto* this_object = interpreter.this_value().to_object(interpreter.heap()); + if (!this_object) { + ASSERT_NOT_REACHED(); + return nullptr; + } + if (StringView("ImageDataWrapper") != this_object->class_name()) { + interpreter.throw_exception<JS::TypeError>("That's not an ImageDataWrapper, bro."); + return nullptr; + } + return &static_cast<ImageDataWrapper*>(this_object)->impl(); +} + +JS::Value ImageDataWrapper::width_getter(JS::Interpreter& interpreter) +{ + auto* impl = impl_from(interpreter); + if (!impl) + return {}; + return JS::Value(impl->width()); +} + +JS::Value ImageDataWrapper::height_getter(JS::Interpreter& interpreter) +{ + auto* impl = impl_from(interpreter); + if (!impl) + return {}; + return JS::Value(impl->height()); +} + +JS::Value ImageDataWrapper::data_getter(JS::Interpreter& interpreter) +{ + auto* impl = impl_from(interpreter); + if (!impl) + return {}; + return impl->data(); +} + +} +} diff --git a/Libraries/LibWeb/Bindings/ImageDataWrapper.h b/Libraries/LibWeb/Bindings/ImageDataWrapper.h new file mode 100644 index 0000000000..99552553fd --- /dev/null +++ b/Libraries/LibWeb/Bindings/ImageDataWrapper.h @@ -0,0 +1,55 @@ +/* + * 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/Wrapper.h> + +namespace Web { +namespace Bindings { + +class ImageDataWrapper : public Wrapper { +public: + explicit ImageDataWrapper(ImageData&); + virtual ~ImageDataWrapper() override; + + ImageData& impl() { return m_impl; } + const ImageData& impl() const { return m_impl; } + +private: + virtual const char* class_name() const override { return "ImageDataWrapper"; } + + static JS::Value width_getter(JS::Interpreter&); + static JS::Value height_getter(JS::Interpreter&); + static JS::Value data_getter(JS::Interpreter&); + + NonnullRefPtr<ImageData> m_impl; +}; + +ImageDataWrapper* wrap(JS::Heap&, ImageData&); + +} +} diff --git a/Libraries/LibWeb/DOM/CanvasRenderingContext2D.cpp b/Libraries/LibWeb/DOM/CanvasRenderingContext2D.cpp index 44a5a6cb6f..379e7e21dc 100644 --- a/Libraries/LibWeb/DOM/CanvasRenderingContext2D.cpp +++ b/Libraries/LibWeb/DOM/CanvasRenderingContext2D.cpp @@ -29,6 +29,7 @@ #include <LibWeb/DOM/CanvasRenderingContext2D.h> #include <LibWeb/DOM/HTMLCanvasElement.h> #include <LibWeb/DOM/HTMLImageElement.h> +#include <LibWeb/DOM/ImageData.h> namespace Web { @@ -175,4 +176,18 @@ void CanvasRenderingContext2D::stroke() painter->stroke_path(m_path, m_stroke_style, m_line_width); } +RefPtr<ImageData> CanvasRenderingContext2D::create_image_data(JS::GlobalObject& global_object, int width, int height) const +{ + return ImageData::create_with_size(global_object, width, height); +} + +void CanvasRenderingContext2D::put_image_data(const ImageData& image_data, float x, float y) +{ + auto painter = this->painter(); + if (!painter) + return; + + painter->blit(Gfx::Point(x, y), image_data.bitmap(), image_data.bitmap().rect()); +} + } diff --git a/Libraries/LibWeb/DOM/CanvasRenderingContext2D.h b/Libraries/LibWeb/DOM/CanvasRenderingContext2D.h index dce9683d88..2b46422d60 100644 --- a/Libraries/LibWeb/DOM/CanvasRenderingContext2D.h +++ b/Libraries/LibWeb/DOM/CanvasRenderingContext2D.h @@ -71,6 +71,9 @@ public: void line_to(float x, float y); void stroke(); + RefPtr<ImageData> create_image_data(JS::GlobalObject&, int width, int height) const; + void put_image_data(const ImageData&, float x, float y); + private: explicit CanvasRenderingContext2D(HTMLCanvasElement&); diff --git a/Libraries/LibWeb/DOM/ImageData.cpp b/Libraries/LibWeb/DOM/ImageData.cpp new file mode 100644 index 0000000000..11a17ffeaa --- /dev/null +++ b/Libraries/LibWeb/DOM/ImageData.cpp @@ -0,0 +1,86 @@ +/* + * 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 <LibGfx/Bitmap.h> +#include <LibJS/Runtime/Uint8ClampedArray.h> +#include <LibWeb/DOM/ImageData.h> + +namespace Web { + +RefPtr<ImageData> ImageData::create_with_size(JS::GlobalObject& global_object, int width, int height) +{ + if (width <= 0 || height <= 0) + return nullptr; + + if (width > 16384 || height > 16384) + return nullptr; + + + dbg() << "Creating ImageData with " << width << "x" << height; + + auto* data = JS::Uint8ClampedArray::create(global_object, width * height * 4); + if (!data) + return nullptr; + + auto data_handle = JS::make_handle(data); + + auto bitmap = Gfx::Bitmap::create_wrapper(Gfx::BitmapFormat::RGBA32, Gfx::Size(width, height), width * sizeof(u32), (u32*)data->data()); + if (!bitmap) + return nullptr; + return adopt(*new ImageData(bitmap.release_nonnull(), move(data_handle))); +} + +ImageData::ImageData(NonnullRefPtr<Gfx::Bitmap> bitmap, JS::Handle<JS::Uint8ClampedArray> data) + : m_bitmap(move(bitmap)) + , m_data(move(data)) +{ +} + +ImageData::~ImageData() +{ +} + +int ImageData::width() const +{ + return m_bitmap->width(); +} + +int ImageData::height() const +{ + return m_bitmap->height(); +} + +JS::Uint8ClampedArray* ImageData::data() +{ + return m_data.cell(); +} + +const JS::Uint8ClampedArray* ImageData::data() const +{ + return m_data.cell(); +} + +} diff --git a/Libraries/LibWeb/DOM/ImageData.h b/Libraries/LibWeb/DOM/ImageData.h new file mode 100644 index 0000000000..644f96b43d --- /dev/null +++ b/Libraries/LibWeb/DOM/ImageData.h @@ -0,0 +1,61 @@ +/* + * 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 <LibGfx/Forward.h> +#include <LibJS/Heap/Handle.h> +#include <LibWeb/Bindings/Wrappable.h> + +namespace Web { + +class ImageData + : public RefCounted<ImageData> + , public Bindings::Wrappable { +public: + using WrapperType = Bindings::ImageDataWrapper; + + static RefPtr<ImageData> create_with_size(JS::GlobalObject&, int width, int height); + + ~ImageData(); + + int width() const; + int height() const; + + Gfx::Bitmap& bitmap() { return m_bitmap; } + const Gfx::Bitmap& bitmap() const { return m_bitmap; } + + JS::Uint8ClampedArray* data(); + const JS::Uint8ClampedArray* data() const; + +private: + explicit ImageData(NonnullRefPtr<Gfx::Bitmap>, JS::Handle<JS::Uint8ClampedArray>); + + NonnullRefPtr<Gfx::Bitmap> m_bitmap; + JS::Handle<JS::Uint8ClampedArray> m_data; +}; + +} diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index c75815c3da..96dee4304c 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -42,6 +42,7 @@ class HTMLHeadElement; class HTMLHtmlElement; class HTMLImageElement; class HtmlView; +class ImageData; class LayoutDocument; class LayoutNode; class MouseEvent; @@ -64,6 +65,7 @@ class EventListenerWrapper; class EventTargetWrapper; class HTMLCanvasElementWrapper; class HTMLImageElementWrapper; +class ImageDataWrapper; class MouseEventWrapper; class NodeWrapper; class WindowObject; diff --git a/Libraries/LibWeb/Makefile b/Libraries/LibWeb/Makefile index 63bcd6432d..961648393f 100644 --- a/Libraries/LibWeb/Makefile +++ b/Libraries/LibWeb/Makefile @@ -7,6 +7,7 @@ LIBWEB_OBJS = \ Bindings/EventTargetWrapper.o \ Bindings/HTMLCanvasElementWrapper.o \ Bindings/HTMLImageElementWrapper.o \ + Bindings/ImageDataWrapper.o \ Bindings/MouseEventWrapper.o \ Bindings/NavigatorObject.o \ Bindings/NodeWrapper.o \ @@ -53,6 +54,7 @@ LIBWEB_OBJS = \ DOM/HTMLScriptElement.o \ DOM/HTMLStyleElement.o \ DOM/HTMLTitleElement.o \ + DOM/ImageData.o \ DOM/MouseEvent.o \ DOM/Node.o \ DOM/ParentNode.o \ |