Commit Graph

236 Commits

Author SHA1 Message Date
Gingeh
7b3afbc11c LibWeb: Paint element overlay during Foreground paint phase
Also removed the FocusAndOverlay phase because it is now useless
2026-01-24 11:54:39 +01:00
Jelle Raaijmakers
779c5a61e0 Tests/LibWeb: Use hidden image workaround for flaky test
We use this workaround in other tests as well. As a bonus, replace the
data: URL with an image we already had available.
2026-01-23 20:19:11 +00:00
Callum Law
c35ecc8b1c LibWeb: Respect font-width for variable fonts 2026-01-21 23:49:25 +01:00
Tim Ledbetter
cc559048cc LibWeb: Paint element outlines during Foreground paint phase
Previously, outlines for elements without their own stacking context
were painted during the `FocusAndOverlay` phase, which runs after all
child stacking contexts. This caused outlines to incorrectly appear
on top of elements with higher z-index.
2026-01-20 15:38:54 +01:00
Jelle Raaijmakers
f2f8f3ae57 LibWeb: Propagate <body>'s image-rendering to root element
Whenever we propagated a <body>'s background image to the root element,
we ignored any `image-rendering` property present.
2026-01-19 12:05:08 +01:00
Tim Ledbetter
81973cafa4 LibWeb: Size root element backgrounds relative to its border box 2026-01-18 00:31:03 +01:00
Aliaksandr Kalenik
affad6c85d Tests: Add ref tests for nested sticky positioning
Increases sticky positioning test coverage.
2026-01-15 19:50:53 +01:00
Aliaksandr Kalenik
009ddd4823 LibWeb: Integrate AccumulatedVisualContext with display list
Integrate AccumulatedVisualContext with display list recording and
playback. This is the main commit of the refactoring that delivers the
architectural improvements enabled by AccumulatedVisualContext.

Recording changes:

Each display list command now stores a single
RefPtr<AccumulatedVisualContext> instead of separate scroll_frame_id
and ClipFrame. The recorder simply captures the current accumulated
context when appending commands.

The before_paint()/after_paint() hooks that pushed/popped scroll frame
IDs are replaced by directly setting accumulated_visual_context on the
recorder before painting each element.

Playback changes:

The display list player now uses LCA (Lowest Common Ancestor) based
traversal to switch between visual contexts efficiently. When
transitioning from context A to context B:

1. Find the LCA of A and B in the context tree
2. Pop (restore) states back to the LCA depth
3. Push (save + apply) states from LCA down to B

This approach minimizes redundant save/restore operations. For example,
when rendering siblings that share a common scroll container, the
player keeps that scroll state applied and only switches the divergent
parts of their context chains.

Key deletions:

- Remove translate_by() from all 45 display list commands - commands
  are now immutable
- Remove transform/perspective fields from PushStackingContext -
  transforms are tracked via AccumulatedVisualContext
- Remove push_scroll_frame_id()/pop_scroll_frame_id() from
  DisplayListRecorder
- Remove before_paint()/after_paint() hooks from Paintable
- Merge ApplyOpacity, ApplyCompositeAndBlendingOperator, ApplyFilter
  into single ApplyEffects command

Stacking context painting changes:

The StackingContext::paint() method is significantly simplified.
Instead of building a PushStackingContextParams struct with transform
matrices and pushing/popping stacking contexts, it now:

1. Sets the accumulated visual context (which already contains
   transforms)
2. Applies effects (opacity, blend mode, filters) if needed
3. Applies clip path if needed
4. Paints the content
5. Restores state

The visual state management that was interleaved throughout the
painting code is now handled uniformly by the context tree.
2026-01-15 19:50:53 +01:00
Aliaksandr Kalenik
c87daa61a6 Tests: Add regression test for SVG transforms with opacity
Add a test case that was reduced from a regression discovered and fixed
during the AccumulatedVisualContext refactoring. The test verifies that
SVG elements with both CSS transforms (rotate) and opacity render
correctly together.
2026-01-15 19:50:53 +01:00
aplefull
4608987da9 LibWeb: Resolve SVG url() references in shadow root scope 2026-01-15 11:06:22 +00:00
Michael Watt
9e35e06dc3 LibWeb: Create containing blocks for non-initial filter values
This fixes:
http://wpt.live/css/css-will-change/will-change-abspos-cb-002.html
http://wpt.live/css/css-will-change/will-change-abspos-cb-003.html
http://wpt.live/css/css-will-change/will-change-fixedpos-cb-001.html
http://wpt.live/css/css-will-change/will-change-fixedpos-cb-004.html
2026-01-12 11:52:50 +00:00
Shannon Booth
71cfc859f9 LibWeb/SVG: Implement <feDropShadow> filter integration 2026-01-11 13:14:40 +01:00
sideshowbarker
1b41659efd LibXML+LibWeb: Use existing HTML entities table for XML parsing too
For XHTML documents, resolve named character entities (e.g., &nbsp;)
using the HTML entity table via a getEntity SAX callback. This avoids
parsing a large embedded DTD on every document and matches the approach
used by Blink and WebKit.

