Laying out a float or atomic inline will now use the same logic
regardless of whether it's replaced or not.
This reduces the amount of code, and should have no observable effect.
Testing: Unneeded (no behavior change)
This part of #37942
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
When a style change does not chang the structure of the box tree, it is
possible to skip box tree rebuilding for an element. This change adds
support for reusing old box trees when no element has that type of
damage. In order to make this happen, there needs to be a type of
"empty" `LayoutDamage` that just indicates that a fragment tree layout
is necessary.
This is the first step toward incremental fragment tree layout.
Testing: This should not change observable behavior and thus is covered
by
existing WPT tests. Performance numbers to follow.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
`BoxFragment` had 2 fields that are only relevant for block-level boxes:
`clearance` and a boxed `block_margins_collapsed_with_children`.
This moves both pieces of data into a new `BlockLevelLayoutInfo` struct,
which is boxed.
As a result, the size of `BoxFragment` is reduced from 272 to 264 bytes.
Testing: Unneeded (no behavior change)
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Clearance only applies to block-level boxes, so it was unnecessary to
require it as a parameter. Instead, in block layout we can set it using
the new `.with_clearance()` method.
Testing: Unnecessary (no behavior change)
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
It was very easy to forget about using `.with_specific_layout_info()` to
set the specific layout info, so it's better to make it a parameter.
In fact this already happened in the past: #36993 fixed the missing
specific layout info for flex items.
This patch fixes it for floats and atomic inlines. It also propagates it
in other cases where not doing so was not a big deal because the
specific layout info was None, but that was a fragile assumption.
Testing: Various WPT improvements
Fixes: #37898
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
The logic for laying out block-level replaced elements wasn't taking
floats into account when resolving a `stretch` inline size. By handling
them with the same logic as non-replaced elements, we fix that problem,
and reduce the amount of code.
Testing: Adding new tests
Fixes: #37861
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
#37433 didn't handle intrinsic contributions. This patch computes the
correct SizeConstraint to be used as the ConstraintSpace's block size
when computing intrinsic inline sizes.
Testing: Adding new test
Fixes: #37478
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
`PlacementAmongFloats` should guarantee that the inline size of the
placement rect is at least as big as the inline size of the box,
resulting in a non-negative free space.
However, that may fail when dealing with huge sizes that need to be
saturated to MAX_AU, so this floors the free space by zero.
Testing: New crashtest
Fixes: #37312
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
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>
When making last-minute changes to the repaint-only layout pass, damage
propagation was broken, meaning that full layout was always done. This
change fixes that, meaning that times in the `blaster.html` test case
now reflect those described in the original commit message from #36978.
In addition, some style repair is now fixed:
- `InlineFormattingContext`s now keep a `SharedInlineStyles` for the
root of the IFC
which is updated during style repair.
- `BlockFormattingContext`s now properly update their style.
These changes are verified by turning on repaint only layout for more
properties
in Stylo via servo/stylo#183.
Testing: Manual performance testing via `blaster.html`.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Before this patch it wasn't possibly to simultaneously support intrinsic
min/max sizes and content alignment in the block axis. For example,
block containers only support the former, and flex containers only the
latter.
The reason is that the final block size was decided by the parent
formatting context *after* performing layout, while content alignment is
performed *during* layout.
To address the problem, this introduces the struct `LazySize`, which
contains the data to resolve the final size, except for the intrinsic
size. Thus the parent formatting context can first create a `LazySize`,
then pass it to the child layout so that (if necessary) it can compute
the final size once the intrinsic one is known, and after layout the
parent formatting context uses it to actually size the child.
This PR just provides the functionality that will be used by follow-ups,
but at this point no layout is using the `LazySize` provided by the
parent, so there shouldn't be any behavior change yet.
Testing: Unnecessary (no behavior change)
This is part of #36981 and #36982
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This change adds the simplest kind of incremental layout. When Servo
detects that all style changes only require a repaint, only run stacking
context tree and WebRender display list generation. This means that
these kind of restyles do not need a re-layout. Instead, the existing
box and fragment trees will be used and the styles of damaged nodes will
be updated in their box and fragment tree nodes.
This requires a new style repair DOM traversal for nodes that have had
their style damaged. In addition, careful accounting of all the places
where we store style must happen in order ot update those styles.
Testing: This is covered by existing WPT tests as it should not change
observable behavior.
We have created a test case which shows a 50% speedup when run
in Servo, even though there still a long way to go to match the speed
of other browsers:
https://gist.github.com/mrobinson/44ec87d028c0198917a7715a06dd98a0
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
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>
Instead of resolving the canvas background properties (essentially
keeping a possible reference to the `<body>`'s style) during fragment
tree construction, wait until painting to possibly find the style on an
appropriate `<body>` fragment. This is possible now because `Fragment`
keeps a list of flags with relevant information about the root and
`<body>` elements.
A benefit of this approach is that styles aren't cached in the fragment
tree, which would be problematic for incremental layout. In addition,
the old code was making an effort to transform the `<body>`'s background
by the root element's transform. Only Safari does this and there was
a resolution the WG that this should not happen in
https://github.com/w3c/csswg-drafts/issues/6683.
Testing:
- `/css/css-transforms/transform-translate-background-001.html`
- `/css/css-transforms/transform-translate-background-002.html`
- `/css/CSS2/floats/float-root.html`
Fixes: #30475.
Closes: #30569.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
`PositioningContext` held two vectors, one inside an `Option`, to
differentiate between the version used for a containing block for all
descendants (including `position: absolute` and `position: fixed`) or
only for `position: absolute` descendants. This distinction was really
hard to reason about and required a lot of bookkeeping about what kind
of `PositioningContext` a layout box's parent expected. In addition, it
led to a lot of mistakes.
This change simplifies things so that `PositioningContext` only holds a
single vector. When it comes time to lay out hoisted absolutely
positioned
fragments, the code then:
- lays out all of them (in the case of a `PositioningContext` for all
descendants), or
- only lays out the `position: absolute` descendants and preserves the
`position: fixed` descendants (in the case the `PositioningContext`
is only for `position: absolute`.), or
- lays out none of them if the `PositioningContext` was created for
box that did not establish a containing block for absolutes.
It's possible that this way of dealing with hoisted absolutes is a bit
less efficient, but, the number of these descendants is typically quite
small, so it should not be significant. In addition, this decreases the
size in memory of all `PositioningContexts` which are created in more
situations as time goes on.
Testing: There is a new WPT test with this change.
Fixes: #36696.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
As per
[w3.org/TR/filter-effects-1#FilterProperty](https://www.w3.org/TR/filter-effects-1/#FilterProperty),
`filter` shouldn't make the root element establish a containing block
for absolute and fixed positioned descendants. `will-change: filter` has
matching behavior.
This PR adds a check for if we are the root element before establishing
such a block.
To know if we are the root element, we look at the `FragmentFlags`
passed in. Previously for our function, these were dummy flags, always
constructed as empty. Thus, this PR also makes sure the correct
FragmentFlags are passed down the chain to the function
`establishes_containing_block_for_all_descendants`.
Testing:
- `/css/filter-effects/filtered-html-is-not-container.html` now passes
- `/css/css-will-change/will-change-fixedpos-cb-003.html` now passes
- Manual tests are working
Fixes: #35391
---------
Signed-off-by: haval0 <56519858+haval0@users.noreply.github.com>
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
https://drafts.csswg.org/css-align/#justify-block
Testing: Improves various WPT tests. `justify-self-auto-margins-2.html`
fails but I think the test is wrong.
Signed-off-by: Oriol Brufau <obrufau@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>
2025-04-19 10:17:03 +00:00
Renamed from components/layout_2020/flow/mod.rs (Browse further)