Commit graph

600 commits

Author SHA1 Message Date
Tim Ledbetter
cd0074528e LibWeb: Verify type before casting PaintableBox to PaintableWithLines
Previously, calling `BlockContainer::paintable_with_lines()` would cast
a `PaintableBox` to a `PaintableWithLines` without verifying that the
cast was valid, which isn't the cast for `FieldsetPaintable`, for
example. This method now returns null if it isn't poossible to cast to
`PaintableWithLines`.
2025-07-13 03:01:59 +02:00
Jelle Raaijmakers
1e0013a3bc LibWeb: Use margin box height for inline-block vertical alignment
Some checks are pending
CI / macOS, arm64, Sanitizer, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
For `vertical-align: middle` and `vertical-align: text-bottom`, we used
just the content height of the inline box to determine its alignment
position. This caused incorrect positioning when padding is applied.

This fixes the button alignment on our GitHub page.

Fixes #290.
2025-07-12 18:03:14 +02:00
Andreas Kling
8e49b69f42 LibWeb: Never split <svg> for inline continuations
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.
2025-07-12 14:11:41 +02:00
Andreas Kling
4e23882995 LibWeb: Use foreignObject's own size as available space inside it
This ensures that percentages resolve against the foreignObject's size
instead of the size of its containing block.

This makes user profile pictures clip correctly in the "Friends" view
of the Discord app.
2025-07-12 14:11:41 +02:00
Aliaksandr Kalenik
910fd426a2 LibWeb: Allow <svg> to establish a stacking context
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.
2025-07-12 11:01:15 +02:00
Jelle Raaijmakers
2998049fe9 LibWeb: Implement the unreachable scrollable overflow
Whenever we end up with a scrollable overflow rect that goes beyond
either of its axes (i.e. the rect has a negative X or Y position
relative to its parent's absolute padding box position), we need to clip
that rect to prevent going into the "unreachable scrollable overflow".

This fixes the horizontal scrolling on https://ladybird.org (gets more
pronounced if you make the window very narrow).
2025-07-11 08:23:46 +02:00
Tim Ledbetter
438bb56160 LibWeb/SVG: Don't crash when a filter has no valid effects 2025-07-10 00:18:25 +02:00
Lucien Fiorini
635adc8aa7 LibWeb/SVG: Implement resolution for a subset of SVG filters 2025-07-09 18:07:12 +01:00
Andreas Kling
aae0b52403 LibWeb: Resolve mask/clip in foreignObject's own coordinate space
We were neglecting to resolve these correctly, which caused them to get
the same metrics as the nearest viewport above the foreignObject.
2025-07-09 14:36:08 +02:00
Andreas Kling
f5f3cd041a LibWeb: Apply SVG viewbox transform to foreignObject elements 2025-07-09 14:36:08 +02:00
Andreas Kling
f343a418b2 LibWeb: Never split SVG foreignObject for inline continuations
This would produce a bizarre layout tree and certainly not yield
expected results.
2025-07-09 14:36:08 +02:00
Andreas Kling
b4708510fb LibWeb: Layout foreignObject as block-level element with hidden overflow
This is according to the default user-agent style from the SVG2 spec.

In order for this to work correctly, we also have to assign width and
height to foreignObject boxes during SVG layout, since they are handled
manually by SVGFormattingContext.
2025-07-09 14:36:08 +02:00
Andreas Kling
ddcb87fb40 LibWeb: Make TreeBuilder nicer to SVG foreignObject
This patch does two things:

1. Makes TreeBuilder never cross the foreignObject boundary when looking
   for an appropriate insertion parent. Before this change, we would
   sometimes make things inside the foreignObject DOM subtree have
   layout nodes outside the foreignObject.

2. Makes foreignObject boxes participate in the anonymous wrapping of
   inline-level boxes. This is particularly imporant for absolutely
   positioned elements inside foreignObject, which were previously
   getting incorrectly wrapped if there was any text (even empty)
   preceding the abspos element.
2025-07-09 14:36:08 +02:00
Andreas Kling
07838016c8 LibWeb: Make layout code aware that we create BFC for foreignObject
We were already always doing this, but through an unusual mechanism:
SVG layout creates a BFC on the stack when laying out foreignObject
subtrees.

