Commit Graph

453 Commits

Author SHA1 Message Date
Sam Atkins
f657a4b71b LibWeb/CSS: Parse @font-face { font-weight } with two values
WPT has coverage for matching but not parsing, so the test is homemade.
2026-02-24 10:05:09 +00:00
Aliaksandr Kalenik
86bc379119 Tests: Move true ref tests from Screenshot/ to Ref/
Move them to Ref/ where they belong, before converting the remaining
Screenshot tests to direct PNG comparison.
2026-02-24 09:55:14 +01:00
Luke Wilde
8017f8a7ed Tests/LibWeb: Import Fullscreen WPT tests 2026-02-23 18:44:26 +00:00
Callum Law
8d4084261a LibWeb: Resolve list item marker using registered counter styles 2026-02-23 11:21:09 +00:00
Callum Law
ca54cc6c79 LibWeb: Resolve <counter> functions using registered counter styles
Previously we only supported a subset of the predefined counter styles,
we now respect counter styles defined by `@counter-style` rules when
resolving the value of `counter()` and `counters()` functions
2026-02-23 11:21:09 +00:00
Tim Ledbetter
81f077adfd LibWeb: Ensure mspace presentation hint is valid before setting it
The height and depth attributes are parsed individually and then
combined into a `calc()` expression. Bare zero is valid as a standalone
CSS length but inside `calc()` it is typed as a number, so
`calc(0 + 0)` fails to parse as a length. We now check the parsed value
is valid to avoid a crash.
2026-02-23 09:57:32 +01:00
Tim Ledbetter
8240fa0dc8 LibWeb: Resolve percentage table widths in wrapper width computation
Previously, a table with `width: 100%` and `margin: auto` whose content
was narrower than the viewport would be centered based on content
width rather than filling the containing block. Resizing the viewport
wider than the content would shift the table progressively further to
the right.

Co-authored-by: Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
2026-02-21 05:16:56 +01:00
Jelle Raaijmakers
ca45464c87 LibWeb: Scale down perspective transformation by DPR in DisplayList
By doing so, we attenuate the perspective transform on higher resolution
devices such as Retina displays (2x).

This fixes the perspective transform on sites such as
https://poke-holo.simey.me/.
2026-02-19 21:31:21 +01:00
Tim Ledbetter
8c5d081cdd LibWeb: Ensure elements with non-invertible transforms are not rendered 2026-02-19 14:33:31 +00:00
Luke Wilde
84db5d8c1c Meta+test-web: Support per-test .headers files
If a test requires custom response headers, we now serve it via the
http-test-server, which will read the headers file and add them to the
response.
2026-02-19 14:58:09 +01:00
Jelle Raaijmakers
f2e6f70fbb LibWeb: Use saveLayer compositing for background-clip: text
Instead of rendering text glyphs into a separate mask surface and using
clipShader, paint the backgrounds first and then composite the text
glyphs via saveLayer with SkBlendMode::kDstIn. Skia's saveLayer
automatically sizes its backing at device resolution including CSS
transforms, so no manual scale computation is needed.

Fixes pixelation when zooming in on clipped backgrounds on e.g. the
title of https://modern-css.com/.
2026-02-17 18:59:33 +01:00
Jelle Raaijmakers
aa2a95c775 LibWeb: Pass through background image painting even if area is empty
We should decide at a later stage, when we've calculated the final
background painting area, whether that area is empty and we can skip
painting the background.

Fixes #7973
2026-02-16 19:33:01 +01:00
Psychpsyo
05c785b081 LibWeb: Only use overflow clip edge when overflow is set to clip 2026-02-14 22:58:21 +01:00
Psychpsyo
a7267f711b LibWeb: Add overflow-clip-margin-* properties
The corner radius isn't quite right yet, but this gives us
another couple WPT passes for these.
2026-02-14 22:58:21 +01:00
Tim Ledbetter
d49a2dcfa1 LibWeb: Implement word-break functionality using UAX#14 line breaking
We now use ICU's line break iterator to determine soft wrap
opportunities, enabling correct line breaking for CJK text.
2026-02-14 16:23:18 -05:00
Psychpsyo
b29591244e LibWeb: Prevent thin double borders from disappearing
They're also no longer drawin in one stroke since that would
confuse the stroke-drawing code otherwise, since the order of it all
means that we'd be drawing a stroke that jumps back and forth a lot
and had gaps between every line segment.
2026-02-11 11:17:11 +01:00
Tim Ledbetter
6cf506d980 LibWeb: Allow table fixup to find internal table boxes in inline parents 2026-02-11 09:58:38 +01:00
Aliaksandr Kalenik
3fc33f86dd Revert "LibWeb: Flatten non-3d transforms"
This reverts commit 63aeaa81e5.

