This was resulting in a whole lot of rebuilding whenever a new IDL
interface was added.
Instead, just directly include the prototype in every C++ file which
needs it. While we only really need a forward declaration in each cpp
file; including the full prototype header (which itself only includes
LibJS/Object.h, which is already transitively brought in by
PlatformObject) - it seems like a small price to pay compared to what
feels like a full rebuild of LibWeb whenever a new IDL file is added.
Given all of these includes are only needed for the ::initialize
method, there is probably a smart way of avoiding this problem
altogether. I've considered both using some macro trickery or generating
these functions somehow instead.
Introduces separate layout and paintable type for foreign element.
It is necessary to inherit SVGForeignObjectPaintable from SVGMaskable
in upcoming changes.
This just reuses the layout to compute the bounding box rather than
implementing the full bounding box algorithm, which is likely the slower
option, but also much simpler to implement.
This is enough to fix the faces on https://zengm.com/facesjs/.
These changes are compatible with clang-format 16 and will be mandatory
when we eventually bump clang-format version. So, since there are no
real downsides, let's commit them now.
Going via the `ViewportPaintable` missed some steps (in particular
computing clip rects), which meant nested SVGs within SVGs-as-images
were completely clipped.
This uses the same trick as done for masks in #23554. Each use of an
SVG `<clipPath>` becomes it's own layout subtree rooted at it's user.
This allows each use have it's own layout (which allows supporting
features such as `clipPathUnits`).
Since we drive painting for SVG-as-image manually anyway, there's no
need for them to say they are "ready to paint", since that just causes
unnecessary extra processing in the HTML event loop.
If an unexpected token is encountered when parsing an SVG attribute it
is now immediately propagated with ErrorOr. Previously, some situations
where an unexpected token was encountered could cause a crash.
This URL library ends up being a relatively fundamental base library of
the system, as LibCore depends on LibURL.
This change has two main benefits:
* Moving AK back more towards being an agnostic library that can
be used between the kernel and userspace. URL has never really fit
that description - and is not used in the kernel.
* URL _should_ depend on LibUnicode, as it needs punnycode support.
However, it's not really possible to do this inside of AK as it can't
depend on any external library. This change brings us a little closer
to being able to do that, but unfortunately we aren't there quite
yet, as the code generators depend on LibCore.
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 introduces a WEB_SET_PROTOTYPE_FOR_INTERFACE macro that
caches the interface name in a local static FlyString. This means that
we only pay for FlyString-from-literal lookup once per browser lifetime
instead of every time the interface is instantiated.
Rather than try to lay out masks normally, this updates the TreeBuilder
to create layout nodes for masks as a child of their user (i.e. the
masked element). This allows each use of a mask to be laid out
differently, which makes supporting `maskContentUnits=objectBoundingBox`
fairly easy.
The `SVGFormattingContext` is then updated to lay out masks last (as
their sizing may depend on their parent), and treats them like
viewports.
This is pretty ad-hoc, but the SVG specification does not give any
guidance on how to actually implement this.
Instead of crashing with a TODO() on half of the test cases generated by
Domato, let's just return a zeroed-out SVGAnimatedLength or
SVGAnimatedNumber from getters that return them.
We'll eventually have to implement these correctly, but crashing is not
productive since it blocks us from finding other issues.
Since SVG gradients can reference each other, we have to keep track of
visited gradients when traversing the link chain, or we will recurse
infinitely when there's a reference cycle.
With this the `<circle>` element now correctly parses percentage sizes,
and resolves them relative to the viewport.
The rest of the geometry elements are still left TODO.
This will allow resolving paths that use sizes that are relative to the
viewport. This necessarily removes the on element caching, which has
been redundant for a while as computed paths are stored on the
paintable.
This avoids constantly re-rendering the same SVG image over and over
during painting when it's being used at a couple of different sizes
(for example when used as a CSS background).
In this change, updating layout and painting are moved to the EventLoop
processing steps. This modification allows the addition of resize
observation dispatching that needs to happen in event loop processing
steps and must occur in the following order relative to layout and
painting:
1. Update layout.
2. Gather and broadcast resize observations.
3. Paint.
Painting command executors are defined within the "Painting" namespace,
allowing us to remove this prefix from their names.
This commit performs the following renamings:
- Painting::PaintingCommandExecutor to Painting::CommandExecutor
- Painting::PaintingCommandExecutorCPU to Painting::CommandExecutorCPU
- Painting::PaintingCommandExecutorGPU to Painting::CommandExecutorGPU
Separating the recorder list from the painter will allow us to save it
for later execution without carrying along the painter's state. This
will be useful once we have a separate thread for executing painting
commands, to which we will have to transfer commands from the main
thread.
Preparation for https://github.com/SerenityOS/serenity/pull/23108