LibWeb: Add canvas.strokeRect(), and fix scale & translate

Add an implementation of CanvasRenderingContext2DWrapper.strokeRect().
While implementing this I fixed fillRect() and the new strokeRect() to
honor the .scale() and .translate() values that had previously been plumbed.

Also enhance the canvas.html demo to utilize strokeRect(), scale(), and translate().
This commit is contained in:
Brian Gianforcaro 2020-04-07 01:09:17 -07:00 committed by Andreas Kling
parent 7291d5c86f
commit 39855fe9ef
5 changed files with 80 additions and 3 deletions

View file

@ -16,8 +16,20 @@ canvas {
<script>
document.addEventListener("DOMContentLoaded", function() {
ctx = document.getElementById("foo").getContext("2d");
ctx.fillStyle = 'red';
ctx.fillRect(10, 10, 200, 100);
var width = 200;
var height = 100;
for (var i = 0; i < 2; i++)
{
ctx.fillStyle = 'red';
ctx.fillRect(10, 10, width, height);
ctx.strokeStyle = 'blue';
ctx.strokeRect(10, 10, width, height);
ctx.scale(0.5, 0.5);
ctx.translate(10 + width * 2, 10 + height * 2);
}
});
</script>
</head>

View file

@ -47,6 +47,8 @@ CanvasRenderingContext2DWrapper::CanvasRenderingContext2DWrapper(CanvasRendering
put_native_function("fillRect", fill_rect, 4);
put_native_function("scale", scale, 2);
put_native_function("translate", translate, 2);
put_native_property("strokeStyle", stroke_style_getter, stroke_style_setter);
put_native_function("strokeRect", stroke_rect, 4);
}
CanvasRenderingContext2DWrapper::~CanvasRenderingContext2DWrapper()
@ -73,6 +75,17 @@ JS::Value CanvasRenderingContext2DWrapper::fill_rect(JS::Interpreter& interprete
return JS::js_undefined();
}
JS::Value CanvasRenderingContext2DWrapper::stroke_rect(JS::Interpreter& interpreter)
{
auto* impl = impl_from(interpreter);
if (!impl)
return {};
auto& arguments = interpreter.call_frame().arguments;
if (arguments.size() >= 4)
impl->stroke_rect(arguments[0].to_i32(), arguments[1].to_i32(), arguments[2].to_i32(), arguments[3].to_i32());
return JS::js_undefined();
}
JS::Value CanvasRenderingContext2DWrapper::scale(JS::Interpreter& interpreter)
{
auto* impl = impl_from(interpreter);
@ -109,5 +122,19 @@ void CanvasRenderingContext2DWrapper::fill_style_setter(JS::Interpreter& interpr
impl->set_fill_style(value.to_string());
}
JS::Value CanvasRenderingContext2DWrapper::stroke_style_getter(JS::Interpreter& interpreter)
{
auto* impl = impl_from(interpreter);
if (!impl)
return {};
return JS::js_string(interpreter, impl->stroke_style());
}
void CanvasRenderingContext2DWrapper::stroke_style_setter(JS::Interpreter& interpreter, JS::Value value)
{
if (auto* impl = impl_from(interpreter))
impl->set_stroke_style(value.to_string());
}
}
}

View file

@ -43,10 +43,13 @@ private:
virtual const char* class_name() const override { return "CanvasRenderingContext2DWrapper"; }
static JS::Value fill_rect(JS::Interpreter&);
static JS::Value stroke_rect(JS::Interpreter&);
static JS::Value scale(JS::Interpreter&);
static JS::Value translate(JS::Interpreter&);
static JS::Value fill_style_getter(JS::Interpreter&);
static void fill_style_setter(JS::Interpreter&, JS::Value);
static JS::Value stroke_style_getter(JS::Interpreter&);
static void stroke_style_setter(JS::Interpreter&, JS::Value);
NonnullRefPtr<CanvasRenderingContext2D> m_impl;
};

View file

@ -56,11 +56,32 @@ void CanvasRenderingContext2D::fill_rect(int x, int y, int width, int height)
if (!painter)
return;
Gfx::Rect rect(x, y, width, height);
Gfx::Rect rect = compute_rect(x, y, width, height);
painter->fill_rect(rect, m_fill_style);
did_draw(rect);
}
void CanvasRenderingContext2D::set_stroke_style(String style)
{
m_stroke_style = Gfx::Color::from_string(style).value_or(Color::Black);
}
String CanvasRenderingContext2D::stroke_style() const
{
return m_fill_style.to_string();
}
void CanvasRenderingContext2D::stroke_rect(int x, int y, int width, int height)
{
auto painter = this->painter();
if (!painter)
return;
Gfx::Rect rect = compute_rect(x, y, width, height);
painter->draw_rect(rect, m_stroke_style);
did_draw(rect);
}
void CanvasRenderingContext2D::scale(double sx, double sy)
{
// FIXME: Actually do something with the scale factor!
@ -77,6 +98,14 @@ void CanvasRenderingContext2D::translate(double x, double y)
m_translate_y = y;
}
Gfx::Rect CanvasRenderingContext2D::compute_rect(int x, int y, int width, int height)
{
return Gfx::Rect((x + m_translate_x) * m_scale_x,
(y + m_translate_y) * m_scale_y,
width * m_scale_x,
height * m_scale_y);
}
void CanvasRenderingContext2D::did_draw(const Gfx::Rect&)
{
// FIXME: Make use of the rect to reduce the invalidated area when possible.

View file

@ -49,13 +49,18 @@ public:
void set_fill_style(String);
String fill_style() const;
void set_stroke_style(String);
String stroke_style() const;
void fill_rect(int x, int y, int width, int height);
void stroke_rect(int x, int y, int width, int height);
void scale(double sx, double sy);
void translate(double x, double y);
private:
explicit CanvasRenderingContext2D(HTMLCanvasElement&);
Gfx::Rect compute_rect(int x, int y, int width, int height);
void did_draw(const Gfx::Rect&);
OwnPtr<Gfx::Painter> painter();
@ -67,6 +72,7 @@ private:
double m_translate_x { 0 };
double m_translate_y { 0 };
Gfx::Color m_fill_style;
Gfx::Color m_stroke_style;
};
}