1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-16 20:05:07 +00:00
Commit graph

78 commits

Author SHA1 Message Date
Aliaksandr Kalenik
adf0262b54 LubWeb: Call before_children_paint for positioned descendants
Add before_children_paint and after_children_paint calls for
positioned descendants with z-index: auto during painting
2022-11-15 22:53:47 +01:00
Aliaksandr Kalenik
f3d57e1157 LibWeb: Clip hidden overflow by absolute rect of containing block
Since handling overflow: hidden in PaintableBox::before_children_paint
while following paint traversal order can't result in correctly computed
clip rectangle for elements that create their own stacking context
(because before_children_paint is called only for parent but overflow:
hidden can be set somewhere deeper but not in direct ancestor), here
introduced new function PaintableBox::clip_rect() that computes clip
rectangle by looking into containing block.

should_clip_overflow flag that disables clip for absolutely positioned
elements in before_children_paint and after_children_paint is removed
because after changing clip rectangle to be computed from not parent
but containing block it is not needed anymore (absolutely positioned
item is clipped if it's containing block has hidden overflow)
2022-11-15 22:53:47 +01:00
Andreas Kling
5aeb6fec68 LibWeb: Make hit testing traverse positioned descendants in right order
We were doing a forward traversal in hit testing which led to sometimes
incorrect results when multiple boxes were occupying the same X and Y
coordinate.
2022-11-04 10:38:00 +01:00
Aliaksandr Kalenik
e4db71c88b LibWeb: Support translate3d 2022-11-02 11:04:23 +00:00
Andreas Kling
8aab33de5f LibWeb: Skip positioned children in paint_descendants()
Positioned descendants are now handled entirely by paint_internal()
so we can just skip over positioned children in paint_descendants().
This avoids drawing the same boxes multiple times.
2022-10-23 23:32:42 +02:00
Andreas Kling
8bf0e71c0c LibWeb: Paint non-positioned stacking contexts with z-index 0 or auto
As I understand it, these have to be painted interleaved with positioned
descendants in the same z-index category, in tree order.
2022-10-23 23:32:42 +02:00
Andreas Kling
447519f678 LibWeb: Paint positioned descendants with z-index: auto
This "worked" before because all positioned elements would create their
own stacking context. When we stopped doing this, there was nobody to
actually paint positioned descendants with `z-index: auto`.

This patch splits up steps 8 and 9 of the paint order algorithm and
implements step 8 as a paint tree traversal. There's more to step 8 than
I've implemented here, so I've left a FIXME for our future selves.
2022-10-23 23:32:42 +02:00
Andreas Kling
8a0e40c5b0 LibWeb: Update StackingContext::paint_descendants() for new rule
Since positioned elements no longer automatically create stacking
contexts, we can't rely on this assumption when painting descendants of
a stacking context.

In this commit, we fix an issue that manifested as a failure to
Gfx::Painter::restore() in the "Overlay" paint phase. What happened was
that a CSS clip was being applied in the "Background" paint phase, and
then unapplied in the "Overlay" phase. Due to bogus checks in
paint_descendants(), the "Background" phase never ran for positioned
elements, but the "Overlay" phase did.

The check for positioned elements was bogus in the first place and had
never actually worked before, since we would always skip over positioned
descendants due to them having stacking contexts.
2022-10-23 23:32:42 +02:00
Andreas Kling
055a1998c1 LibWeb: StackingContext::paint_descendants() can take const layout node
It doesn't mutate the layout tree in any way.
2022-10-23 23:32:42 +02:00
Aliaksandr Kalenik
66e424a084 LibWeb: Fix pointer-events check in hit_test 2022-10-20 17:58:16 +02:00
Aliaksandr Kalenik
dfc3a4772b LibWeb: Ignore "pointer-events: none" elements in hit_test 2022-10-19 16:11:15 +02:00
Andreas Kling
90b66533d0 LibWeb: Don't hit test all child stacking contexts twice
We're supposed to hit test positive z-index stacking contexts first,
and negative z-index stacking contexts later. Instead, we were hit
testing all stacking contexts both times.

This made hit testing unbearably slow on some websites.

While we're here, also add an extra comment about why stacking contexts
are traversed in reverse order. It tripped me up while looking at this,
so I'm sure it could trip someone else up too.

Regressed in 44057c9482.
2022-10-07 12:10:59 +02:00
Andreas Kling
95a3da86c3 LibWeb: Reset painter translation when painting fixed-position elements
This makes nested position:fixed elements work, previously we'd apply
the viewport scroll offset once at every nesting level.
2022-10-02 21:14:02 +02:00
Hendiadyoin1
e68309144b LibWeb: Don't scale by x, x when a scale x, y is provided as a transform 2022-10-01 21:08:50 +01:00
Luke Wilde
dbe12662b8 LibWeb: Implement matrix3d transform function from css-transforms-2 2022-10-01 14:07:47 +02:00
Luke Wilde
0fdd924db2 LibWeb: Implement rotation transform functions from css-transforms-2 2022-10-01 14:07:47 +02:00
Andreas Kling
b7f9387f69 LibWeb: Don't draw only-translated stacking contexts via bitmap
If the 2D transform in effect is just a simple translation, we don't
need to draw into a temporary bitmap and then transform it. We can
just translate the painter. :^)
2022-09-29 20:10:02 +02:00
MacDue
f6264523b9 LibWeb: Fix destination bitmap edge clip case in transform painting
This fixes an edge case, where the destination rect falls partly
outside the painter, so is clipped to a smaller size in
`get_region_bitmap()` (which needs to be accounted for with an extra
offset).
2022-09-26 01:38:30 +02:00
MacDue
3fad64dfbc LibWeb: Sample the destination when painting element opacity/transform
This now copies the area under the destination to a new bitmap, that
is then scaled to the size of the source. The element is then painted
into that bitmap, which is then scaled and painted back to
the destination. This is done as many effects such as shadows, border
radii, filters, etc require being able to read pixels from the painter.