This change makes the rest of the layout system aware of this, and
also allows it to be reflected in layout dumps.
2025-07-09 14:36:08 +02:00
Andreas Kling
0cf9a4543a LibWeb: Make SVG foreignObject establish a new stacking context
This matches the behavior of Blink and Gecko, but not WebKit.
2025-07-09 14:36:08 +02:00
Aliaksandr Kalenik
8d9920af16 LibWeb: Account for natural aspect ratio in calculate_min_content_height
By the time we calculate the min-content height, the width is already
known, so we can use it to calculate the height based on the natural
aspect ratio.
2025-07-08 22:35:04 +02:00
Callum Law
36e2d25efa LibWeb: Parse grid track placements closer to spec
This brings parsing of grid-row-* and grid-column-* properties (and
their associated shorthands) more inline with spec.

Changes:
- Only set omitted properties for combined-value shorthands (e.g.
  `grid-row: a` rather than `grid-row: a / b`) if the single value is
  `<custom-ident>`.

- `[ [ <integer [-∞,-1]> | <integer [1,∞]> ] && <custom-ident>? ]`:
  - Properly resolve `calc`s for `<integer>` that rely on compute-time
    information.

- `[ span && [ <integer [1,∞]> || <custom-ident> ] ]`
  - Allow `calc`s for `<integer>`
  - Allow `<custom-ident>`

There is still work to be done to properly use these parsed values.

Gains us 46 WPT tests.
2025-07-08 17:26:16 +01:00
Sam Atkins
b711b01f76 LibWeb/CSS: Remove comment that free space is distributed
Some checks are pending
CI / macOS, arm64, Sanitizer_CI, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers_CI, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer_CI, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer_CI, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Corresponds to 24c1b60e9a
2025-07-08 10:24:49 +01:00
Aliaksandr Kalenik
9e232a70c3 LibWeb: Allow descendant boxes to contribute in overflow rect of parent
Some checks are pending
CI / macOS, arm64, Sanitizer_CI, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers_CI, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer_CI, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer_CI, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
...with inline children. This fixes an issue when we ignore abspos boxes
contained by PaintableWithLines while calculating overflow rect size.

Lots of layout tests are affected, because now PaintableWithLines has
overflow rect.

`Text/input/DOM/Element-set-scroll-left.html` is also affected and now
matches other browsers.
2025-07-06 17:10:18 +02:00
Jelle Raaijmakers
22dacde2c5 LibWeb: Simplify break loop condition in LineBuilder
No functional changes.
2025-07-05 23:56:42 +01:00
Callum Law
9ab7c5d08d LibWeb: Support relative lengths in calc color values
Gains us ~40 WPT tests.
2025-07-04 13:18:55 +01:00
Callum Law
62d138ebf7 LibWeb: Allow passing a resolution context to CSSStyleValue::to_color
This will be used for resolving any calculated style values within the
various `CSSColorValue` sub-classes.

