Commit Graph

32 Commits

Author SHA1 Message Date
Oriol Brufau
80318ad25e layout: Let OutsideMarker store an IndependentFormattingContext (#42864)
`OutsideMarker` was storing the `BlockFormattingContext` and the
`LayoutBoxBase` in separate fields. Now it will store an entire
`IndependentFormattingContext` in a single field.

In particular, this fixes the issue that `OutsideMarker::repair_style()`
wasn't calling `BlockFormattingContext::repair_style()`. Now we can just
rely on `IndependentFormattingContext::repair_style()`, which correctly
repairs the style of both the `BlockFormattingContext` and the
`LayoutBoxBase`.

Also, the `BlockLevelBox::repair_style()` was repairing the style of the
`LayoutBoxBase` twice, for all kinds of block-level boxes. This removes
the duplication.

Testing: Adding a new test
Fixes: #42779

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
2026-02-26 09:55:15 +00:00
Oriol Brufau
60c5977291 layout: Correctly repair OutsideMarker::list_item_style (#42825)
`OutsideMarker::repair_style()` was setting `list_item_style` to the
style of the marker, not the style of the list item.

This patch sets it to `node.parent_style(context)` instead, and it fixes
`ServoThreadSafeLayoutNode::parent_style()` to take the pseudo-element
chain into account. This requires modifying a bunch of logic to pass the
`SharedStyleContext` around.

Testing: Adding a new test

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
2026-02-25 13:25:45 +00:00
Oriol Brufau
a2041d6263 layout: Reuse boxes for independent formatting contexts with self damage if compatible (#42783)
Previously, when a formatting context root had rebuild damage from its
own (not from ancestors), we weren't reusing it. Now we check if the
level of the box (i.e. whether it's inline-level, block-level, a table
cell, a table caption, or absolutely positioned) that will be generated
by the new style is compatible with the old box. And if so, we reuse it.

Testing: Not needed, there should be no behavior change

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Co-authored-by: Luke Warlow <lwarlow@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
2026-02-24 17:19:24 +00:00
Martin Robinson
0c182904f5 layout: Clear dirty box tree nodes during damage traversal (#42596)
Instead of keeping dirty box tree nodes around after the damage
traversal, clear them readily (like `display: none` nodes). This
simplifies the logic during box tree reconstruction and also prepares
the damage traversal for future work.

In addition, restructure the logic of the damage traversal to make it a
bit easier to follow.

Testing: This shouldn't change observable behavior so should be covered
by existing
tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
Co-authored-by: Luke Warlow <lwarlow@igalia.com>
2026-02-13 13:43:13 +00:00
Martin Robinson
e80ec57069 layout: Remove outer Option on BoxSlot (#41858)
This was used before for dummy `BoxSlot`s, but we don't have those any
longer, so this can just be removed now.

Testing: This should not change observable behavior so is covered by
existing tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2026-01-12 16:24:15 +00:00
Oriol Brufau
accda387b4 layout: Stop splitting inline boxes when they contain block-levels (#41492)
We now follow the same approach as Blink: sequences of block-levels in
an inline formatting context get wrapped in an anonymous block, which is
treated as a line item. Inline ancestors are no longer split.

This means that inline elements will now generate a single inline box,
and the box tree makes more sense in general. This will help for
incremental layout.

This also means that block-level elements will now be properly affected
by effects like opacity of filters set on inline ancestors.

Recently, WebKit has done some similar work, but without the anonymous
blocks. We might also consider removing them in the future.

Google's explainer:
https://docs.google.com/document/d/15kgdIHhb9EVNup6Ir5NWwJxpzY5GH0ED7Ld3iMW3HlA/

Testing: Several tests are now passing
Fixes: #39813

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
2026-01-01 17:41:37 +00:00
Oriol Brufau
8b5333b38e layout: Cleanup for replaced elements with widgets (#40769)
This cleans up the changes done in #40578.

In particular, it removes the unnecessary `Contents::ReplacedWithWidget`
since we can handle that with `Contents::Replaced`. It also removes
`IndependentFormattingContextContents::ReplacedWithWidget` in favor of
`IndependentFormattingContextContents::Replaced`, by adding an optional
parameter for the widget.

That ensures that the behavior of replaced elements won't accidentally
diverge dependign on whether they have a widget. For example, #40578
forgot to handle `ReplacedWithWidget` in
`tentative_block_content_size()`.

Additionally, this removes the hardcoded especial behavior for `<video>`
that was added in `ServoThreadSafeLayoutElement::with_pseudo()`.

Testing: Adding a reftest
Fixes: #40708
Fixes: #40770

---------

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
2025-11-20 20:52:39 +00:00
TIN TUN AUNG
6fda77da05 Media: Display User Agent Controls widget for video element. (#40578)
Add Contents::ReplacedWithWidget for video elements with UA control
widget, to allow Traverse into the children of video element during Box
Tree Construction, Generate
IndependentFormattingContextContent::ReplacedWithWidgets, to store both
the `ReplacedContents` and `BlockFormattingContext`. During fragment
tree generation process, first layout the Image Fragment, and then
Layout the Inner Controls BlockFormattingContext. Doing this allow us to
determine the size of Inner Controls widget based on the size of the
Image Fragment. Minor Fix: ::before/::after pseudo elment should be
suppress for replaced element.

Testing: Should show the controls widget for `<video controls></video>`,
and should not affect any existing WPT test. Since how to display UA
widget of Video Element is not defined in the spec, expectedly there has
no existing WPT test that testing this.
Fixes https://github.com/servo/servo/issues/40452
Fixes https://github.com/servo/servo/issues/31414

---------

Signed-off-by: rayguo17 <tin.tun.aung1@huawei.com>
2025-11-18 07:02:13 +00:00
Mukilan Thiyagarajan
07cf9a9175 compositor: Rename RenderingGroupId to PainterId (#40307)
And let the Compositor create the `PainterId` when it creates a new
`Painter`. Also make inline formatting code take `LayoutContext` rather
than threading it via the `InlineFormattingContextBuilder`.


Testing: Should preserve existing behavior, so covered by existing
tests.

Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
2025-10-31 11:49:24 +00:00
Oriol Brufau
a594bea159 layout: Simplify InlineFormattingContextBuilder::start_inline_box() (#40037)
This patch removes the `block_in_inline_splits` parameter, since the
single caller was just passing None. Then this parameter will only be
provided for `start_inline_box_internal()`, which is made private since
its an internal method as the name indicates.

Testing: Not needed, no behavior change

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
2025-10-21 05:30:36 +00:00
Oriol Brufau
7999d114e5 layout: Add Contents::Widget(NonReplacedContents) for HTML widgets (#39928)
Widgets like `<input>` and `<textarea>` have various behaviors similar
to replaced elements, but aren't fully replaced.

Therefore, this adds a new case into the `Contents` enum so that it can
represent the three states: non-replaced, fully replaced, and widget.
This means that `NonReplacedContents::OfTextControl` can be dropped.

The code is refactored in order to centralize the logic to identify
widgets in a single place.

This fixes some places where we weren't checking if the element was a
widget, e.g. in `construct_for_root_element()`. But I think the change
isn't currently observable in practice.

Testing: Unneeded, no behavior change.
This is part of #39927

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
2025-10-17 11:10:43 +00:00
Narfinger
e64f021550 Allow WebViews and fonts to have a RenderingGroupId. (#39140)
Motivation: The font cache currently has to store a cache of Keys which
need to be given by the webrender instance.
Having a cache for every WebViewId in the future when we have every
webview have the different webrender::DocumentId might be too wasteful
to store this key cache per DocumentId. This proposes to include in the
WebViewId another id, the RenderingGroupId. This id can be easily
changed
to be equivalent to the DocumentId when we support multiple DocumentIds
for a unique Webrender instance.
Additionally this will keep it easier to integrate the currently out of
tree patches for multiple rendering contexts with different webrenders.


Change:
We introduce the RenderingGroupId in the WebViewId and allow a method to
extract it. The font key cache uses this cache
and forwards it to the Compositor when requesting new changes. The
compositor currently ignores this id.
Additionally, the WebView can return the RenderingGroupId. The WebViewId
also has an appropiate constructor for specifying a RenderingGroupId.
Because there currently will be only one RenderingGroupId the
performance will be minimal.


Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>

Testing: This should be covered by WPT tests and normal browsing
behavior works fine.

---------

Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
2025-09-29 10:01:56 +00:00
Oriol Brufau
9264ef1a95 layout: Ensure IFC for abspos with inline-level original display (#39041)
Absolutely positioned elements get blockified, but their static position
still depends on the original display. Therefore, if we encounter an
abspos with an inline-level original display, we will now ensure that
it's handled in an inline formatting context. This way its static
position will correctly take into account things like `text-align`.

Testing: Several WPT tests are now passing.
Fixes: #39017

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
2025-09-02 03:43:55 +00:00
Oriol Brufau
ec1b9b2480 layout: Refactor InlineFormattingContextBuilder::is_empty (#39048)
This method could iterate all the items in the inline formatting context
that was being created. This patch turns it into a field, replacing
`has_uncollapsible_text_content` (so this doesn't increase memory).

Testing: Not needed, no behavior change

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
2025-08-31 00:50:00 +00:00
Martin Robinson
99ce81cf64 layout: Support storing layout data for two-level nested pseudo-elements (#38678)
Add basic support for storing layout data for pseudo-elements nested to
up to two levels. This removes the last unstored layout result and fixes
a double-borrow issue. This change does not add properly parsing nor
styling of these element types, but does prepare for those changes which
must come from stylo.

Testing: This fixes a intermittent panic in
`tests/wpt/tests/css/css-lists/nested-marker-styling.html`
Fixes: #38177. 
Closes: #38183.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2025-08-14 13:41:34 +00:00
Martin Robinson
5ff084a688 layout: Use the PseudoElement from ServoThreadSafeLayoutNode in NodeAndStyleInfo (#38630)
Instead of storing the non-pseudo version of the node in
`NodeAndStyleInfo`, store the pseudo version and use that to query the
`PseudoElement` that a `NodeAndStyleInfo` refers to.

This is a step on the way toward fixing nested pseudo-elements in Servo.

Testing: This should not change behavior and is thus covered by existing
WPT tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-08-13 17:31:57 +00:00
JoeDow
5cd57f9dba layout: Add incremental box tree construction for inline boxes (#38084)
This changes extend the incremental box tree construction for inline
boxes. Since an `InlineItem` can be split into multiple `InlineItem`s by
a block element, the reason such an inline item is marked as damaged may
simply be the removal of the block element or the need to reconstruct
its box tree. Therefore, under the current LayoutDamage design,
theoretically, even damaged inline items might still have some of their
splits reusable. However, based on the principle of simplicity and
effectiveness, this PR only considers reusing undamaged inline boxes.

Testing: This should not change observable behavior and is thus covered
by existing WPT tests.

Signed-off-by: sharpshooter_pt <ibluegalaxy_taoj@163.com>
2025-07-25 11:49:46 +00:00
Martin Robinson
51367c22a6 layout: Store most anonymous pseudo-elements in box slots (#37941)
Previously, anonymous boxes, such for anonymous table parts were not
associated with their non-pseudo ancestor DOM nodes. This presents a
problem when it comes time to clear layout data during incremental
layouts. This change reworks the way that pseudo-elements in general are
stored in their non-pseudo ancestor DOM nodes, allowing for any number
to be placed there.

This trades a bit of performance for space, as just adding a vector to
the node would add something like 24 bytes of storage to every node.
This change should have a neutral runtime memory usage.

Testing: This shouldn't change observable behavior and is thus covered
by
existing WPT tests. It will allow tests to pass in a subsequent PR.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2025-07-08 15:22:09 +00:00
JoeDow
864c877be5 layout: Add incremental box tree construction for inline floats and abspos (#37892)
Layout: Add incremental box tree construction for inline floats and
abspos

Due to false positives in the memory benchmark on CI, the previous PR
[37868](https://github.com/servo/servo/pull/37868) reverted. Now it is
resubmitted.

Signed-off-by: sharpshooter_pt <ibluegalaxy_taoj@163.com>
2025-07-05 08:33:04 +00:00
Jonathan Schwender
c65cd1eadd Revert "layout: Add incremental box tree construction for inline floats and abspos" (#37888)
This reverts commit 19ceccc8eb due to a
significant increase in resident memory usage (See
https://github.com/servo/servo/issues/37887).

Testing: This is a revert due to a regression

Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
2025-07-05 03:45:58 +00:00
JoeDow
19ceccc8eb layout: Add incremental box tree construction for inline floats and abspos (#37868)
This changes extend the incremental box tree construction for inline
out-of-flow-box, including the
`InlineItem::OutOfFlowAbsolutelyPositionedBox` and
`InlineItem::OutOfFlowFloatBox`.

Testing: This should not change observable behavior and is thus covered
by existing WPT tests.

Signed-off-by: sharpshooter_pt <ibluegalaxy_taoj@163.com>
2025-07-04 14:30:00 +00:00
JoeDow
75e5c1bced layout: Add incremental box tree construction for inline atomics (#37866)
This changes extend the incremental box tree construction for inline
atomic

Testing: This should not change observable behavior and is thus covered
by existing WPT tests.

Signed-off-by: sharpshooter_pt <ibluegalaxy_taoj@163.com>
2025-07-04 10:54:54 +00:00
Martin Robinson
82f7f761d9 layout: Add incremental box tree construction for table caption (#37849)
This change extends incremental box tree updates to table captions. In
addition, calls to `LayoutBox::invalidate_cached_fragment()` are moved
to the damage calculation traversal.

Testing: This should not change observable behavior and is thus covered
by existing WPT tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2025-07-03 10:32:05 +00:00
Martin Robinson
6dafeb7a59 layout: Add a first pass at incremental box tree construction (#37751)
This change:

- Adds a new type of LayoutDamage that signifies that a box needs its
  children recollected, because one or more of them need to be rebuilt.
- During restyle damage propagation, propagate this new damage upward in
  the tree. Then box tree construction should be able to preserve any
  still-valid box tree nodes from box slots.
- During BlockLevelBox job finalization, if a box slot is valid and
  there is not LayoutDamage to the element, use the old box slot,
  ensuring that its fragment cache is invalidated.

Testing: This should not change observable behavior and thus is covered
by existing WPT tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
Co-authored-by: coding-joedow <ibluegalaxy_taoj@163.com>
2025-07-03 08:13:20 +00:00
Martin Robinson
7375d09887 layout: Remove TryFrom<Contents> for NonReplacedContents (#37815)
This implementation is quite confusing as it makes it harder to tell
that we are just looking for the case that `Contents` contains
`NonReplacedContents`.

Testing: This shouldn't have any functional change, so is covered by
existing tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-07-01 18:21:33 +00:00
Nico Burns
7427ea4aed Move to_bidi_level method from Stylo to Servo (#37343)
This method is only used in Servo and is the only reason that `stylo`
depends on `unicode-bidi`.

Stylo PR: https://github.com/servo/stylo/pull/196
2025-06-11 14:44:13 +00:00
Oriol Brufau
8540b0f6e3 layout: Force outside ::marker to establish a BFC (#37252)
Even though we were continuing the parent BFC, we weren't updating the
SequentialLayoutState to have the correct containing block info. That
caused problem in the presence of floats.

This patch establishes an independent BFC, which avoids the problem.
This seems reasonable since outside markers are out-of-flow-ish, and it
matches Firefox. Blink implements them as inline-blocks, so they should
also establish a BFC.

Testing: Adding new tests. Some still fail because of a different issue.
Also, adding an expectation for several existing tests that were missing
it.
Fixes: #37222

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
2025-06-06 16:01:27 +00:00
Martin Robinson
9781f1241a layout: Move text decoration propagation to stacking context tree construction (#37069)
Text decorations have a special kind of propagation. Instead of
propating these during box tree construction, move propagation to
stacking context tree construction. This will allow for using a very
easy type of incremental layout when text decorations change. For
instance, when a link changes color during hovering over it, we can skip
all of box and fragment tree construction.

In addition, propagation works a bit better now and color and style
properly move down from their originating `Fragment`s.

This introduces three new failures, because now we are drawing the
text-decoration with the correct color in more places, which exposes an
issue we have with text-decorations not being drawn in relation to the
baseline (taking into account `vertical-align`).

Testing: There are tests for these changes.
Fixes #31736.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2025-05-21 16:38:29 +00:00
Martin Robinson
a0dd2c1beb layout: Share styles to inline box children via SharedInlineStyles (#36896)
`TextRun`s use their parent style to render. Previously, these styles
were cloned and stored directly in the box tree `TextRun` and resulting
`TextFragment`s. This presents a problem for incremental layout.
Wrapping the style in another layer of shared ownership and mutability
will allow updating all `TextFragment`s during repaint-only incremental
layout by simply updating the box tree styles of the original text
parents.

This adds a new set of borrows when accessing text styles, but also
makes it so that during box tree block construction
`InlineFormattingContext`s are created lazily and now
`InlineFormattingContextBuilder::finish` consumes the builder, making
the API make a bit more sense. This should also improve performance of
box tree block construction slightly.

Testing: This should not change observable behavior and thus is covered
by existing WPT tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2025-05-12 09:38:50 +00:00
Martin Robinson
d5e008fd6a layout: Use ServoLayoutNode directly instead of a generic impl (#36876)
This makes it so that layout is no longer generic on the node type,
depending directly on `script`'s `ServoLayoutNode`. In addition to
greatly simplifying layout, this is necessary because incremental layout
needs to be able to create pseudo-element styles without having a handle
on the original `impl LayoutNode`. We feel this is a reasonable
tradeoff.

Testing: No functional changes, so covered by existing WPT tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2025-05-06 14:27:51 +00:00
Martin Robinson
b63a1818c4 layout: Implement node geometry queries against BoxTree's Fragment (#36663)
This is a followup to #36629, continuing to implement script-based
layout queries  using the `Fragment`s attached to the `BoxTree`. In this
change, geometry queris (apart from parent offset) are calculated using
`Fragment`s hanging of the `BoxTree`.

In order to make this work, all `Fragment`s for inlines split by blocks,
need to be accessible in the `BoxTree`. This required some changes to
the way that box tree items were stored in DOM `BoxSlot`s. Now every
inline level item can have more than a single `BoxTree` item. These are
carefully collected by the `InlineFormattingContextBuilder` -- currently
a bit fragile, but with more documentation.

Testing: There are tests for these changes.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2025-04-25 13:38:05 +00:00
Martin Robinson
7787cab521 layout: Combine layout_2020 and layout_thread_2020 into a crate called layout (#36613)
Now that legacy layout has been removed, the name `layout_2020` doesn't
make much sense any longer, also it's 2025 now for better or worse. The
split between the "layout thread" and "layout" also doesn't make as much
sense since layout doesn't run on it's own thread. There's a possibility
that it will in the future, but that should be something that the user
of the crate controls rather than layout iself.

This is part of the larger layout interface cleanup and optimization
that
@Looriool and I are doing.

Testing: Covered by existing tests as this is just code movement.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-04-19 10:17:03 +00:00