diff --git a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasPath.cpp b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasPath.cpp
index 83d2713cf22..86a2b5f0c38 100644
--- a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasPath.cpp
+++ b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasPath.cpp
@@ -17,6 +17,12 @@ Gfx::AffineTransform CanvasPath::active_transform() const
return {};
}
+void CanvasPath::ensure_subpath(float x, float y)
+{
+ if (m_path.is_empty())
+ m_path.move_to(active_transform().map(Gfx::FloatPoint { x, y }));
+}
+
void CanvasPath::close_path()
{
m_path.close();
@@ -33,9 +39,21 @@ void CanvasPath::move_to(float x, float y)
m_path.move_to(active_transform().map(Gfx::FloatPoint { x, y }));
}
+// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-lineto
void CanvasPath::line_to(float x, float y)
{
- m_path.line_to(active_transform().map(Gfx::FloatPoint { x, y }));
+ // 1. If either of the arguments are infinite or NaN, then return.
+ if (!isfinite(x) || !isfinite(y))
+ return;
+
+ if (m_path.is_empty()) {
+ // 2. If the object's path has no subpaths, then ensure there is a subpath for (x, y).
+ ensure_subpath(x, y);
+ } else {
+ // 3. Otherwise, connect the last point in the subpath to the given point (x, y) using a straight line,
+ // and then add the given point (x, y) to the subpath.
+ m_path.line_to(active_transform().map(Gfx::FloatPoint { x, y }));
+ }
}
void CanvasPath::quadratic_curve_to(float cx, float cy, float x, float y)
diff --git a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasPath.h b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasPath.h
index 93c7affeea6..e729abfa419 100644
--- a/Userland/Libraries/LibWeb/HTML/Canvas/CanvasPath.h
+++ b/Userland/Libraries/LibWeb/HTML/Canvas/CanvasPath.h
@@ -48,6 +48,8 @@ protected:
private:
Gfx::AffineTransform active_transform() const;
+ void ensure_subpath(float x, float y);
+
JS::NonnullGCPtr m_self;
Optional m_canvas_state;
Gfx::Path m_path;