summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-04-21 23:49:51 +0200
committerAndreas Kling <kling@serenityos.org>2020-04-21 23:49:51 +0200
commit2d4c91df8ef30f248b0220cf431aac364a713bbf (patch)
tree52751ce7536fd87797bbe247929dd4f94c82100e
parent54133c683d3c62c1561552b1f7e6b3d262ae8011 (diff)
downloadserenity-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.cpp37
-rw-r--r--Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.h3
-rw-r--r--Libraries/LibWeb/Bindings/ImageDataWrapper.cpp95
-rw-r--r--Libraries/LibWeb/Bindings/ImageDataWrapper.h55
-rw-r--r--Libraries/LibWeb/DOM/CanvasRenderingContext2D.cpp15
-rw-r--r--Libraries/LibWeb/DOM/CanvasRenderingContext2D.h3
-rw-r--r--Libraries/LibWeb/DOM/ImageData.cpp86
-rw-r--r--Libraries/LibWeb/DOM/ImageData.h61
-rw-r--r--Libraries/LibWeb/Forward.h2
-rw-r--r--Libraries/LibWeb/Makefile2
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 \