Commit graph

713 commits

Author SHA1 Message Date
Lorenz A
010b0b00ff LibWeb: Propagate style values in deep anonymous wrappers
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.
2025-11-23 21:38:07 +01:00
Psychpsyo
2db3796fd3 LibWeb: Implement CSS perspective-origin 2025-11-21 11:14:28 +00:00
Jelle Raaijmakers
2c5beeabe3 LibWeb: Improve support for SVG text positioning attributes
Previously, we only supported very basic numbers and a single level of
text positioning support in the `x`, `y`, `dx` and `dy` attributes in
`<text>` and `<tspan>` SVG elements.

This improves our support for them in the following ways:

  * Any `length-percentage` or `number` type value is accepted;
  * Nested `<text>` and `<tspan>` use the 'current text position'
    concept to determine where the next text run should go;
  * We expose the attributes' values through the API.

Though we still do not support:

  * Applying the `rotate` attribute;
  * Applying transformations on a per-character basis.
  * Proper horizontal and vertical glyph advancing (we just use the path
    bounding box for now).
2025-11-20 23:15:24 +01:00
Sam Atkins
fd4888e800 LibWeb/Layout: Honor hanging and each-line in text-indent 2025-11-20 16:02:40 +01:00
Sam Atkins
c4b9e7eadf LibWeb: Parse and propagate extended text-indent property values
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.
2025-11-20 16:02:40 +01:00
Aliaksandr Kalenik
70b5496ecd LibWeb: Account for box-sizing in max-content contribution [GFC]
Use `calculate_inner_height()` and `calculate_inner_width()`, which
account for box-sizing, to resolve the item's size in max-content
contribution calculations.
2025-11-14 16:24:30 +01:00
Psychpsyo
e064fa19d2 LibWeb: Add transform-style and have it make a stacking context 2025-11-12 15:47:36 +01:00
Psychpsyo
eb21ea890c LibWeb: Implement CSS perspective property 2025-11-12 00:41:14 +01:00
Jelle Raaijmakers
c845e2cef7 LibWeb: Don't join anonymous pseudo wrappers for block node insertion
This can happen if pseudo elements are absolutely positioned, they need
the nearest non-inline parent to determine their position.
2025-11-11 10:49:49 +01:00
Jelle Raaijmakers
ac829cf60a LibWeb: Hoist anonymous wrappers out of parent inline nodes
When we generate pseudo elements, we create anonymous wrappers that
might end up in an InlineNode, even if they have `display: block` set.
This causes them not to be rendered.

Do not rely on inline continuation logic for these anonymous wrappers,
but rather find the first layout parent that's not an InlineNode and
insert it into that.

Fixes #5042.
2025-11-11 10:49:49 +01:00
Callum Law
9d515ec666 LibWeb: Share a ColorResolutionContext in apply_style
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
2025-11-10 12:11:36 +01:00
Callum Law
bbb344d534 LibWeb: Compute font features in ComputedProperties
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
2025-11-10 12:11:36 +01:00
Callum Law
7a5b948b5b LibWeb: Resolve more calculated values in ComputedProperties
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
2025-11-10 12:11:36 +01:00
Andreas Kling
6894034774 LibWeb: Mark flex item main size definite if resolved from aspect-ratio
This matches the behavior of other engines and makes the cards on the
Apple App Store appear in the narrower layouts.
2025-11-07 16:42:32 +01:00
Andreas Kling
baa9b6cc34 LibWeb: Prefer non-emoji font when deciding width of space between words
This fixes an issue where having an emoji font first in the font-family
cascade list would cause us to get the space width from the emoji font
as well.

We now look at adjacent text chunks when deciding which font to use for
space widths, instead of just blindly obeying the font-family value.
2025-11-06 23:42:01 +01:00
Jelle Raaijmakers
3741d3040c LibWeb: Support percentage values in min/max flex item size constraints
Originally, 7200b3a16c introduced a two-pass system to determine
hypothetical cross sizes. Later, this was partially reverted in
0084d992d4, but some code was left behind that caused resolution of
percentages in `{min/max}-{width/height}` size constraints not to work.