This also removes the now-unused DTD infrastructure:

- Remove resolve_external_resource callback from Parser::Options
- Remove resolve_xml_resource() function and its ~60KB embedded DTD
- Remove all call sites passing the unused callback
2026-01-09 19:13:41 +00:00
Sam Atkins
aca321684f Tests: Reimport disabled mediaqueries ref tests, and enable passing ones 2026-01-09 08:11:11 +01:00
Tim Ledbetter
5de5e7522b LibWeb: Implement interpolation of drop-shadow() filter functions 2026-01-06 12:13:13 +01:00
Aliaksandr Kalenik
f1253c7139 LibWeb: Fix grid placement when using unresolved named grid lines
This patch fixes an issue where grid items using `grid-area: <name>`
with no matching named grid area or lines would be incorrectly placed
at position 0.

According to https://www.w3.org/TR/css-grid-1/#line-placement:
1. When a `<custom-ident>` doesn't match any named line, placement
   should fall back to the first implicit grid line
2. When the same `<custom-ident>` is given for both `grid-*-start` and
   `grid-*-end` (which happens with `grid-area: name`), and both fall
   back to the same implicit line, the resulting span is 1

Previously, the fallback values were hardcoded to 0 and 1, which placed
items in track 0. The fix changes the fallback to use
`m_explicit_line_count` (the first implicit line index) for both start
and end identifiers. When both reference the same line (start == end),
the existing "both positioned" logic now handles this by setting span=1
and adjusting end accordingly.
2026-01-03 16:41:31 +01:00
Gingeh
690c48d912 LibWeb: Don't crash from svg mask reference cycles 2025-12-20 23:54:54 -06:00
Sam Atkins
38b02c79ad LibWeb/CSS: Allow a slash in border-radius longhand properties
`border-radius` requires a slash between the x/y components, but the
longhands like `border-top-left-radius` don't allow it. This spec
change allows authors to put a slash there for consistency.

Corresponds to:
e938d7d705
2025-12-15 14:30:20 +00:00
Sam Atkins
f9f4c36f20 LibWeb: Implement the headingoffset and headingreset attributes
:heading() now matches based on a computed heading level, which is based
on the level of the tag (h1, h2, etc) and then modified by these two new
attributes.

I'm caching this heading level on HTMLHeadingElement, based on the dom
tree version. That's more invalidation than is actually needed, but it
saves us calculating it over and over when the document hasn't changed.

The failing test cases are:
- Implicit headingreset for modal dialogs which is apparently unspecced
  and controversial.
- Not walking the flat tree properly. A flat tree ancestor of a
  slot-assigned element is its slot, which is something we don't do
  anywhere that I could find. I've made a note to look into this later.

We also don't implement the `ReflectRange` IDL attribute yet, which
means we're not clamping the read value of `headingOffset`.

Corresponds to:
e774e8e318
2025-12-15 14:08:24 +00:00
Tim Ledbetter
ac2334453b LibWeb: Use default fetch processing for any applicable rel keyword
Previously, the `preload`, `preconnect` and `dns-prefetch` keywords
took precedence over the others. When these keywords were present
the default fetch processing steps would not occur even when a relevant
keyword such as `stylesheet` or `icon` was present.
2025-12-13 10:52:25 -05:00
Jelle Raaijmakers
7a693a9780 LibWeb: Use parent's space for anonymous wrappers with inline contents
We already dealt with this for block level children, but inline level
children should also look at the anonymous wrapper's parent's available
space to be able to properly resolve percentage values, for example.
2025-12-11 23:29:14 +00:00
Callum Law
dca80ad5eb LibWeb: Account for animated values when computing font
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
2025-12-05 10:03:15 +00:00
InvalidUsernameException
fb9286eccb LibWeb: Apply clip frames even when transformation is identity
Clip frames for overflow were applied based on whether the box in
question had a non-identity matrix transformation associated with it.
That however is not correct, since specifying a no-op transform like
`scale(1)` still needs to apply clip overflow rectangles. So instead we
need to check whether the element associated with the box in question
has any CSS transforms.

This appears to have been a regression from
9bbc1cd618 and effectively reverts that
commit, but keeps its effect by unifying on the check for CSS transforms
instead.

