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
parent 14005f89a6
commit 8057542dea
9 changed files with 237 additions and 273 deletions

View File

@@ -279,10 +279,10 @@ public:
path.line_to(TRY(read_point()));
break;
case PathCommand::HorizontalLine:
path.line_to({ TRY(read_unit()), path.segments().last()->point().y() });
path.line_to({ TRY(read_unit()), path.last_point().y() });
break;
case PathCommand::VerticalLine:
path.line_to({ path.segments().last()->point().x(), TRY(read_unit()) });
path.line_to({ path.last_point().x(), TRY(read_unit()) });
break;
case PathCommand::CubicBezier: {
auto control_0 = TRY(read_point());