This does work (and is not that noticeable in many cases), but it does
mean there may be a few scaling artifacts in the background
around transformed elements. Though that was already the case before
anyway for the elements (since it is just a bitmap scale).

What we really want is to (where possible) just scale the paintable
and its descendants, then paint things normally, which would give
much nicer results (but is much more tricky to achieve).

This also now makes it so only a bitmap of the size of the paintable is
copied/created, rather than the whole page.
2022-09-25 18:37:31 +02:00
Andreas Kling
5c6621547c LibWeb: Compute StackingContext transform origin only once
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.
2022-09-24 23:06:09 +02:00
MacDue
c3841e1667 LibWeb: Restore clipping of positioned descendants
63c727a was meant to stop clipping absolutely positioned descendants,
but used `is_positioned()` rather than `is_absolutely_positioned()`,
which meant it disabled clipping in many more cases that it should
have.
2022-09-24 19:06:57 +02:00
Brian Gianforcaro
d0a1775369 Everywhere: Fix a variety of typos
Spelling fixes found by `codespell`.
2022-09-14 04:46:49 +00:00
Andreas Kling
63c727a4a3 LibWeb: Don't clip to containing block when painting abspos descendants 2022-09-14 00:09:49 +02:00
Sam Atkins
75e0b21940 LibWeb: Store calculated transformation matrix on the StackingContext
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. :^)
2022-07-21 16:36:08 +02:00
Sam Atkins
032646b6c3 LibWeb: Produce a transformation matrix for TransformFunction::Rotate
Currently we can't actually paint the result, but at least the maths is
correct. :^)
2022-07-21 16:36:08 +02:00
Sam Atkins
b5ab961e20 LibWeb: Add proper support for Angle parameters in transform functions
Also, made the `reference_length` parameter optional for the lambda that
extracts transform-function parameters, since it is only needed to
resolve `LengthPercentage` parameters.
2022-07-21 16:36:08 +02:00
Andreas Kling
a6e1b9eed2 LibWeb: Snap transformed stacking contexts to pixel grid
Make sure that we're painting them at an integer pixel position, to
avoid smearing.
2022-07-21 01:46:25 +02:00
MacDue
0b0a691ecd LibWeb: Fix overflow: hidden not applying to positioned descendants
This now calls before/after_child_paint() on the parent paintable
of a positioned child. This allows the parent's overflow clipping
to apply to the child.
2022-07-19 15:00:59 +02:00
MacDue
f079214b18 LibWeb: Apply overflow: hidden to all (relevant) child paint phases
Previously, before/after_children_paint() was only called for the
"Foreground" paint phase, this meant the backgrounds and other
features of child nodes of a element with overflow: hidden were
not clipped.
2022-07-19 15:00:59 +02:00
sin-ack
3f3f45580a Everywhere: Add sv suffix to strings relying on StringView(char const*)
Each of these strings would previously rely on StringView's char const*
constructor overload, which would call __builtin_strlen on the string.
Since we now have operator ""sv, we can replace these with much simpler
versions. This opens the door to being able to remove
StringView(char const*).

No functional changes.
2022-07-12 23:11:35 +02:00
Igor Pissolati
44057c9482 LibWeb: Make hit testing respect hidden overflow 2022-07-04 11:09:27 +02:00
Andreas Kling
5b72a9cb11 LibWeb: Use paint tree traversal helpers in StackingContext 2022-04-08 20:58:42 +02:00
Simon Wanner
a2d89f11d1 LibWeb: Use the correct painter for painting stacking contexts
When cloning the PaintContext we should be using the painter backed by
the bitmap created for this stacking context layer.

