Browse Source

LibWeb: Add CanvasRenderingContext2D.drawImage(image, x, y)

This function allows you to draw a loaded <img> element into a canvas.
Andreas Kling 5 years ago
parent
commit
067ea5a2e0

+ 26 - 0
Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.cpp

@@ -27,10 +27,13 @@
 #include <AK/FlyString.h>
 #include <AK/FlyString.h>
 #include <AK/Function.h>
 #include <AK/Function.h>
 #include <LibJS/Interpreter.h>
 #include <LibJS/Interpreter.h>
+#include <LibJS/Runtime/Error.h>
 #include <LibJS/Runtime/PrimitiveString.h>
 #include <LibJS/Runtime/PrimitiveString.h>
 #include <LibJS/Runtime/Value.h>
 #include <LibJS/Runtime/Value.h>
 #include <LibWeb/Bindings/CanvasRenderingContext2DWrapper.h>
 #include <LibWeb/Bindings/CanvasRenderingContext2DWrapper.h>
+#include <LibWeb/Bindings/HTMLImageElementWrapper.h>
 #include <LibWeb/DOM/CanvasRenderingContext2D.h>
 #include <LibWeb/DOM/CanvasRenderingContext2D.h>
+#include <LibWeb/DOM/HTMLImageElement.h>
 
 
 namespace Web {
 namespace Web {
 namespace Bindings {
 namespace Bindings {
@@ -49,6 +52,7 @@ CanvasRenderingContext2DWrapper::CanvasRenderingContext2DWrapper(CanvasRendering
     put_native_function("translate", translate, 2);
     put_native_function("translate", translate, 2);
     put_native_property("strokeStyle", stroke_style_getter, stroke_style_setter);
     put_native_property("strokeStyle", stroke_style_getter, stroke_style_setter);
     put_native_function("strokeRect", stroke_rect, 4);
     put_native_function("strokeRect", stroke_rect, 4);
+    put_native_function("drawImage", draw_image, 3);
 }
 }
 
 
 CanvasRenderingContext2DWrapper::~CanvasRenderingContext2DWrapper()
 CanvasRenderingContext2DWrapper::~CanvasRenderingContext2DWrapper()
@@ -86,6 +90,28 @@ JS::Value CanvasRenderingContext2DWrapper::stroke_rect(JS::Interpreter& interpre
     return JS::js_undefined();
     return JS::js_undefined();
 }
 }
 
 
+JS::Value CanvasRenderingContext2DWrapper::draw_image(JS::Interpreter& interpreter)
+{
+    auto* impl = impl_from(interpreter);
+    if (!impl)
+        return {};
+    auto& arguments = interpreter.call_frame().arguments;
+    if (arguments.size() < 3)
+        return interpreter.throw_exception<JS::TypeError>("drawImage() needs more arguments");
+
+    auto* image_argument = arguments[0].to_object(interpreter.heap());
+    if (!image_argument)
+        return {};
+    if (StringView(image_argument->class_name()) != "HTMLImageElementWrapper")
+        return interpreter.throw_exception<JS::TypeError>(String::format("Image is not an HTMLImageElement, it's an %s", image_argument->class_name()));
+
+    auto x = arguments[1].to_double();
+    auto y = arguments[2].to_double();
+
+    impl->draw_image(static_cast<const HTMLImageElementWrapper&>(*image_argument).node(), x, y);
+    return JS::js_undefined();
+}
+
 JS::Value CanvasRenderingContext2DWrapper::scale(JS::Interpreter& interpreter)
 JS::Value CanvasRenderingContext2DWrapper::scale(JS::Interpreter& interpreter)
 {
 {
     auto* impl = impl_from(interpreter);
     auto* impl = impl_from(interpreter);

+ 1 - 0
Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.h

@@ -44,6 +44,7 @@ private:
 
 
     static JS::Value fill_rect(JS::Interpreter&);
     static JS::Value fill_rect(JS::Interpreter&);
     static JS::Value stroke_rect(JS::Interpreter&);
     static JS::Value stroke_rect(JS::Interpreter&);
+    static JS::Value draw_image(JS::Interpreter&);
     static JS::Value scale(JS::Interpreter&);
     static JS::Value scale(JS::Interpreter&);
     static JS::Value translate(JS::Interpreter&);
     static JS::Value translate(JS::Interpreter&);
     static JS::Value fill_style_getter(JS::Interpreter&);
     static JS::Value fill_style_getter(JS::Interpreter&);

+ 17 - 0
Libraries/LibWeb/DOM/CanvasRenderingContext2D.cpp

@@ -28,6 +28,7 @@
 #include <LibGfx/Painter.h>
 #include <LibGfx/Painter.h>
 #include <LibWeb/DOM/CanvasRenderingContext2D.h>
 #include <LibWeb/DOM/CanvasRenderingContext2D.h>
 #include <LibWeb/DOM/HTMLCanvasElement.h>
 #include <LibWeb/DOM/HTMLCanvasElement.h>
+#include <LibWeb/DOM/HTMLImageElement.h>
 
 
 namespace Web {
 namespace Web {
 
 
@@ -82,6 +83,22 @@ void CanvasRenderingContext2D::stroke_rect(float x, float y, float width, float
     did_draw(rect);
     did_draw(rect);
 }
 }
 
 
+void CanvasRenderingContext2D::draw_image(const HTMLImageElement& image_element, float x, float y)
+{
+    if (!image_element.bitmap())
+        return;
+
+    auto painter = this->painter();
+    if (!painter)
+        return;
+
+    auto src_rect = image_element.bitmap()->rect();
+    Gfx::FloatRect dst_rect = { x, y, (float)image_element.bitmap()->width(), (float)image_element.bitmap()->height() };
+    auto rect = m_transform.map(dst_rect);
+
+    painter->draw_scaled_bitmap(enclosing_int_rect(rect), *image_element.bitmap(), src_rect);
+}
+
 void CanvasRenderingContext2D::scale(float sx, float sy)
 void CanvasRenderingContext2D::scale(float sx, float sy)
 {
 {
     dbg() << "CanvasRenderingContext2D::scale(): " << sx << ", " << sy;
     dbg() << "CanvasRenderingContext2D::scale(): " << sx << ", " << sy;

+ 3 - 0
Libraries/LibWeb/DOM/CanvasRenderingContext2D.h

@@ -55,6 +55,9 @@ public:
 
 
     void fill_rect(float x, float y, float width, float height);
     void fill_rect(float x, float y, float width, float height);
     void stroke_rect(float x, float y, float width, float height);
     void stroke_rect(float x, float y, float width, float height);
+
+    void draw_image(const HTMLImageElement&, float x, float y);
+
     void scale(float sx, float sy);
     void scale(float sx, float sy);
     void translate(float x, float y);
     void translate(float x, float y);