The change broken image rendering on X.com and
https://browserbench.org/Speedometer3.1/
2026-02-10 19:19:14 +01:00
Psychpsyo
63aeaa81e5 LibWeb: Flatten non-3d transforms 2026-02-07 18:56:23 +01:00
Jelle Raaijmakers
f55fe69d4d LibWeb: Rework Internals' mouse control
Instead of defining somewhat high level mouse actions, allow granular
control of mouse clicks and mouse down/up/move events. We will want to
simulate things like holding down a mouse button after double clicking
and then dragging the mouse to another position in the future, and this
enables that.
2026-02-06 14:18:10 +00:00
Jelle Raaijmakers
856091fb56 LibWeb: Implement support for text-decoration in ::selection 2026-02-06 10:47:50 +00:00
Jelle Raaijmakers
48aa199f09 LibWeb: Implement support for text-shadow in ::selection 2026-02-06 10:47:50 +00:00
Jelle Raaijmakers
98b4feb406 LibWeb: Apply CSS ::selection styling to text and form controls
Previously, text selection always used the system highlight color. This
implements support for the ::selection pseudo-element's background-color
and color properties.

For form controls like <input> and <textarea>, the selection style is
looked up on the shadow host element, since the actual text lives inside
their shadow DOM.

The text painting logic has been refactored to split fragments into
styled spans (before selection, selected, after selection) so that each
portion can be rendered with its appropriate colors, taking care not to
allocate in 99%+ of fragment rendering cases.
2026-02-06 10:47:50 +00:00
Aliaksandr Kalenik
076726a990 LibWeb: Invalidate layout when SVGPolylineElement attributes change
SVGPolylineElement::get_path() produces a path based on the points
attribute. During layout, this path is copied into paintables. If the
points attribute changes after layout, the path stored in the paintable
becomes stale. Fix by calling set_needs_layout_update() when it changes
so the path is recomputed.
2026-02-05 15:43:41 +01:00
Aliaksandr Kalenik
00fe4a2946 LibWeb: Invalidate layout when SVGPolygonElement attributes change
SVGPolygonElement::get_path() produces a path based on the points
attribute. During layout, this path is copied into paintables. If the
points attribute changes after layout, the path stored in the paintable
becomes stale. Fix by calling set_needs_layout_update() when it changes
so the path is recomputed.
2026-02-05 15:43:41 +01:00
Aliaksandr Kalenik
317075e8b0 LibWeb: Invalidate layout when SVGPathElement attributes change
SVGPathElement::get_path() produces a path based on the d attribute.
During layout, this path is copied into paintables. If the d attribute
changes after layout, the path stored in the paintable becomes stale.
Fix by calling set_needs_layout_update() when it changes so the path
is recomputed.
2026-02-05 15:43:41 +01:00
Aliaksandr Kalenik
c4bdbfbec5 LibWeb: Invalidate layout when SVGLineElement attributes change
SVGLineElement::get_path() produces a path based on x1, y1, x2, and
y2 attributes. During layout, this path is copied into paintables.
If any of these attributes change after layout, the path stored in the
paintable becomes stale. Fix by calling set_needs_layout_update() when
a geometry attribute changes so the path is recomputed.
2026-02-05 15:43:41 +01:00
Tim Ledbetter
d41f77be64 LibWeb: Reset line-height for select elements 2026-02-05 12:34:57 +01:00
Tim Ledbetter
2cd30af4df LibWeb: Only apply overflow clipping to applicable element types
According to the CSS spec, overflow properties only apply to block
containers, grid containers and flex containers.
2026-02-04 21:23:20 +01:00
Aliaksandr Kalenik
da2c07c66d LibWeb: Apply intermediate stacking context effects to abspos elements
Previously, absolutely positioned elements jumped directly to their
containing block's accumulated visual context, skipping effects
(opacity, mix-blend-mode, isolation) from intermediate ancestors. Per
CSS spec, these properties create stacking contexts that abspos elements
cannot escape — they only escape scroll containers and overflow clips.
2026-02-04 20:54:47 +01:00
Psychpsyo
ed2018f301 LibWeb: Add presentational hints for clear attribute on BR elements 2026-02-04 20:24:28 +01:00
Jonathan Gamble
ec50525675 LibWeb/Layout: Don't inject natural size in prepare_for_replaced_layout
Instead, compute them on demand. This affects ReplacedBox and its
subclasses.

