Commit graph

19 commits

Author SHA1 Message Date
Andreas Kling
1987318cc2 LibWeb: Move selection state from layout tree to paint tree
Where we paint the selection is obviously paint-related information,
so let's keep it in the paint tree.
2024-03-18 13:42:16 +01:00
Andreas Kling
1e14264d13 LibWeb: Avoid repeated layout lookups in resolve_paint_only_properties()
By caching the layout node and its computed values in locals, we can
avoid the small amount of redundant work needed to look them up every
single time.
2024-03-02 13:00:09 +01:00
Andreas Kling
8303e61912 LibWeb: Pass BorderRadiusData const& to normalize_border_radii_data()
This avoids making a bunch of temporary copies for no reason.
2024-03-02 13:00:09 +01:00
Andreas Kling
d1b5f55f91 LibWeb: Make Paintable::containing_block() return a PaintableBox*
Every single client of this function was immediately calling paintable()
on the result anyway, so there was no need to return a layout node!

This automatically leverages the cached containing block pointer we
already have in Paintable, which melts away a bunch of unnecessary
traversal in hit testing and painting. :^)
2024-03-01 17:57:10 +01:00
Aliaksandr Kalenik
2764966ccc LibWeb: Reduce paintable tree traversals during hit-testing
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/
2024-03-01 13:03:53 +01:00
Aliaksandr Kalenik
c74fc4c171 LibWeb: Clean previous border radii clips in refresh_clip_state()
The list of border radii clips needs to be reset before being populated
with new clips that have refreshed positions. Besides fixing painting,
this also improves performance because the number of sample/blit
commands does not increase as we scroll.
2024-02-28 07:44:12 -05:00
Aliaksandr Kalenik
95d91a37d2 LibWeb: Resolve outline CSS property before paint commands recording
Refactor to resolve paint-only properties before painting, aiming to
stop using layout nodes during recording of painting commands.

Also adds a test, as we have not had any for outlines yet.
2024-02-12 13:38:24 +01:00
Aliaksandr Kalenik
d4932196cc LibWeb: Account for all clipped border radii in containing block chain
With this change, instead of applying only the border-radius clipping
from the closest containing block with hidden overflow, we now collect
all boxes within the containing block chain and apply the clipping from
all of them.
2024-02-11 08:12:31 +01:00
Aliaksandr Kalenik
76d1536307 LibWeb: Optimize scroll offset and clip state recalculation
In this commit we have optimized the handling of scroll offsets and
clip rectangles to improve performance. Previously, the process
involved multiple full traversals of the paintable tree before each
repaint, which was highly inefficient, especially on pages with a
large number of paintables. The steps were:

1. Traverse the paintable tree to identify all boxes with scrollable or
   clipped overflow.
2. Gather the accumulated scroll offset or clip rectangle for each box.
3. Perform another traversal to apply the corresponding scroll offset
   and clip rectangle to each paintable.

To address this, we've adopted a new strategy that separates the
assignment of the scroll/clip frame from the refresh of accumulated
scroll offsets and clip rectangles, thus reducing the workload:

1. Post-relayout: Identify all boxes with overflow and link each
   paintable to the state of its containing scroll/clip frame.
2. Pre-repaint: Update the clip rectangle and scroll offset only in the
   previously identified boxes.

This adjustment ensures that the costly tree traversals are only
necessary after a relayout, substantially decreasing the amount of work
required before each repaint.
2024-02-09 16:45:44 +01:00
Aliaksandr Kalenik
1af466babf LibWeb: Fix invalidation of CSS properties that do not affect layout
Recently, we moved the resolution of CSS properties that do not affect
layout to occur within LayoutState::commit(). This decision was a
mistake as it breaks invalidation. With this change, we now re-resolve
all properties that do not affect layout before each repaint.
2024-02-03 09:28:03 +01:00
Aliaksandr Kalenik
d27b376699 LibWeb: Store clip border radii in CSSPixels instead of DevicePixels
Paintable boxes should not hold information stored in device pixels.
It should be converted from CSS pixels only by the time painting
command recording occurs.
2024-01-30 11:22:22 +01:00
Aliaksandr Kalenik
556679fedd LibWeb: Account for scroll offset in hit-testing
The hit-testing position is now shifted by the scroll offsets before
performing any checks for containment. This is implemented by assigning
each PaintableBox/InlinePaintable an offset corresponding to the scroll
frame in which it is contained. The non-scroll-adjusted position is
still passed down when recursing to children because the assigned
offset accumulated for nested scroll frames.

