`TableSlotCell` 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 `TableSlotCell::repair_style()`
wasn't calling `BlockFormattingContext::repair_style()`. Now we can just
rely on the correct `IndependentFormattingContext::repair_style()`.
Testing: Adding a new test
Fixes: #42777
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
These two types of boxes should also be able to isolate damage during
propagation and serve as roots for box tree reconstruction, as their
contents are independent of their containing box.
Testing: This should not change testable behavior so 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: Luke Warlow <lwarlow@igalia.com>
Replace the old dirty root box tree layout approach with one that works
based on independent formatting contexts. Instead of just allowing a
single dirty root to be the source of box tree reconstruction, allow box
tree reconstruction to happen anywhere in the tree that can isolate box
tree damage from ancestors. This essentially combines damage propagation
and box tree construction into a single step.
There is currently one downside to this approach compared to the dirty
root approach which is that we currently cannot detect and start box
tree layout when the dirty has a compatible `display` and `position`
value. This can mean the scope of box tree layout extends further up the
tree. We will address this in a followup -- but have not noticed any
major performance implications (currently fragment tree layout is much
more expensive than box tree layout).
Benefits:
1. Damage propagation now only happens under the dirty root.
2. Future changes can limit the scope of damage up the tree and perhaps
preserve the inline content size cache between box tree rebuilds.
Testing: This should not change behavior in a testable way (we currently
do
not have robust performance tests), so WPT test results should not
change.
---------
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
Co-authored-by: Luke Warlow <lwarlow@igalia.com>
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>
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>
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>
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>
Use `ServoThreadSafeLayoutNode` in more places in layout rather than
`ServoLayoutNode`. The former is meant to be used during layout, but
layout 2020 was written against the latter. In general, this reduces the
amount of conversion to the thread-safe version in many places in
layout.
In addition, an unused iterator from the `script` crate
`ServoThreadSafeLayoutNodeChildrenIterator` is replaced with the child
iterator from `layout`. The `layout` version must be directly in
`script` now as it uses the dangerous variants of `next_sibling` and
`first_child`, which allow encapsulating the unsafe bits into one
module.
This will ultimately be useful for storing the layout data of
pseudo-element children of pseudo-elements properly.
Testing: This should not change any behavior and thus is covered by
existing tests.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This was done in #24871, but after some refactorings it became public.
This makes it private again. As said in
b2b3ea992c:
> Privacy forces the rest of the code to go through methods
> rather than matching on the enum,
> reducing accidental layout-mode-specific behavior.
It also avoids the risk of accidentally calling `layout()` on the inner
layout-mode-specific struct, bypassing caching.
Testing: Not needed (no behavior change)
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
With the work to unify the layout logic for replaced and non-replaced
boxes (#37942), I think the `IndependentNonReplacedContents` enum does
no longer make much sense.
Therefore, this removes `IndependentNonReplacedContents`, merging its
values into `IndependentFormattingContextContents`.
The methods defined on `IndependentFormattingContextContents` can now be
on `IndependentFormattingContext`, in particular this implies that the
layout results of a replaced box will now be cached.
Testing: Unneeded (no behavior change)
This part of #37942
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
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>
This change extends incremental box tree updates to table columns.
Testing: This should not change observable behavior and is thus covered
by existing WPT tests.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This change extends incremental box tree updates to table cells. In
addition, for simplicity this refactors `BoxSlot::take_layout_box()`
into `BoxSlot::take_layout_box_if_undamaged()`.
Testing: This should not change observable behavior and is thus covered
by existing WPT tests.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
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>
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>
Now that we are standardizing on the `_traits` crates becoming `_api`
and exposing the API of the crate that they get their name from [^1],
`script_layout_interface` becomes `layout_api` as it exposes the API for
`layout` that is used by `script` This brings the crate in line with the
naming of the other ones in `shared`.
[^1]:
https://servo.zulipchat.com/#narrow/channel/263398-general/topic/Organizing.20*_traits.20crates/with/396893711
Testing: This should not change any behavior and thus is covered by
existing tests.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
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>
`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>
Table cells share background styles with their track and track group
boxes. When a track and track group style is repaired, this new data
structure will allow reparing the style of the cell `Fragment`s without
having to lay the table out again or walk through `Fragment`s and
individually repair their background styles.
Testing: This doesn't change behavior and is thus tested by existing
WPT tests.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
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>
Previously, spans were partially clamped during layout, but this means
that accessing and setting these properties via script wouldn't behave
according to the HTML specification. In addition, the value wasn't
floored in layout, so could lead to panics. This change improves
clamping and moves it to script.
Testing: This change includes a new WPT test.
Fixes#36699.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
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>