The Transformation class wasn't really accomplishing anything. It still
had to store StyleValues, so it was basically the same as
TransformationStyleValue, with extra steps to convert from one to the
other. So... let's just use TransformationStyleValue instead!
Apart from moving code around, the behavior has changed a bit. We now
actually acknowledge unresolvable parameters and return an error when
we try to produce a matrix from them. Previously we just skipped over
them, which was pretty wrong. This gets us an extra pass in the
typed-om test.
We also get some slightly different results with our transform
serialization, because we're not converting to CSSPixels and back.
...when the style is `none` or `hidden`. `outline-width` is not affected
by `outline-style: none` at all.
In our codebase, that means doing the border-width conversion when
assigning to ComputedValues.
Corresponds to:
2a3d1e4d1009f11f2ef9
Storing these within `LengthPercentage`, `LengthBox`, and `Variant`
over-complicated things.
We also now use the correct `SerializationMode` when serializing `xywh`
and `rect`
We can deduplicate some code by using `assemble_coordinated_value_list`,
also moves this to a method in `ComputedProperties` to be in line with
other values
Computing the font for an element in `compute_font` is premature since
we are yet to apply animated properties - instead we should compute the
value on the fly (with a cache to avoid unnecessary work) to ensure we
are respecting the latest values
Since we resolve any relative lengths at compute time there's no need
for the value to be passed around as a `NumberOrCalculated` and we can
just resolve it within `ComputedProperties::font_variation_settings`.
The only place this is used it is used with value_or so there's no need
to return it is an `Optional`.
This is only used for loading fonts (which occurs during style
computation) so there's no need to store it in `ComputedValues`
The style propagation logic in `NodeWithStyle::apply_style()`
was incomplete for anonymous nodes created during layout
(e.g., within `wrap_in_button_layout_tree_if_needed`).
1. **Non-inherited CSS values** were not being propagated to the
anonymous wrappers.
2. Propagation did not recurse into **nested anonymous wrappers**
(descendants).
This fix adds calls to `propagate_non_inherit_values(child)` and
`child.propagate_style_to_anonymous_wrappers()`, ensuring all computed
styles reach the entire anonymous wrapper hierarchy.
CSS Text 3 gives `text-indent` a couple of optional keywords to control
which lines are affected. This commit parses them, but doesn't yet do
anything with them.
There is no need to recreate this each time we need it when we can
instead create it once and then reuse it.
This is stop-gap since we should resolve colors to their computed forms
as part of StyleComputer::compute_properties
Reduces time spent in ColorResolutionContext::for_layout_node from ~1.1%
to ~0.1% when loading
https://en.wikipedia.org/wiki/2023_in_American_television
By doing this in computed properties rather than InlineLevelIterator we
only do it once per element rather than once per text fragment.
Reduces runtime of this process from ~15% to ~0.2% when loading
https://en.wikipedia.org/wiki/2023_in_American_television
We simplify these at style computation time so there is no need to
maintain them as {Number|Length}OrCalculated
Reduces the time spent in `Length::ResolutionContext::for_layout_node`
from 3.3% to 0.4% when loading
https://en.wikipedia.org/wiki/2023_in_American_television
This applies size, inline-size, and style containment in some cases.
There are other WPT tests for that, but we seem to not implement enough
of containment for this to have an effect so I've not imported those.
Gets us 35 WPT subtests.
Whether an absbox is positioned below or to the right of its previous
sibling in an `InlineFormattingContext` is determined by the
display-outside value before blockification, so we store the
pre-blockification `display` value in `ComputedValues` to access it in
`InlineFormattingContext` and position the box accordingly.
We now also more closely follow the spec when computing values for
font-weight and we now:
- Support relative lengths in `calc()`s
- Properly clamp `calc()`s
- Support relative keywords (e.g. lighter, bolder)
- Respect that font-weight can be a non-integer number.
This does expose a few false positives in the font-weight-computed.html
WPT test. This is because we don't recompute non-inherited font-weight
within `recompute_inherited_style` which means that relative keyword
values can fall out of sync with their parent's value. These previously
passed as we treated `bolder` and `lighter` as aliases for `bold` and
`normal` respectively.
Not every user of this requires an `auto` state, but most do.
This has quite a big diff but most of that is mechanical:
LengthPercentageOrAuto has `resolved_or_auto()` instead of `resolved()`,
and `to_px_or_zero()` instead of `to_px()`, to make their output
clearer.
Interpolation can leave `padding-*` values as negative - this should be
handled by interpolation clamping it to the allowed range of values
but we don't yet do that. As a stop gap we can clamp this before setting
it in ComputedValues.
This fixes 3 crashes and gains us 11 passes in the imported WPT tests
We now also store `outline-width` in ComputedValues as a `CSSPixels`
since we know it's an absolute length at `apply_style` time - this saves
us some work in converting to CSSPixels during layout.
Gains us 46 new passes since we now interpolate keywords (thick, thin,
etc) correctly.
Also loses us 4 WPT tests as we longer clamp negative values produced by
interpolation from the point of view of getComputedStyle (although the
'used' value is still clamped).
Gains us 112 new passes since we now interpolate keywords (thick, thin,
etc) correctly.
Also loses us 4 WPT tests as we longer clamp negative values produced by
interpolation from the point of view of getComputedStyle (although the
'used' value is still clamped).
All fragments inside an atomic inline box should stay within that box,
otherwise we'll screw up the paint order and paint them behind things
that they're supposed to be on top of.
This fixes an issue with inline-block content not appearing on sites
like Google Docs and Reddit, among others.
If `will-change` is set to a property value where that property could
create a stacking context, then we create a stacking context regardless
of the current value of that property.
This property provides a hint to the rendering engine about properties
that are likely to change in the near future, allowing for early
optimizations to be applied.
This reverts 0e3487b9ab.
Back when I made that change, I thought we could make our StyleValue
classes match the typed-om definitions directly. However, they have
different requirements. Typed-om types need to be mutable and GCed,
whereas StyleValues are immutable and ideally wouldn't require a JS VM.
While I was already making such a cataclysmic change, I've moved it into
the StyleValues directory, because it *not* being there has bothered me
for a long time. 😅
These will be used for the mask-repeat property as well in an upcoming
commit, hence the more generic names. Also, this more closely matches
the names used in the spec.
Taking a ColorResolutionContext directly instead of creating one from a
layout node allows us to call this from places where we don't have a
layout node.
Using a generic context argument will allow us to resolve colors in
places where we have all the required information but not in the form of
a layout node as was expected previously.
`CSSColorValue`s which have unresolved `calc` components should be able
to be resolved. Previously we would always resolve them but with
incorrect values.
This is useful as we will now be able to now whether we should serialize
colors in their normalized form or not.
Slight regression in that we now serialize (RGB, HSL and HWB) colors
with components that rely on compute-time information as an empty
string, but that will be fixed in the next commit.
The existing resolve methods are not to spec and we are working to
replace them with new ones based on the `simplify_a_calculation_tree`
method.
These are marked as deprecated rather than replaced outright as work
will need to be done on the caller side to be made compatible with the
new methods, for instance the new methods can fail to resolve (e.g.
if we are missing required context), where the existing methods will
always resolve (albeit sometimes with an incorrect value).
No functionality changes.
This fixes an issue where we'd make an absolute mess from nested SVG
roots with display:block. Before this fix, the inner SVG root would
trigger the inline continuation logic and try to split the tree.
83b6bc4 went too far by forbidding SVGSVGElement from establishing a
stacking context. This element type does follow the behavior of CSS
boxes, unlike inner SVG elements like `<rect>`, `<circle>`, etc., which
are not supposed to be aware of concepts like stacking contexts,
overflow clipping, scroll offsets, etc.
This change allows us to delete overrides of `before_paint()` and
`after_paint()` in SVGPaintable and SVGSVGPaintable, because display
list recording code has been rearranged to take care of clipping and
scrolling before recursing into SVGSVGPaintable descendants.
`Screenshot/images/css-transform-box-ref.png` expectation is updated and
fixes a bug where a rectangle at the very bottom of the page was not
clipped correctly.
`Screenshot/images/svg-filters-lb-website-ref.png` has a more subtle
difference, but if you look closely, you’ll see it matches other
browsers more closely now.
We assume elsewhere that any abspos element's containing block must be
some kind of Layout::Box, so let's enforce that when deciding if a box
can be such a container.
This fixes a bad downcast on https://serpapi.com/
This exposed a few bugs which caused the following tests to behave
incorrectly:
- `tab-size-text-wrap.html`: This previously relied on a bug where we
incorrectly treated `white-space: pre` as allowing text wrapping. The
fix here is to implement the text-wrap CSS shorthand property.
- `execCommand-preserveWhitespace.html`: We don't correctly serialize
shorthand properties. This is covered by an existing FIXME in
`CSSStyleProperties::serialized()`
- `white-space-shorthand.html`: The last 5 subtests here fail as we
don't correctly handle shorthand properties in
`CSSStyleProperties::remove_property()`. This is covered by an
existing FIXME in said function.
When restructuring a block node inside an inline parent, if the
nearest block ancestor is `display: inline-block`, ensure that
the generated anonymous wrappers also have `display: inline-block`.
This fixes layout issues with block elements nested
inside inline-block elements.
The special case for anonymous table wrappers actually ended up hurting
correctness by preventing the full ancestor chain from being marked for
for intrinsic size cache invalidation.
Caused Layout/input/table/propagate-style-update-to-wrapper.html to
flake on CI, and was easy to reproduce locally with sanitizers.
The fix here is simply to remove the special handling of anonymous table
wrapper parents, since *all* parents are invalidated automatically
anyway!
Began flaking in fa9c463ffd.
Instead of indiscriminately clearing the cache for all anonymous boxes,
we now only clear it for those that were generated by a non-anonymous
box in need of layout update.
This increases the cache hit rate and allows us to avoid more work.
We now cache the containing block (box) once at the start of layout,
which allows Layout::Node::containing_block() to return instantly
instead of doing tree traversal.
Removes a 0.7% profile item on Speedometer 3.
This is a improved version of a73cd88f0c
The old commit was reverted in 552dd18696
The new version only paints an element into a new layer if background
blend modes other than normal are used. The rasterization performance
of most websites should therefore not suffer.
Co-Authored-By: Alexander Kalenik <kalenik.aliaksandr@gmail.com>
This reverts commit a73cd88f0c.
Emitting SaveLayer for each paintable made rasterization a lot slower
on every website because now Skia has to allocate enormous amounts of
temporary surfaces. Let's revert it for now and figure how to implement
it with less aggressive SaveLayer usage.
positioned element is a descendant of inline-block
Sets inline block offsets in InlineFormattingContext.cpp, but this is
not enough. When static position rect is calculated during layout,
not all ancestors of abspos box may have their offsets calculated yet
(more info here: https://github.com/LadybirdBrowser/ladybird/pull/2583#issuecomment-2507140272).
So now static position rect is calculated relative to static containing
block during layout and calculation relative to actual containing block
is done later in
FormattingContext::layout_absolutely_positioned_element.
Fixes wpt/css/CSS2/abspos/static-inside-inline-block.html
Before this change, an element masked with 'mask-image: url(...)' would
show the mask, but 'mask: url(...)' would not. On e.g. dialogic.nl it
would show white boxes instead of the actual images in the top
navigation bar. We still do not support many of the other mask
properties, but with this change at least the masks show up in both
cases.
This reduces the number of `.cpp` files that need to be recompiled when
one of the below header files changes as follows:
CSS/ComputedProperties.h: 1113 -> 49
CSS/ComputedValues.h: 1120 -> 209
Having one big `if` to determine whether or not we should restructure an
inline layout node became a bit unwieldy. This extracts the logic into a
separate method.
When drawing a table, some of the CSS properties must be moved from the
table grid box to an anonamyous table wrapper box. One of these
properties is `position`. `z-index` however is not. This leads to the
following behavior if a table has both `position` and `z-index`:
* The wrapper box has the `position`, but a `z-index` of `auto`.
* The grid box has the `z-index`, but `position: static`.
This effectively means that the `z-index property is ignored since it
has no effect on non-positioned elements. This behavior contradicts what
other browsers do and causes layout issues on websites.
To align Ladybird behavior with other browser this commit also moves the
`z-index` property to the wrapper box.
While keyword_to_foo() does return Optional<Foo>, in practice the
invalid keywords get rejected at parse-time, so we don't have to worry
about them here. This simplifies the user code quite a bit.
This fixes the very, _very_ slow loading of https://yzy-sply.com. The
`apply_style()` method also calls into this method recursively, so we
just need to call it once instead of once per node in the continuation
chain.