Through intrinsic sizing, we can potentially end up with a definite
available space for the items in the last FC run. At that point we
should be able to resolve percentages against the available space, but
we were never doing that.
2025-11-05 12:01:40 +01:00
Jelle Raaijmakers
4ff17fc8d7 LibWeb: Only consider main size for item height in intrinsic sizing
We did not actually check whether we are in intrinsic sizing mode, and
should actually use the available space in all other cases. This will
allow for proper determination of the hypothetical cross size in the
next commit.
2025-11-05 12:01:40 +01:00
Jelle Raaijmakers
f9b4fa9702 LibWeb: Add CSS::Size::is_intrinsic_sizing_constraint() 2025-11-05 12:01:40 +01:00
Andreas Kling
cebd4cc10d LibWeb: Add ImageProvider virtual to access the DecodedImageData
...and also the current frame index, in case of animations.
2025-11-05 09:11:49 +01:00
ayeteadoe
30729feebb LibWeb: Prevent crash in content calculations for ListItemMarkerBox
In several content calculation methods in FormattingContext, we assumed
that if create_independent_formatting_context_if_needed() fails the
input Layout::Box is a BlockContainer; however, the web platform test
css/css-pseudo/parsing/marker-supported-properties-in-animation.html is
one scenario where the input is a Layout::ListItemMarkerBox instead and
there is no FormattingContext supported for it yet.
2025-10-30 18:21:24 +00:00
Lorenz A
ffcd3a4bb2 LibWeb: Count the width of inline-blocks in InlineNodes only once
An BlockContainer inside an InlineNode is called from the
`for each in inclusive_subtree_of_type`  but is also a fragment
 of that InlineNode. Don't count the the Node twice.
2025-10-27 21:45:33 -07:00
Jelle Raaijmakers
beb1d60714 LibWeb: Simplify calculation of the SVG viewbox transform
We don't need to construct a new AffineTransform and multiply that by
yet another AffineTransform; we can simply translate and scale the
transform that's already in place. No functional changes.
2025-10-27 16:42:27 -07:00
Callum Law
12716dccf0 LibWeb: Avoid including ComputedProperties.h in Element.h
This reduces the size of the recompile when ComputedProperties.h is
modified from ~1200 to ~70
2025-10-27 14:50:54 +00:00
Jelle Raaijmakers
62ae4e878f LibWeb: Implement support for drawing with CanvasPattern
We already had the API, but drawing to the canvas was not affected by
any created CanvasPattern. This moves CanvasPatternPaintStyle to LibGfx
so we don't have to reach into LibWeb, and implements the plumbing to
let Skia use images as a fill pattern.
2025-10-23 13:20:03 +01:00
Callum Law
fc5cdd69a0 LibWeb: Extract transition coordination logic to reusable method
This will be useful for other coordinating list property groups (e.g.
background and animation)
2025-10-23 10:09:11 +01:00
Amish K. Naidu
884b7fcbf5 LibWeb: Peek after extracting next chunk in InlineLevelIterator
Peek is used to determine if the current chunk is
the last and if so, add trailing box metrics.
For this to work correctly, it must be done only
after calling next(), otherwise peek gives us the
current chunk.
2025-10-20 12:37:25 +01:00
Luke Wilde
eeb5446c1b LibWeb: Avoid including Navigable.h in headers
This greatly reduces how much is recompiled when changing Navigable.h,
from >1000 to 82.
2025-10-20 10:16:55 +01:00
Tim Ledbetter
0bdb831c68 LibWeb: Avoid null dereference in ListItemBox specified content check 2025-10-14 10:27:11 +01:00
InvalidUsernameException
1ffb0ca311 LibWeb: Remove redundant function parameter
This function can really only be called with a box and its containing
block, otherwise the results are not meaningful. Instead of passing
these two dependent values separatly, reduce it down to a single
parameter to not make the function appear more general than it is.
2025-10-14 10:23:27 +02:00
InvalidUsernameException
70c46e081d LibWeb: Correctly calculate nested positioned elements' static position
If there are multiple nested `position: fixed` or `position: absolute`
elements that are positioned based on their static position due to not
specifying any insets, we sum up all their ancestor offsets to calculate
said static position.

However, these offsets represent the offset to the containing block. So
summing up all the ancestor blocks will count elements multiple times
for cases where the containing block is not based on the closest element
capable of forming a containing block (i.e. absolute and fixed position
elements) when multiple such elements are nested.

With this change we only iterate over ancestors forming containing
blocks instead of over all ancestors boxes. To sum up everything between
the box currently being positioned and its containing block, we start
the iteration on the parent box of the current box.

This fixes 3 WPT tests that I could find. But these tests are not
intended to test the error cases fixed here, they just incidentally rely
on the correct behavior. As such, I have added dedicated tests myself.
Note that two of the tests already pass on master, but they seemed like
a good cases to have anyway.
2025-10-14 10:23:27 +02:00
=
a3e973970a LibWeb/CSS: Check overflow value before determining box baseline
The CSS spec says the baseline of an inline-block should be the bottom
margin when either the overflow property is not 'visible' or there are
no in-flow line boxes. Previously, only the latter case was checked.

This fixes 1 WPT test:
https://wpt.live/css/css-align/baseline-of-scrollable-1a.html
2025-10-13 09:47:32 +01:00
Manuel Zahariev
9d77221c4d LibWeb/CSS: Add support for content to the ::marker pseudo-element
A ::marker pseudo-element is created for list item nodes (nodes
with display:list-item).