With this change, hit testing works in the Inspector.
Fixes https://github.com/SerenityOS/serenity/issues/22068
2024-01-29 09:57:40 +01:00
Aliaksandr Kalenik
0bf82f748f LibWeb: Move clip rect calculation to happen before painting
With this change, clip rectangles for boxes with hidden overflow or the
clip property are no longer calculated during the recording of painting
commands. Instead, it has moved to the "pre-paint" phase, along with
the assignment of scrolling offsets, and works in the following way:

1. The paintable tree is traversed to collect all paintable boxes that
   have hidden overflow or use the CSS clip property. For each of these
   boxes, the "final" clip rectangle is calculated by intersecting clip
   rectangles in the containing block chain for a box.
2. The paintable tree is traversed another time, and a clip rectangle
   is assigned for each paintable box contained by a node with hidden
   overflow or the clip property.

This way, clipping becomes much easier during the painting commands
recording phase, as it only concerns the use of already assigned clip
rectangles. The same approach is applied to handle scrolling offsets.

Also, clip rectangle calculation is now implemented more correctly, as
we no longer stop at the stacking context boundary while intersecting
clip rectangles in the containing block chain.

Fixes:
https://github.com/SerenityOS/serenity/issues/22932
https://github.com/SerenityOS/serenity/issues/22883
https://github.com/SerenityOS/serenity/issues/22679
https://github.com/SerenityOS/serenity/issues/22534
2024-01-28 08:25:28 +01:00
Aliaksandr Kalenik
3cf5ad002a LibWeb: Allow inline nodes to establish a stacking context
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.
2024-01-05 19:36:55 +01:00
Aliaksandr Kalenik
ac6b3c989d LibWeb: Apply scroll boxes offsets after painting commands recording
With this change, instead of applying scroll offsets during the
recording of the painting command list, we do the following:
1. Collect all boxes with scrollable overflow into a PaintContext,
   each with an id and the total amount of scrolling offset accumulated
   from ancestor scrollable boxes.
2. During the recording phase assign a corresponding scroll_frame_id to
   each command that paints content within a scrollable box.
3. Before executing the recorded commands, translate each command that
   has a scroll_frame_id by the accumulated scroll offset.

This approach has following advantages:
- Implementing nested scrollables becomes much simpler, as the
  recording phase only requires the correct assignment of the nearest
  scrollable's scroll_frame_id, while the accumulated offset from
  ancestors is applied subsequently.
- The recording of painting commands is not tied to a specific offset
  within scrollable boxes, which means in the future, it will be
  possible to update the scrolling offset and repaint without the need
  to re-record painting commands.
2023-12-30 11:10:24 +01:00
Aliaksandr Kalenik
1b3223dd9e LibWeb: Rename painter() to recording_painter() in PaintContext
Using recording_painter() as a name is less misleading, indicating
the painter in stacking context traversal doesn't perform actual
painting commands.
2023-11-27 21:53:38 +01:00
Andreas Kling
d296992fb3 LibWeb: Make StackingContext point to paint tree instead of layout tree
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.
2023-08-20 05:02:59 +02:00
Andreas Kling
8bb275f2ea LibWeb: Move painting logic from Layout::Viewport to ViewportPaintable 2023-08-20 05:02:59 +02:00
Andreas Kling
c01c4b41e2 LibWeb: Add ViewportPaintable to represent viewports in the paint tree
This patch just adds the new root paintable and updates the tests
expectations. The next patch will move painting logic from the layout
viewport to the paint viewport.
2023-08-20 05:02:59 +02:00