...traversal. We've already fixed step 3 and 9 to not filter out
non-positioned stacking contexts, because modern CSS has more ways to
create stacking context besides being positioned with z-index (like by
using "transform", "filter" or "clip-path" properties).
See following spec issue for more details https://github.com/w3c/csswg-drafts/issues/2717
Visual improvement on https://basecamp.com/
Prior to this change, SVGs were following the CSS painting order, which
means SVG boxes could have established stacking context and be sorted by
z-index. There is a section in the spec that defines what kind of SVG
boxes should create a stacking context
https://www.w3.org/TR/SVG2/render.html#EstablishingStackingContex
Although this spec is marked as a draft and rendering order described in
this spec does not match what other engines do.
This spec issue comment has a good summary of what other engines
actually do regarding painting order
https://github.com/w3c/svgwg/issues/264#issuecomment-246432360
"as long as you're relying solely on the default z-index (which SVG1
does, by definition), nothing ever changes order when you apply
opacity/filter/etc".
This change aligns our implementation with other engines by forbidding
SVGs to create a formatting context and painting them in order they are
defined in tree tree.
By storing a list of positioned and floating descendants within the
stacking context tree node, we can eliminate the need for costly
paintable tree traversals during hit-testing.
This optimization results in hit-testing being 2 to 2.5 times faster
on https://ziglang.org/documentation/master/
This change modifies hit_test() to no longer return the first paintable
encountered at a specified position. Instead, this function accepts a
callback that is invoked for each paintable located at a position, in
hit-testing order.
This modification will allow us to reuse this call for
`Document.elementsFromPoint()` in upcoming changes.
Now, instead of resolving "transform" and "transform-origin" during the
construction of the stacking context tree, we do so during the layout
commit.
This is part of a refactoring effort to make the paintable tree
independent from the layout tree.
With this change, a stacking context can be established by any
paintable, including inline paintables. The stacking context traversal
is updated to remove the assumption that the stacking context root is
paintable box.
Grid specification https://www.w3.org/TR/css-grid-2/#z-order defines
special painting order for grid items which should be the same as for
defined for inline-blocks in CSS2.
Eventually we should not need the layout tree for anything when painting
and this code will only look at the paint tree. For now, this is just
another step in that direction.
Previously stacking contexts were only painted in steps 3, 8, and 9.
These steps are only meant to cover positioned elements (as per
https://www.w3.org/TR/CSS22/zindex.html). This meant that elements with
opacity (which forms a stacking context) could end up painted above
elements that actually occlude them.
Stacking contexts are sorted after building a tree of them. They are
sorted by z-index first, DOM tree order second.
Sorting was previously *very* slow on pages with many stacking contexts.
That was because the sort() function used Node::is_before() in the
quick_sort comparator to see if one StackingContext was before another.
is_before() does tree traversal and can take quite a long time per call.
This patch avoids all that by letting StackingContext know its index
among all StackingContexts within the same document in tree order.
There's a noticeable snappiness increase on the CSS-FLEXBOX-1 spec page,
for instance. :^)
...and also for hit testing, which is involved in most of them.
Much of this is temporary conversions and other awkwardness, which
should resolve itself as the rest of LibWeb is converted to these new
types. Hopefully. :thousandyakstare:
When mousing over twitter, 17% of time was spent computing stacking
context transform origins. Since this never changes after the stacking
context is created, we can cache it and avoid all that work.
This is mainly so we can easily read that matrix later, but also has the
benefit of only calculating the matrix once, instead of every time we
paint. :^)
Since there is currently no easy way to handle rotations and skews
with LibGfx this only implements translation and scaling by first
constructing a general 4x4 transformation matrix like outlined in
the css-transforms-1 specification. This is then downgraded to a
Gfx::AffineTransform in order to transform the destination rectangle
used with draw_scaled_bitmap()
While rotation would be nice this already looks pretty good :^)
Instead of calling quick_sort() every time a StackingContext child
is added to a parent, we now do a single pass of sorting work after the
full StackingContext tree has been built.
Before this change, the quick_sort() was ~13.5% of the profile while
hovering links on GitHub in the Browser. After the change, it's down to
~0.6%. Pretty good! :^)
SPDX License Identifiers are a more compact / standardized
way of representing file license information.
See: https://spdx.dev/resources/use/#identifiers
This was done with the `ambr` search and replace tool.
ambr --no-parent-ignore --key-from-file --rep-from-file key.txt rep.txt *