This commit is centered around a new Box::auto_content_box_size
method. It returns a SizeWithAspectRatio representing the natural
size of a replaced element, or the size derived from attributes
for text input and textarea. These values are used when the
corresponding axis is auto or indefinite.

Although introducing this API choke-point for sizing replaced and
replaced-like elements was the main goal, it's notable that layout
becomes more robust in the face of dynamic changes due to reduced
potential for stale size values (at the cost of extra calculations
and allocations).
2026-02-02 14:36:49 +00:00
Andreas Kling
91cf575b82 LibWeb: Disable script execution for SVG images loaded via <img>
SVG images loaded as <img> elements must not execute scripts per spec.
Previously, SVGScriptElement::process_the_script_element() did not
check whether scripting was disabled, so script processing was
triggered via the children_changed() callback during XML parsing,
causing a nested event loop spin.

Fix this by:
- Disabling scripting on the SVG image's Page
- Passing XMLScriptingSupport::Disabled to the XML document builder
- Checking is_scripting_disabled() in SVGScriptElement before
  processing any script element
- Logging a diagnostic when SVG XML parsing fails (previously the
  parse result was silently discarded)
2026-02-01 22:48:51 +01:00
Tim Ledbetter
dfeed4e9a6 LibWeb: Return computed content width from TFC automatic_content_width()
Previously, `greatest_child_width()` was used, which finds the maximum
margin box width among direct children. This is incorrect for tables,
whose width is determined by column distribution rather than by simply
finding the widest child. We now return the table's computed content
width instead, which already holds the correct value after layout.
2026-02-01 20:35:16 +01:00
Aliaksandr Kalenik
d29b1bfaa9 LibWeb: Fix sticky positioning inside fixed-position ancestors
When a sticky element was inside a position:fixed ancestor,
nearest_scroll_frame() would stop at the fixed boundary and return
nullptr. This caused precompute_sticky_constraints() to bail out,
leaving the sticky element at its normal flow position with no offset.
2026-02-01 19:57:14 +01:00
InvalidUsernameException
c810e99842 LibWeb: Do not clip inspector overlays
When painting inspector overlays for a highlighted node, we want to
ignore any clipping that may be going on due to explicit CSS properties,
stacking contexts or similar. That makes sure our overlay is not
obscured by the clipping.

This fixes a regression from 009ddd4823.
2026-02-01 14:29:59 +01:00
InvalidUsernameException
27b88b7665 LibWeb: Apply visual context when painting non-boxes as well
When highlighting something that does not correspond to a
`PaintableBox`, we still need to apply `AccumulatedVisualContext`s. In
that case, search for the closest `PaintableBox` ancestor and apply its
`AccumulatedVisualContext`

This bug is most easily observed by highlighting a text node on a page
that has a scrollbar and is scrolled down at least a bit.

This fixes a regression from 009ddd4823.
2026-02-01 14:29:59 +01:00
Tim Ledbetter
89cbe44c71 LibWeb: Apply scroll offset to children of sticky elements with overflow
Previously, sticky elements were excluded from propagating  their
scroll frame to descendants' accumulated visual context. This meant
that when a sticky element also had scrollable overflow, the scroll
offset was never visually applied to its children during painting.
2026-01-31 18:22:30 +01:00
Aliaksandr Kalenik
0fcd8c0bfa LibWeb: Fix pseudo-element scroll offset leaking to generating element
In Element::set_scroll_offset(), when setting a pseudo-element's
scroll offset, the code was also incorrectly setting the generating
element's own m_scroll_offset. Added an else branch so only the
pseudo-element's offset is set.

Also adds a ref test for scrollable pseudo-elements to prevent
regression. The test scrolls a ::before pseudo-element via wheel
event and verifies the content scrolls correctly.
2026-01-27 20:32:12 +01:00
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