No functionality changes.
2025-07-04 13:18:55 +01:00
Gingeh
863092afdc LibWeb: Don't crash with non-<col> table-column 2025-07-01 11:18:14 +02:00
Tim Ledbetter
d7bdbeb446 LibWeb: Disable ligatures if text-rendering is set to optimizeSpeed
If `font-variant-ligatures` is set to `normal` and `text-rendering` is
set to `optimizeSpeed` then all ligatures are now disabled.
2025-06-27 16:51:30 +01:00
Tim Ledbetter
b4097623e5 LibWeb: Disable font kerning if text-rendering is set to optimizeSpeed
If `font-kerning` is set to `normal` and `text-rendering` is
set to `optimizeSpeed` then kerning is now disabled.
2025-06-27 16:51:30 +01:00
Tim Ledbetter
68035a2b8d LibWeb/CSS: Add the text-rendering property 2025-06-27 16:51:30 +01:00
Tim Ledbetter
a14471b89b LibWeb: Explicitly disable ligatures if font_variant_ligatures is none
Some checks are pending
CI / macOS, arm64, Sanitizer_CI, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers_CI, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer_CI, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer_CI, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
2025-06-27 10:06:20 +02:00
Aliaksandr Kalenik
594194eb60 LibWeb: Skip serialization of implicit grid lines created during layout
Some checks are pending
CI / macOS, arm64, Sanitizer_CI, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers_CI, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer_CI, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer_CI, Clang (push) Waiting to run
Package the js repl as a binary artifact / Linux, arm64 (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
StyleValues created for grid-template-rows and grid-template-columns by
GFC should not include `-start`/`-end` lines implicitly created by grid
areas.
2025-06-25 20:45:48 +02:00
Tim Ledbetter
48f56cad08 LibWeb: Handle non-numeric font-weight values in keyframes
Previously, using `font-weight` with a keyword or `calc()` value inside
a keyframe rule would cause a crash.
2025-06-25 09:01:56 +02:00
Gingeh
b85a8a23a7 LibWeb: Handle percentage font-size values 2025-06-24 12:42:26 +01:00
Tim Ledbetter
9b6da84fff LibWeb/CSS: Implement the font-kerning property
This sets whether the kerning information stored on the current font is
used.
2025-06-23 13:26:48 +01:00
Aliaksandr Kalenik
4ed9f6fcc0 LibWeb: Collapse auto-fit tracks in middle of tracks definition [GFC]
Some checks are pending
CI / macOS, arm64, Sanitizer_CI, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers_CI, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer_CI, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer_CI, Clang (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
`collapse_auto_fit_tracks_if_needed()` had a check that does collapsing
only if auto-fit is used like
`grid-template-columns: repeat(auto-fit, 1px);`, and it didn't work for
valid cases when `repeat(auto-fit)` is placed in the middle of
definition like `grid-template-columns: 1px repeat(auto-fit, 1px) 1px;`.
2025-06-23 02:29:45 +02:00
Aliaksandr Kalenik
c333d0876c LibWeb: Simplify resolve_definite_track_size() [GFC] 2025-06-23 02:29:45 +02:00
Aliaksandr Kalenik
b315e80142 LibWeb: Don't use get_free_space() to count auto-fill/fit tracks [GFC]
Spec says that definite grid container size should be used as free space
so there's no need to use `get_free_space()` that does iteration over
tracks and subtracts definite sizes from available space.
2025-06-23 02:29:45 +02:00
Aliaksandr Kalenik
e6dabdcebe LibWeb: Serialize grid line names in GridFormattingContext
`getComputedStyle()` for grid tracks returns style value produced during
layout. This is needed to return resolved track sizes values which are
thrown away after layout is done. Now GFC produces more correct style
value by not ignoring grid line names.
2025-06-21 22:07:08 +02:00
Aliaksandr Kalenik
af602b2555 LibWeb: Align CSS Grid properties parsing with the specification
Reimplements `grid`, `grid-template`, `grid-template-rows`, and
`grid-template-columns` in a way that uses a separate function for each
grammar rule defined in the specification. This change results in many
additional passing tests from the already imported WPT suite. Most of
the remaining test failures are related to incorrect serialization of
grid properties.
2025-06-21 22:07:08 +02:00
Jelle Raaijmakers
30efcd0d00 LibWeb: Prevent time-traveling leading inline metrics
Some checks are pending
CI / macOS, arm64, Sanitizer_CI, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers_CI, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer_CI, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer_CI, Clang (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
In `InlineLevelIterator`, whenever we call `skip_to_next()` and enter a
node with box model metrics, we could potentially accumulate leading and
trailing metrics. This lead to a weird situation where an element with
`display: inline-block` could adopt the leading metrics of an inline
element that follows it, since we perform the call to
`add_extra_box_model_metrics_to_item()` too late.

Move `skip_to_next()` down so it no longer interferes with the `Item`
we're creating.

The test expectation for
`atomic-inline-with-percentage-vertical-align.html` is updated, although
neither the old nor new results are 100% accurate since either box jumps
one pixel to the right.
2025-06-20 19:59:32 +02:00
Sam Atkins
2c7310553a LibWeb/Layout: Reuse create_pseudo_element_if_needed() for ::backdrop 2025-06-19 12:35:31 +01:00
Sam Atkins
9c656dd7d1 LibWeb/Layout: Only apply ::before/::after creation rules to them 2025-06-19 12:35:31 +01:00
Sam Atkins
c1d4323cf7 LibWeb: Support counter-* properties on pseudo-elements
There are multiple things happening here which are interconnected:

- We now use AbstractElement to refer to the source of a counter, which
  means we also need to pass that around to compute `content`.

- Give AbstractElement new helper methods that are needed by
  CountersSet, so it doesn't have to care whether it's dealing with a
  true Element or PseudoElement.

- The CountersSet algorithms now walk the layout tree instead of DOM
  tree, so TreeBuilder needs to wait until the layout node exists
  before it resolves counters for it.

- Resolve counters when creating a pseudo-element's layout node. We
  awkwardly compute the `content` value up to twice: Once to figure out
  what kind of node we need to make, and then if it's a string, we do
  so again after counters are resolved so we can get the true value of
  any `counter()` functions. This will need adjusting in the future but
  it works for now.
2025-06-19 12:35:31 +01:00
Sam Atkins
a6df9e1bac LibWeb/Layout: Store computed style for ::marker
This lets us refer to its properties later, for example to resolve its
counters.
2025-06-19 12:35:31 +01:00
Sam Atkins
23520509cc LibWeb/Layout: Expose which pseudo-element a node was generated for 2025-06-19 12:35:31 +01:00
Sam Atkins
dfce9974b5 LibWeb: Remove GeneratedPseudoElement enum
This doesn't currently provide any value over just using PseudoElement,
and makes it harder to work with PseudoElement in other places.
2025-06-19 12:35:31 +01:00
Sam Atkins
a57595faf5 LibWeb: Make [resolve,inherit]_counters() take AbstractElement
This is one of those cases where the spec says "element" and
means "element or pseudo-element". The easiest way to handle both is to
make these be free functions that take an AbstractElement, and then
give AbstractElement some helper methods so that the caller doesn't
have to care which it's dealing with.

There are some FIXMEs here because PseudoElement doesn't have a
CountersSet yet, and because the CountersSet currently uses a
UniqueNodeID to identify counter sources, which doesn't support
pseudo-elements.
2025-06-19 12:35:31 +01:00
Aliaksandr Kalenik
6169e91994 LibWeb: Delete redundant GridFitContent class from track representation
GridSize already supports the FitContent type, so there is no need to
additionally wrap it in a GridFitContent class.
2025-06-18 15:51:10 +01:00
Tim Ledbetter
e0af205d69 LibWeb/CSS: Implement the empty-cells property
This property sets whether table borders and backgrounds are painted
if a given table cell has no visible content.
2025-06-18 14:55:03 +01:00
Jelle Raaijmakers
46a46a1c61 LibGfx+LibWeb: Append glyphs in LineBoxFragment run more efficiently
Some checks are pending
CI / macOS, arm64, Sanitizer_CI, Clang (push) Waiting to run
CI / Linux, x86_64, Fuzzers_CI, Clang (push) Waiting to run
CI / Linux, x86_64, Sanitizer_CI, GNU (push) Waiting to run
CI / Linux, x86_64, Sanitizer_CI, Clang (push) Waiting to run
Package the js repl as a binary artifact / macOS, arm64 (push) Waiting to run
Package the js repl as a binary artifact / Linux, x86_64 (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Since we know the number of glyphs we're going to append, ensure the
LineBoxFragment run's capacity once and perform unchecked appends.
2025-06-17 17:03:33 +02:00
Jelle Raaijmakers
c91718148d LibWeb: Undo curious case of line wrapping 2025-06-17 17:03:33 +02:00
Jelle Raaijmakers
4a514020e0 LibWeb: Remove unused include from InlineLevelIterator 2025-06-17 17:03:33 +02:00
Jelle Raaijmakers
1871843acb LibWeb: Reformat Node/PaintableBox::has_css_transform()
Slightly more visually pleasing. No functional changes.
2025-06-17 11:55:28 +02:00