Cuts display list size, mostly because now we avoid lots of FillRect
previusly recorded for boxes with transparent background.
Website | DisplayList Items Before | DisplayList Items After
-------------|--------------------------|-------------------------
ladybird.org | 1431 | 1117
null.com | 4714 | 4484
discord.com | 5360 | 4992
`paint_background()` is invoked for each PaintableBox, so by avoiding
save/restore pair emitted for each call, we substantially decrease
display list size.
Website | DisplayList Items Before | DisplayList Items After
-------------|--------------------------|-------------------------
ladybird.org | 2753 | 1431
null.com | 5298 | 4714
discord.com | 6598 | 5360
Initially ClippableAndScrollable was introduced, because we had
PaintableBox and InlinePaintable and both wanted to share clipping and
scrolling logic. Now, when InlinePaintable is gone, we could inline
ClippableAndScrollable implementation into PaintableBox.
A "namespace prefix map", see:
https://w3c.github.io/DOM-Parsing/#the-namespace-prefix-map
Is meant to also hold null namespaces:
> where namespaceURI values are the map's unique keys
> (which can include the null value representing no namespace)
Which we previously neglected. This resulted in a crash for
the updated WPT test.
Previously, we always applied the enclosing clip rectangle for all paint
phases except overlays, and the own clip rectangle for the background
and foreground phases. The problem is that applying a clip rectangle
means emitting an AddClipRect display list item for each clip rectangle
in the containing block. With this change, we choose whether to include
the own clip based on the paint phase and this way avoid emitting
AddClipRect for enclosing clip rectangles twice.
Own clip rect is alredy applied in `PaintableBox::before_paint()` for
all paintables with lines, so there's no need to do it once again in
`PaintableWithLines::paint()`.
Own clip rect is alredy applied in `PaintableBox::before_paint()` for
all image paintables, so there's no need to do it once again in
`ImagePaintable::paint()`.
Unbalanced save and restore means that effects only relevant to a
stacking context leak outside, which is never expected behavior. Having
a `VERIFY()` for that makes it much easier to catch such issues.
These were only used in SVGSVGPaintable to apply scroll frame id, which
is already handled by `before_paint()` and `after_paint()` hooks in
PaintableBox.
Unbalanced save/restore within display list items recorded for a
paintable means that some state only relevant for the paintable leaks to
subsequent paintables, which is never expected behavior.
...with inline children. This fixes an issue when we ignore abspos boxes
contained by PaintableWithLines while calculating overflow rect size.
Lots of layout tests are affected, because now PaintableWithLines has
overflow rect.
`Text/input/DOM/Element-set-scroll-left.html` is also affected and now
matches other browsers.
Some SVG presentation attributes are only supported on certain
elements. We now support these special cases for attributes and
elements that we currently have implemented.
We were always delegating hit tests to PaintableBox if a
PaintableWithLines has no fragments, which means that anonymous
containers could overlap with previous siblings and prioritize their
border box rect. Instead, the nearest non-anonymous ancestor should take
care of hit testing the children so the correct order is maintained.
To achieve this, we no longer do an early hit test in
PaintableWithLines::hit_test() if there are no fragments and default
to the later PaintableBox::hit_test() call that does take anonymous
containers into account.
Fixes the issue seen in #4864.
This way we can reuse the logic between PaintableWithLines and
PaintableBox. It also introduces the .is_positioned() check for the
children of a PaintableWithLines, which makes sure to skip positioned
child nodes since those are handled by the StackingContext.
A PaintableWithLines will first try to see if there are any fragments
that have a hit. If not, it falls back to hit testing against its border
box rect.
However, inline content is often hoisted out of its parent into an
anonymous container to maintain the invariant that all layout nodes
either have inline or block level children. If that's the case, we
should not check the border box rect of the anonymous container, because
we might trigger a hit too early if the node has previous siblings in
its original parent node that overlap with their bounds.
By ignoring anonymous nodes, we leave the border box hit testing to the
nearest non-anonymous ancestor, which correctly applies the hit testing
order to its children.
Note that the border box rect checks whether the _untransformed_ point
is inside of it, which mirrors the behavior of PaintableBox::hit_test().
We should not need to check if the result of a hit test is actually
visible for hit testing, because if it wasn't, it should not have been
returned from PaintableBox::hit_test() in the first place.
The included WPT test passes through -1 which ends up modolo'ing
to u32 max at the IDL conversion layer, resulting in an unsigned
overflow when checking bounds.
For simplicity, this requires that the setlike Foo class has a
`void on_set_modified_from_js(Badge<Bindings::FooPrototype>)` method.
This will be called after the set is modified from a generated `add()`,
`delete()`, or `clear()` method.