Before:
    - The content of the ::marker element is created magically from
    the value of the ordinal (for <ol>) or from a template (for <ul>).
    The style `content` is ignored for ::marker pseudo-elements.

After:
    - If a "list item node" has CSS `content` specified for its ::marker
    pseudo-element, use this to layout the pseudo-element,
    https://drafts.csswg.org/css-lists-3/#content-property
    - Otherwise, layout the list item node as before.
2025-10-10 12:02:16 +01:00
Aliaksandr Kalenik
d3f40e9a72 LibWeb: Delete AudioPaintable::layout_box()
No need for this method when we could reach into DOM node directly from
Paintable.
2025-10-10 09:03:39 +02:00
Luke Wilde
adeedabf54 LibWeb: Don't class mousewheel as handled if scroll offset isn't updated
Before this change, you could only scroll the current hovered scroll
container, even if it was at the beginning or end and thus having no
effect.

Now, if it doesn't update, it will not be classed as handled and will
move onto the next scroll container.
2025-10-07 19:43:07 +02:00
Callum Law
25192d3c20 LibWeb: Store BorderRadiusStyleValue sub-values directly
Storing these within LengthPercentage is unnecessary
2025-10-07 10:50:01 +01:00
Callum Law
2ebf446cbf LibWeb: Store BackgroundSizeStyleValue sub-values directly
Storing these within LengthPercentage is unnecessary
2025-10-07 10:50:01 +01:00
Sam Atkins
3916e33276 LibWeb/CSS: Parse the container-type property
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.
2025-09-30 22:05:45 +01:00
Pascal Pomper
5b1eba7ac8 LibWeb: Position absolute block-level boxes below previous siblings
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.
2025-09-29 18:37:53 +02:00
Andreas Kling
7867fef8d7 LibWeb: Use correct width for flex item intrinsic height calculation
Before this change, we always used the flex container's full available
space as the width for intrinsic (height) sizing of flex items.

This meant that flex lines with more than one flex item had their
intrinsic height determined as if they were alone on the line.

For flex row layouts, if we've already determined the flex item's main
size, we now use that as the width to get the intrinsic height.

This leads to more correct layouts, and also avoids some redundant work
since we no longer do unnecessary sizing work with the wrong width (and
can hit cache instead).
2025-09-29 13:27:58 +02:00
Andreas Kling
6ec10a5408 LibWeb: Make more FlexFormattingContext functions take FlexItem
...instead of taking the Layout::Box. This will allow us to make more
nuanced decisions in those functions by having access to flex layout
internal state.
2025-09-29 13:27:58 +02:00
Andreas Kling
f00f975cf4 LibWeb: Treat percentage max-width as none during min-content sizing
...but only for non-replaced boxes. This is what CSS-SIZING-3 tells us
to do, and we were already doing it for width, but neglecting max-width.
2025-09-28 19:25:18 +02:00
Psychpsyo
4e0abaaede LibWeb: Don't assume ImageBox's image provider is the DOM node
This gets rid of the assumption that the DOM node of an ImageBox is
also its image provider. This will become necessary when generating
the image boxes for view transition pseudos, for which the DOM node
won't be the image provider. (that'll be the pseudo element itself)
2025-09-25 22:38:05 +01:00
Andreas Kling
989f6ddb42 LibWeb: Add fast_is<T> for hotly dynamic_cast'ed things on imdb.com 2025-09-25 21:42:52 +02:00
Andreas Kling
4b281fa880 LibWeb: Make Length ctor/dtor/factory inline
These functions are trivial, and we were actually bleeding a lot of time
in profiles to just function entry/exit.

By marking Length::make_px() as [[nodiscard]], we also exposed some
places that were creating a Length and not using it for anything.
2025-09-24 23:59:41 +02:00
Sam Atkins
0314606c73 LibWeb/CSS: Replace resolve_length_deprecated() with resolve_length() 2025-09-24 16:33:53 +01:00
Sam Atkins
0ff012d3f3 LibWeb/CSS: Replace resolve_time_deprecated() with resolve_time() 2025-09-24 16:33:53 +01:00
zac
8c29b0a848 LibWeb/Tests: Add empty text chunk in empty editables
Otherwise the cursor won't get rendered in empty input fields.
2025-09-24 12:33:17 +01:00
zac
152711958e LibWeb: Add const where possible in InlineLevelIterator 2025-09-24 12:33:17 +01:00
zac
fca2d71b16 LibWeb: Set is_first_chunk to false as needed in InlineLevelIterator
`m_text_node_context->is_first_chunk` was always true because
`InlineLevelIterator::next_without_lookahead` never set it to false.
2025-09-24 12:33:17 +01:00
zac
191b026c9f LibWeb: Rename is_generated to is_generated_for_pseudo_element
While much longer, this better conveys the intent. Since this method
isn't used too often, I think the extra length is worth it.
2025-09-24 12:33:17 +01:00