Fixes: 54c3053bc3 ("LibWeb: Preserve paint state when painting...")
2022-04-08 20:44:23 +02:00
Andreas Kling
3c4bdd7cfa LibWeb: Ignore non-painting layout nodes when hit testing
We currently have to check this because the paint tree hangs from the
layout tree and has no independent means of traversal.
2022-04-07 17:06:02 +02:00
Andreas Kling
54c3053bc3 LibWeb: Preserve paint state when painting stacking contexts indirectly
For layers that require indirect painting (due to opacity, transform,
etc.) we create a nested PaintContext. Until now, that PaintContext
was created fresh without transferring all the state from the parent
PaintContext.
2022-03-26 17:31:01 +01:00
Jelle Raaijmakers
ab19b092ed LibGfx: Implement Rect::to_rounded<U>()
This replaces the usage of `rounded_int_rect`, whose name did not
accurately reflect the rounding operation happening. For example, the
position of the rect was not rounded but floored, and the size was
pulled through `roundf` before casting to `int` which could result in
inadvertent flooring if the resulting floating point could not exactly
represent the rounded value.
2022-03-23 11:53:34 +01:00
Simon Wanner
dc94879b83 LibWeb: Support transform: translate(...) by percentage 2022-03-22 02:06:21 +01:00
Simon Wanner
145efbe07a LibWeb: Apply the CSS transform-origin property
We don't have transform-box yet, so this applies to the border-box
for now.

This also makes us pass a couple Web Platform Tests as well :^)
For example:
https://wpt.live/css/css-transforms/css3-transform-scale-002.html
2022-03-22 02:06:21 +01:00
Andreas Kling
196a3eb239 LibWeb: Ignore invisible boxes and stacking contexts during hit testing 2022-03-21 15:43:37 +01:00
Andreas Kling
996f3228a2 LibWeb: Fix O(n^2) traversal in hit testing
We already walk the entire paint tree within each stacking context in
the main hit testing function (StackingContext::hit_test()), so there's
no need for each individual paintable to walk its own children again.

By not doing that, we remove a source of O(n^2) traversal which made hit
testing on deeply nested web pages unbearably slow.
2022-03-21 13:03:33 +01:00
Andreas Kling
0ba785894c LibWeb: Make hit testing functions return Optional<HitTestResult>
Using "HitTestResult with null paintable" as a way to signal misses was
unnecessarily confusing. Let's use Optional instead. :^)
2022-03-21 13:03:33 +01:00
Andreas Kling
96db8d64f6 LibWeb: Include entire border box when painting stacking context layer
For stacking contexts that have opacity between 0 and 1, and also
contexts with a 2D transform, we first paint them into a temporary layer
buffer. Then we blend that buffer with the contents in one go.

Before this patch, we were only drawing the content box of the stacking
context into this layer buffer, which led to padding and borders missing
from elements painted this way.
2022-03-20 13:36:45 +01:00
Simon Wanner
48efdaa8c4 LibWeb: Update hit_test for CSS Transforms
This now also takes a FloatPoint instead of an IntPoint to avoid
excessive rounding when multiple transforms apply on top of each other.
2022-03-18 18:51:42 +01:00
Simon Wanner
a2331e8dd3 LibWeb: Implement CSS transforms on stacking contexts
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 :^)
2022-03-18 18:51:42 +01:00
Andreas Kling
ccc37032a4 LibWeb: Don't call establishes_stacking_context() during painting
By the time we're painting, we've already built the stacking context
tree. So instead of asking if a box establishes a stacking context, we
can ask if its paintable *has* a stacking context.

This was taking up ~6% of the profile when mousing around on the HTML
specification. With this change, it disappears completely. :^)
2022-03-16 19:16:45 +01:00
Andreas Kling
f5c2e87965 LibWeb: Sort stacking context tree once, after fully building it
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! :^)
2022-03-13 18:09:43 +01:00
Andreas Kling
5779a910e5 LibWeb: Move hit testing to the painting tree 2022-03-11 00:21:49 +01:00
Andreas Kling
ba606d9057 LibWeb: Move PaintingBox to its own .cpp and .h files 2022-03-11 00:21:49 +01:00
Andreas Kling
f017c1c064 LibWeb: Make hit testing return a { paintable, offset }
Everything related to hit testing is better off using the painting tree.
The thing being mousemoved over is a paintable, so let's hand that out
directly instead of the corresponding layout node.
2022-03-11 00:21:49 +01:00
Andreas Kling
aae356baf1 LibWeb: Port inline elements to the new Paintable system
This patch adds InlinePaintable which corresponds to Layout::InlineNode.
2022-03-11 00:21:49 +01:00