LibGfx: Simplify path storage and tidy up APIs

Rather than make path segments virtual and refcounted let's store
`Gfx::Path`s as a list of `FloatPoints` and a separate list of commands.

This reduces the size of paths, for example, a `MoveTo` goes from 24
bytes to 9 bytes (one point + a single byte command), and removes a
layer of indirection when accessing segments. A nice little bonus is
transforming a path can now be done by applying the transform to all
points in the path (without looking at the commands).

Alongside this there's been a few minor API changes:

- `path.segments()` has been removed
  * All current uses could be replaced by a new `path.is_empty()` API
  * There's also now an iterator for looping over `Gfx::Path` segments
- `path.add_path(other_path)` has been removed
  * This was a duplicate of `path.append_path(other_path)`
- `path.ensure_subpath(point)` has been removed
  * Had one use and is equivalent to an `is_empty()` check + `move_to()`
- `path.close()` and `path.close_all_subpaths()` assume an implicit
  `moveto 0,0` if there's no `moveto` at the start of a path (for
  consistency with `path.segmentize_path()`).

Only the last point could change behaviour (though in LibWeb/SVGs all
paths start with a `moveto` as per the spec, it's only possible to
construct a path without a starting `moveto` via LibGfx APIs).
This commit is contained in:
MacDue 2024-03-17 20:23:17 +00:00 committed by Andreas Kling
commit 8057542dea
Notes: sideshowbarker 2024-07-17 10:54:57 +09:00
9 changed files with 237 additions and 273 deletions

View file

@ -129,7 +129,8 @@ WebIDL::ExceptionOr<void> CanvasPath::arc_to(double x1, double y1, double x2, do
// 2. Ensure there is a subpath for (x1, y1).
auto transform = active_transform();
m_path.ensure_subpath(transform.map(Gfx::FloatPoint { x1, y1 }));
if (m_path.is_empty())
m_path.move_to(transform.map(Gfx::FloatPoint { x1, y1 }));
// 3. If radius is negative, then throw an "IndexSizeError" DOMException.
if (radius < 0)