This starts to enable the fragment cache for all layout modes, except
grid. The main tricky bit here is that update points are absolutes and
these need to be laid out again in their containing blocks. We punt a
little bit on this, by forcing ancestors of update points to rebuild
their Fragments. This is just the first step.
Testing: We do not currently have layout performance tests, but will try
to run some tests manually later. Behavior is covered by the WPT.
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>
This change adds support for the `::marker` pseudo-element and ensure
that
markers are cached into the box tree. This is only initial support,
there are a few
things missing such as animations, transitions, and support the
`content` CSS
property.
Testing: There are WPT tests for this change.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This PR makes it so the `resolution` factor in `image-set` also affects
the image size.
For instance, in the example below:
```css
background-image: image-set("./small.png" 1x, "./large.png" 2x);
```
if `large.png` is used, an image which is 32x32 will be rendered as
16x16. This is specified
in <https://drafts.csswg.org/css-images-4/#image-set-notation>.
Testing:
- `css/css-images/image-set/image-set-resolution-002.html`
---------
Signed-off-by: tobinio <Tobias.frischmann1@gmail.com>
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Josh Matthews <josh@joshmatthews.net>
These two traits both exposed different parts of the compositing API,
but now that the compositor doesn't depend directly on `script` any
longer and the `script_traits` crate has been split into the
`constellation_traits` crate, this can be finally be cleaned up without
causing circular dependencies. In addition, some unit tests for the
`IOPCompositor`'s scroll node tree are also moved into
`compositing_traits` as well.
Testing: This just combines two crates, so no new tests are necessary.
Fixes: #35984.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
The `Constellation` previously held a `window_size` member, but this
assumes that all `WebView`s have the same size. This change removes that
assumption as well as making sure that all `WebView`s pass their size
and HiDIP scaling to the `Constellation` when they are created.
In addition
- `WindowSizeData` is renamed to `ViewportDetails`, as it was
holding more than just the size and it didn't necessarily correspond to
a "window." It's used for tracking viewport data, whether for an
`<iframe>` or the main `WebView` viewport.
- `ViewportDetails` is stored more consistently so that conceptually an
`<iframe>` can also have its own HiDPI scaling. This isn't something
we necessarily want, but it makes everything conceptually simpler.
The goal with this change is to work toward allowing per-`WebView` HiDPI
scaling and sizing. There are still some corresponding changes in the
compositor to make that happen, but they will in a subsequent change.
Testing: This is covered by existing tests. There should be no behavior
changes.
Fixes: This is part of #36232.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
We were allowing `align-self: stretch` to stretch flex items whose cross
size behaves as `auto`, including cyclic percentages.
However, https://github.com/w3c/csswg-drafts/issues/4525 resolved that
stretching should only happen when the cross size computes to `auto`.
So this patch exposes this information in `ContentBoxSizesAndPBM`, and
refactors the flexbox stretching logic.
Fixes: #36285
Testing:
- `/css/css-flexbox/quirks-auto-block-size-with-percentage-item.html`
- `/css/css-flexbox/stretch-requires-computed-auto-size.html`
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This change ensures that `display: inline-grid` is considered an atomic
inline
- Add `is_atomic_inline_level()` logic to `box_fragment.rs` to improve
accuracy.
- Update `stacking_context.rs` to use the new `is_atomic_inline_level()`
method instead of the one from stylo.
- Update `repeat-auto-fill-005.html` test expectation.
- Remove .ini expectations for tests that are no longer failing.
Testing: covered by WPT
Fixes: #35310
---------
Signed-off-by: Barigbue <barigbuenbira@gmail.com>
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes fix#35390
- [X] There are tests for these changes
[Successful WPT
run](https://github.com/reesmichael1/servo/actions/runs/14097679625)
(which includes the new test files)
(I didn't make the formatting changes intentionally--those came from
`mach format` following `mach test-tidy`.)
---------
Signed-off-by: Michael Rees <mrees@noeontheend.com>
This imports the following changes from Blitz:
- Map position:sticky to relative rather than absolute position
16a7c16544
- Map left and right alignment from Stylo
c71cc681d8
- Improve mapping of align-items/self
7bf2a25e75Fixes: #35998
Testing:
-
`/css/css-grid/alignment/grid-align-justify-margin-border-padding.html`
- `/css/css-grid/alignment/grid-align.html`
-
`/css/css-grid/alignment/grid-column-axis-alignment-sticky-positioned-items-001.html`
- `/css/css-grid/alignment/grid-gutters-and-alignment.html`
-
`/css/css-grid/alignment/grid-item-alignment-with-orthogonal-flows.html`
-
`/css/css-grid/alignment/grid-row-axis-alignment-sticky-positioned-items-001.html`
- `/css/css-grid/alignment/grid-self-alignment.html`
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
According to CSS2, the bottom margin of a block container can collapse
with the bottom margin of its last in-flow child if `height` computes to
`auto`.
However, according to CSS Sizing, that was "legacy spec prose" and
should be interpreted as "behaves as `auto`".
Therefore, cyclic percentages and intrinsic keywords like `min-content`
shouldn't prevent margin collapse, because they behave as `auto`.
This change aligns Servo with Gecko and Blink, but diverges from WebKit.
https://www.w3.org/TR/CSS22/box.html#collapsing-marginshttps://www.w3.org/TR/css-sizing/#behave-auto
Testing:
-
`tests/wpt/tests/css/css-sizing/margin-collapse-with-indefinite-block-size-001.html`
-
`tests/wpt/tests/css/css-sizing/margin-collapse-with-indefinite-block-size-002.html`
-
`tests/wpt/tests/css/css-sizing/margin-collapse-with-indefinite-block-size-003.html`
-
`tests/wpt/tests/css/css-sizing/margin-collapse-with-indefinite-block-size-004.html`
-
`tests/wpt/tests/css/css-sizing/margin-collapse-with-indefinite-block-size-005.html`
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
- Remove the last remaining Servo-specific PseudoElement enum from
layout. This was made to select `::before` and `::after` (both eager
pseudo-elements), but now `traverse_pseudo_element` is called
`traverse_eager_pseudo_element` and should work on any eager pseudo
element.
- Expose a single way of getting psuedo-element variants of
ThreadSafeLayoutElement in the Layout DOM, which returns `None` when
the pseudo-element doesn't apply (not defined for eager
pseudo-elements or when trying to get `<details>` related
pseudo-elements on elements that they don't apply to).
- Ensure that NodeAndStyleInfo always refers to a node. This is done by
making sure that anonymous boxes are all associated with their
originating node.
These changes are prepatory work for implementation of the `::marker`
pseudo-element as well as ensuring that all anonymous boxes can be
cached into the box tree eventually.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Servo has a `PseudoElementType` which more or less duplicate's Stylo's
`PseudoElement` with the addition of a non-pseudo element variant. This
type needs to be converted into `PseudoElement` anyway when asking for
the style of an element from Stylo, so eliminate Servo's version and
simply use `Option<PseudoElement>` with the `None` variant meaning the
non-pseudo.
This is preparation for adding support for the `::marker` pseudo
element.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Sometimes column Flexbox needs to do an early layout pass to determine
the preferred block content size of flex items. Previously the
absolutely positioned children created during this pass were discarded,
but now they are cached to be possibly used during the final layout
phase of the flex item. Since they are not thrown away, it is necessary
that the `PositioningContext` used to collect them is compatible with
their final `PositioningContext`.
Fixes#36121.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
* Create `update_rendering` in `CanvasState` instead of manually updating in layout
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
* Mark as dirty and do flushes
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
* fixup rebase
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
* Update components/script/dom/htmlcanvaselement.rs
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
---------
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This replaces `IndependentLayout` with `CacheableLayoutResult` and
stores it in `LayoutBoxBase` so it can be reused when we need to lay out
a box multiple times.
This is a generalization of the caching that we had for flexbox, which
is now removed in favor of the new one.
With this, the number of runs per second in the Chromium perf test
`flexbox-deeply-nested-column-flow.html` are multiplied by 3.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
Spec: https://drafts.csswg.org/css-sizing-3/#funcdef-width-fit-content
It's similar to the `fit-content` keyword but, instead of clamping the
stretch size between `min-content` and `max-content`, it clamps the
provided argument.
So now that we support `fit-content`, it's quite straightforward to add.
It's just not completely clear what should happen when the argument has
a cyclic percentage, so this may need some further adjustments depending
on the outcome of https://github.com/w3c/csswg-drafts/issues/11805
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This change creates a `constellation_traits` crate. Previously messages
to the `Constellation` were in the `compositing_traits` crate, which
came about organically. This change moves these to a new crate which
also contains data types that are used in both compositing/libservo and
script (ie types that cross the process boundary). The idea is similar
to `embedding_traits`, but this is meant for types not exposed to the
API.
This change allows deduplicating `UntrustedNodeAddress`, which
previously had two versions to avoid circular dependencies.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Simply how `ProgressiveWebMetrics` works:
1. Keep only a single struct instead of one in layout and one script
that both implement the `ProgressiveWebMetrics` trait. Since layout
and script are the same thread these can now just be a single
`ProgressiveWebMetrics` struct stored in script.
2. Have the compositor be responsible for informing the Constellation
(which informs the ScripThread) about paint metrics. This makes
communication flow one way and removes one dependency between the
compositor and script (of two).
3. All units tests are moved into the `metrics` crate itself since there
is only one struct there now.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
The static position rect is calculated assuming that the containing
block would be established by the content box of some ancestor, but the
actual containing block is established by the padding box.
So we need to add the padding of that ancestor.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
We were ignoring sizing keywords on the min and max sizing properties.
With this, flexbox layout has full support for sizing keywords.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Adds support for min-content, max-content, fit-content and stretch on
the min and max main size properties of a flex item.
I'm removing `automatic_min_size()` and `flex_base_size()` because they
would need to share so much code among themselves and their one caller
that it's simpler to just inline the code.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Now that Stylo considers `servo` as the default feature, Servo doesn't
need to specify `features = ["servo"]`.
Also use the same crate names as Stylo, rather than renaming them with
`package`.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
`block_size_is_zero_or_intrinsic()` was always returning true for
`stretch`. This function is used for the margin collapse heuristics
in block layout, so we were considering that an empty element with
`height: stretch` would self-collapse.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
* Add doc comments to boundary point
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
* Allow querying content box of text fragments
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
* Implement Range::getBoundingClientRect
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
* Update WPT expectations
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
---------
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
In #35630 I treated an indefinite `stretch` as 0px on min sizing
properties, and as `none` on max sizing properties. However, this was
only for final layout sizes, I forgot about intrinsic contributions.
Blink already modified the relevant test, I'm just reordering it a bit
since we are no longer treating `stretch` as `fit-content`, so it seems
better to test it at the end.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
These methods were doing virtually the same thing. So this patch moves
the common logic into a new `FlexItemBox::to_flex_item()`, which is then
called by `FlexItem::new()` and `FlexItemBox::main_content_size_info()`.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
`Size::resolve_for_min()` had an `Au` parameter, representing the value
to be used for an automatic minimum size. However, this amount isn't
trivial to compute in flexbox, so this patch changes the parameter to a
function that can be called lazily.
Note flexbox isn't currently using `Size::resolve_for_min()`, but it
will in #35961.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
* Migrate to 2024 edition
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
* Allow unsafe_op_in_unsafe_fn lint
This lint warns by default in the 2024
edition, but is *way* too noisy for servo.
We might enable it in the future, but not now.
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
* Compile using the 2024 edition
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
---------
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
We were already not compiling it and not running tests on it by default.
So it's simpler to just completely remove it.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
In particular:
- `z-index` will now work on unpositioned grid items.
- `will-change: z-index` will only establish a stacking context if
`z-index` applies, i.e. if the box is positioned or a flex/grid item.
- The conditions in `establishes_stacking_context()` are reordered,
so that the most likely ones are checked first.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
When computing the intrinsic block size of a replaced element with a
computed preferred inline size of `auto`, instead of transferring the
final inline size through the aspect ratio, we were only transferring
the min and max constraints.
We did this to match other browsers, but Ian Kilpatrick agreed that this
is a bug and plans to change Blink.
CSSWG issue: https://github.com/w3c/csswg-drafts/issues/11236
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
The CSSWG resolved that `block-size: stretch` on a block-level box
stretches the margin box to fill the parent. However, if the parent
doesn't have padding nor border, and doesn't establish an independent
formatting context, then we assume that the margins will collapse.
Therefore, we treat the margins as zero when resolving the stretch size,
regardless of whether they will actually end up collapsing.
https://github.com/w3c/csswg-drafts/issues/11044#issuecomment-2599101601https://drafts.csswg.org/css-sizing-4/#stretch-fit-sizing
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
One of the callers was only used for an assert, and it was passing an
inline size argument to a parameter expecting a block size, so it wasn't
making much sense anyways.
Just inline the code into the other caller, and for consistency remove
the assert for replaced elements too.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Adds support for min-content, max-content, fit-content and stretch on
the min and max cross size properties of a flex item.
With one exception: when resolving the main sizes, transferred cross
minimums and maximums will still ignore keywords.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
We were ignoring `table-layout: fixed` both for `inline-size: auto` and
`inline-size: max-content`. However, the CSSWG resolved that fixed table
layout should be triggered except when `inline-size` is `auto`.
https://github.com/w3c/csswg-drafts/issues/10937#issuecomment-2669150397
Blink has already adopted this change, and they modified the WPT
`/css/css-tables/fixed-layout-2.html` accordingly. Here I'm doing some
further cosmetic cleanups to the test.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
* support CSS `will-change`
* update wpt-test result
* Enable css-will-change test
* Update css-will-change test results
* Check transformable before will-change; update wpt-results
* Solve merge conflict
* Update Cargo.toml and Cargo.lock
* Mark new failing test-cases
---------
Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com>
* layout: Fix behavior of `transform-style: preserve-3d`
This makes `transform-style: preserve-3d` establish a containing block
for all descendants, as specified here:
<https://drafts.csswg.org/css-transforms-2/#transform-style-property>
Signed-off-by: Daniel Hast <hast.daniel@protonmail.com>
* layout: Check for transformable elements
Adds a new `is_transformable` helper method and use this in several other
methods, including the methods for whether the fragment establishes a
new stacking context or a containing block for all descendants.
Signed-off-by: Daniel Hast <hast.daniel@protonmail.com>
* Use generic green square reference for reftest.
Signed-off-by: Daniel Hast <hast.daniel@protonmail.com>
* layout: Fix stacking context & containing block checks.
Only the computed value of `transform-style` should be used to determine
whether the element establishes a stacking context and/or a containing
block, not the used value.
Signed-off-by: Daniel Hast <hast.daniel@protonmail.com>
* Update clip-no-stacking-context test expectation to pass.
Signed-off-by: Daniel Hast <hast.daniel@protonmail.com>
---------
Signed-off-by: Daniel Hast <hast.daniel@protonmail.com>
This function showed up as a top producer of allocations
(around 10% of all allocations).
Allocating the vector once upfront and using
`collect_into_vec` removes any intermediate allocations.
This approach is also recommended by the rayon documentation:
https://docs.rs/rayon/1.10.0/rayon/iter/trait.ParallelIterator.html#method.collect
Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
This changes `FlexItem::content_cross_size` into `Size<Au>` to preserve
keyword sizes. The calculation of the hypothetical cross size still
ignores them though, that will be addressed in a follow-up.
Also, browsers don't follow the spec and treat a stretch size different
than a stretch alignment: the former stretches to the containing block,
while the latter stretches to the line. This aligns Servo with that
behavior (following the spec would require bigger refactorings), so
`stretches()` is renamed to `stretches_to_line()` for clarity.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
* Use 2024 style edition
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
* Reformat all code
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
---------
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>