This fixes some background boxes being rendered for the invisible items
of the carousels on https://computerbase.de/.
2025-12-01 17:46:44 +01:00
Callum Law
1a5933cb04 LibWeb: Fail less when multiple mask images are defined
We don't yet support multiple images but we at least continue to use the
first rather than having none
2025-12-01 10:16:41 +00:00
Callum Law
9de4e3a0eb LibWeb: Avoid resetting important flag when recomputing inherited style
We were missing the important flag here so would always reset it to
false
2025-11-28 16:15:49 +00:00
InvalidUsernameException
bc44203744 LibGfx+Tests: Load bmp files with unpremultiplied alpha
From what I can tell BMP files with an alpha channel always store
unpremultiplied alpha. So let's load them as such to avoid rendering
artifacts from using the wrong alpha type.
2025-11-28 17:00:29 +01:00
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
Sam Atkins
9a1352fc17 LibWeb/CSS: Support calculated angles in conic-gradient() 2025-11-21 11:36:28 +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
0e8f3a4648 Tests: Import ahem font for ref tests
A few tests were trying to use ahem.css but failed because the path was
invalid and the font wasn't imported.
2025-11-20 16:02:40 +01:00
Aliaksandr Kalenik
597fe8288c LibWeb: Apply own clip rect for background phase only when clip used
Fixes a bug where we would clip `box-shadow` when `overflow: hidden`
was set, which is not supposed to happen since `overflow` only affects
clipping of an element's content.
2025-11-19 18:17:42 +01:00
Tim Ledbetter
36c6079dbc LibWeb+LibGfx: Implement SVGFEMorphologyElement
This filter primitive is used to erode or dilate an image.
2025-11-15 16:08:53 +01:00
mikiubo
88e19ebc11 LibWeb: Handle empty string namespaces in selector matching
Per the CSS Namespaces spec, an empty string declared in an
@namespace rule represents no namespace.

Fixes WPT:
- css/css-namespaces/prefix-002.xml
- css/css-namespaces/prefix-003.xml
2025-11-14 08:16:53 +00:00
Psychpsyo
d284b4c2b8 LibWeb: Clamp any values less than 1 in perspective() transform function 2025-11-12 18:45:09 +01:00
Psychpsyo
e064fa19d2 LibWeb: Add transform-style and have it make a stacking context 2025-11-12 15:47:36 +01:00
Tim Ledbetter
154e9db033 LibWeb: Cache the value of Element::lang()
This reduces the time spent in
`SelectorEngine::matches_lang_pseudo_class()` from 1.9% to 0.41% on
https://cloudflare.com
2025-11-12 12:36:16 +01:00
Psychpsyo
eb21ea890c LibWeb: Implement CSS perspective property 2025-11-12 00:41:14 +01:00
Psychpsyo
e44a97e508 LibWeb: Pass 3D transforms to Skia 2025-11-12 00:41:14 +01:00
Tim Ledbetter
5294559f7b LibWeb: Use logical properties in UA stylesheet 2025-10-24 10:11:49 +01:00
Tim Ledbetter
1c00279488 LibWeb: Reset Painter when resetting canvas to its initial state 2025-10-23 18:52:36 +02:00
Pavel Shliak
5ee1031b89 LibWeb: Implement SVGFEColorMatrixElement and feColorMatrix 2025-10-23 13:36:26 +02:00
Lorenz A
e73e0b3c92 LibWeb: Implement CSS decode bytes algo 2025-10-16 16:44:42 +02:00
Callum Law
3708fc6aa7 LibWeb: Resolve relative lengths in @font-face using correct viewport
As with everywhere else we should be using the document rather than the
window's viewports.

Fixes #6467
2025-10-16 10:27:32 +01:00
Tim Ledbetter
e55060ef6e LibWeb: Support the display-p3-linear color space in color functions 2025-10-15 18:40:48 +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
125b13a0cb LibWeb/CSS: Test cases for content inside the ::marker pseudo-element 2025-10-10 12:02:16 +01:00
Sam Atkins
89c89470ef LibWeb/CSS: Stop rejecting declarations with vendor-prefixed keywords
property_accepts_type() only looks at the property itself, not any
longhands it might have, so we thought that `font` didn't accept
`<custom-ident>`s, and seeing "-apple-..." makes us throw out the
declaration even though it's valid as a font name.

We'll reject these like any other unrecognized value if it's somewhere
that's not supported, so this was really just an optimization for a
rare edge case, and removing the check doesn't have any observable
effect except fixing this bug and any similar cases.

Changing property_accepts_type() to look at longhands is not
straightforward, as not all longhand values are valid in the shorthand.
2025-10-02 13:26:26 +02:00
Tim Ledbetter
c79063a77d LibWeb: Convert blend test to use rectangle rather than circle
Using a circle isn't relevant to the outcome of the test and introduces
anti-aliasing artifacts.
2025-09-30 22:33:12 +01:00