Commit graph

190 commits

Author SHA1 Message Date
Jelle Raaijmakers
9e9db9a9dd LibWeb: Store correct text offsets in PaintableFragment
Previously, we were collapsing whitespace in Layout::TextNode and then
passed the resulting string for further processing through ChunkIterator
-> InlineLevelIterator -> InlineFormattingContext -> LineBuilder ->
LineBoxFragment -> PaintableFragment. Our painting tree is where we deal
with things like range offsets into the underlying text nodes, but since
we modified the original string, the offsets were wrong.

This changes the way we generate fragments:

  * Layout::TextNode no longer collapses whitespace as part of its
    stored "text for rendering", but moves this logic to ChunkIterator
    which splits up this text into separate views whenever whitespace
    needs to be collapsed.

  * Layout::LineBox now only extends the last fragment if its end offset
    is equal to the new fragment's start offset. Otherwise, there's a
    gap caused by collapsing whitespace and we need to generate a
    separate fragment for that in order to have a correct start offset.

Some tests need new baselines because of the fixed start offsets.

Fixes #566.
2025-09-12 15:34:09 -04:00
Aliaksandr Kalenik
e2eb8716e5 LibWeb: Fix incorrect margin collapsing behavior [BFC]
This change removes premature reset of
`block_container_y_position_update_callback`. Also makes callback
private in `BlockMarginState`, because resetting it independently of
currently accumulated margins is incorrect.

Lots of test expectations are updated, but there is no visual
difference.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/6074
2025-09-08 14:09:06 +02:00
Aliaksandr Kalenik
87c7fb1d63 LibWeb: Use 0 as min-content size for items with overflow:hidden [GFC]
This behavior is not specified but required to match other browsers.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/5907
2025-08-30 15:57:45 +02:00
Jelle Raaijmakers
f4b04beccd LibWeb: Show inline positioning in layout tree dump
Inline nodes in our layout tree have a position, so let's show it. By
centralizing the logic for this, block nodes now lose their redundant
'content-size' dump info which is already part of the box model dump.
2025-08-27 11:53:45 +01:00
Jelle Raaijmakers
e173b00db6 LibWeb: Always show box model info when dumping layout tree
This is useful information. Let's not hide it.
2025-08-27 11:53:45 +01:00
Aliaksandr Kalenik
d94b33e205 LibWeb: Handle correctly case when abspos and relpos GFC is interleaved
...by another GFC. When searching for grid item that contains an
abspos box positioned relative to GFC, it's incorrect to assume that the
closest ancestor box whose parent establishes GFC is always the one we
are looking for, because there may be non-positioned GFC in between.

Fixes regression introduced in 80c8e78.
2025-08-19 09:28:45 +02:00
Aliaksandr Kalenik
80c8e787a8 LibWeb: Fix abspos layout when box is contained by grid area
Before this change, `layout_absolutely_positioned_element()` in GFC
had an assumption that all contained by grid container abspos boxes were
also direct children of the grid container. This change adds handling
for the cases when it's not true and, in order to identify grid area
abspos box belongs to, we have to find ancestor grid item.
2025-08-17 17:58:16 +02:00
Aliaksandr Kalenik
4d223462a5 LibWeb: Fix cyclic percentage resolution in calculate_min_content_width
Brings back some code removed in 652a457, but this time with explanation
from https://www.w3.org/TR/css-sizing-3 spec.
2025-08-13 10:14:37 +01:00
Aliaksandr Kalenik
652a457f52 LibWeb: Fix grid layout for replaced items with percentage max-width
CSS grid specification states that for grid items with a replaced
element and a percentage preferred size or maximum size, the percentage
should be resolved against 0 during content-based minimum size
calculation. This makes sense, as it prevents replaced items from
overshooting their grid track while intrinsic track sizes are
calculated, and allows later track size resolution steps to scale
replaced items to fit their grid track.
2025-08-10 11:07:02 +02:00
Aliaksandr Kalenik
e3aa3016bf LibWeb: Correctly calculate grid item size while accommodating fr track
Implements text from grid layout specification.
Improves layout on https://cal.com/
2025-08-06 22:42:07 +02:00
Jelle Raaijmakers
edca2ab666 LibWeb: Do not create an anonymous container for table cells by default
We were always creating an anonymous container for the inline contents
of table cells, but the layout node we spawn for the table cells
themselves already is capable of dealing with inline nodes. Regular
logic should kick in for dealing with the block/inline node invariant.
2025-07-15 10:06:36 +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
Andreas Kling
dab1fd265d test-web: Dump stacking context tree in layout test output
This will allow us to test (and catch regressions in) stacking context
tree construction and updates, etc.
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
Psychpsyo
c0e44820e9 Tests: Add doctypes to remaining test cases 2025-06-21 14:09:47 +02:00
aplefull
3781c132aa LibWeb: Fix grid item placement when only grid-column-end is specified 2025-06-03 22:22:24 +02:00
Psychpsyo
c105f99547 Meta: Add doctypes to all grid layout tests 2025-05-13 03:49:32 +03:00
Jelle Raaijmakers
71665fa504 LibWeb: Scale font size by 1.15 for line-height: normal
Browsers such as Chrome and Firefox apply an arbitrary scale to the
current font size if `normal` is used for `line-height`. Firefox uses
1.2 while Chrome uses 1.15. Let's go with the latter for now, it's
relatively easy to change if we ever want to go back on that decision.

This also requires updating the expectations for a lot of layout tests.
The upside of this is that it's a bit easier to compare our layout
results to other browsers', especially Chrome.
2025-05-05 13:15:56 +02:00
Lukas Scheller
852e8ff12f LibWeb: Fix grid placement with named lines 2025-04-05 21:30:37 +02:00
Aliaksandr Kalenik
d8ff71fbb5 LibWeb: Delete parent state pointer in LayoutState
It's safe to remove this pointer because intrinsic layout should never
look up a box's state beyond its containing block.

This change affects the expectations of two layout tests, but both
already differ slightly from other browsers, and the difference between
expectations is less than 5px.
2025-03-26 12:08:09 +00:00
Aliaksandr Kalenik
090ac66af1 LibWeb: Repeat grid track sizing with minmax where both are not definite
...should be treated as invalid value.
2025-03-25 09:53:04 +00:00
Aliaksandr Kalenik
057e643a63 LibWeb: Don't assume length-percentage is always a length [GFC]
Fixes crashing when trying to get length from LengthPercentage with
percentage value.
2025-03-24 18:59:21 +01:00
Aliaksandr Kalenik
1f8e7c3cca LibWeb/Layout: Improve grid item sizing for replaced boxes
With this change we no longer stretch "width: auto" for replaced
elements and also use "width calculation rules for block-level replaced
elements", like suggested by the spec.
2025-03-20 03:36:56 +01:00
Aliaksandr Kalenik
4a7b947c5d LibWeb: Clamp content-based minimum size by limited max track size [GFC]
Progress on https://wpt.live/css/css-grid/grid-items/grid-minimum-size-grid-items-022.html
2025-03-18 15:01:02 +01:00
Aliaksandr Kalenik
23151de217 LibWeb/Layout: Fix min{max}-content size calculation for grid items
Instead of directly invoking `to_px()`,
`calculate_min_content_contribution()` needs to use
`calculate_inner_width()` and `calculate_inner_height()`, which are
aware of how to correctly handle `min-content` and `max-content` values.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/3469
2025-03-15 13:51:16 +01:00
Aliaksandr Kalenik
08c155cd3f LibWeb: Resolve "height: auto" using preferred aspect ratio if possible
Fixes https://github.com/LadybirdBrowser/ladybird/issues/2276
2025-03-15 13:51:16 +01:00
Andreas Kling
7d4d7da28a LibWeb: Wrap inline children of table-cell in anonymous block
This fixes an issue where CSS vertical-align on a table-cell box would
incorrectly apply to both the table-cell box and any inline content it
had inside.
2025-02-25 23:55:36 +01:00
Andreas Kling
16662ab230 LibWeb: Account for collapsed top margins in BFC root height calculation
By the time we're measuring the height of a BFC root, we've already
collapsed all relevant margins for the root and its descendants.
Given this, we should simply use 0 (relative to the BFC root) as the
lowest block axis coordinate (i.e Y value) for the margin edges.

This fixes a long-standing issue where BFC roots were sometimes not tall
enough to contain their children due to margins.
2025-02-22 18:41:42 +01:00
Jelle Raaijmakers
4d9f17eddf LibGfx+LibWeb: Draw glyph runs with subpixel accuracy
This improves the quality of our font rendering, especially when
animations are involved. Relevant changes:

  * Skia fonts have their subpixel flag set, which means that individual
    glyphs are rendered at subpixel offsets causing glyph runs as a
    whole to look better.

  * Fragment offsets are no longer rounded to whole device pixels, and
    instead the floating point offset is kept. This allows us to pass
    through the floating point baseline position all the way to the Skia
    calls, which already expected that to be a float position.

The `scrollable-contains-table.html` ref test needed different table
headings since they would slightly inflate the column size in the test
file, but not the reference.
2024-12-21 23:09:52 +01:00
Aliaksandr Kalenik
bfdf52701f LibWeb: Treat min{max}-height as none if available is intrinsic [GFC]
Fixes infinite recursion in following cases:
- max-height: fit-content
- max-height: min-content
- max-height: max-content
2024-12-03 23:10:08 +01:00
Psychpsyo
1d44df74f7 LibWeb: Stop zero-area children from causing scrollable overflow 2024-11-24 11:10:47 +01:00
Aliaksandr Kalenik
a8c1d12e84 LibWeb: Fix percentage insets resolution for grid items
compute_inset() was incorrectly retrieving the containing block size
because containing_block() is unaware of grid areas that form a
containing block for grid items but do not exist in the layout tree.
With this change, we explicitly pass the containing block into
compute_inset(), allowing it to correctly provide the containing block
sizes for grid items.
2024-11-11 20:20:39 +01:00
Gingeh
6862d33e7c LibWeb: Don't crash from clipping grid spans 2024-11-11 00:57:10 +01:00
Aliaksandr Kalenik
e95226839e LibWeb: Fix infinite recursion when max-width is min/max-content in GFC
Treat max-width as auto when it's specified to min/max-content and
available size is intrinsic constraint.

Fixes stack overflow on https://claude.ai/
2024-10-30 08:47:52 +01:00
Edward Banner
912511a152 LibWeb: Use containing block to compute scrollable overflow
Instead of using child boxes to compute scrollable overflow for the box,
we use descendants which have the box as their containing block.
2024-10-18 15:26:42 +02:00
Edward Banner
03569fc509 LibWeb: Fix table overflow issues
- Include vertical border spacing in row group offset calculation so
  that they are axis-aligned with child row/cell elements. This makes it
  so there isn't horizontal and vertical overflow caused by child
  row/cell elements.
- Include horizontal border spacing in tr width calculations. This makes
  it so tr elements don't have overflow anymore when there are multiple
  columns.
- Apply vertical caption offset to row group top offset.
- Don't double-count top padding when calculating vertical offset for
  tr and row groups.
2024-10-14 17:30:17 +01:00
Aliaksandr Kalenik
0dec2dc21c LibWeb: Improve grid area calculation for abspos items in GFC
- Add support for placement of abspos items into track formed by last
  line and padding edge of grid container
- Correctly handle auto-positioned abspos items by placing them between
  padding edges of grid container

Fixes crashing on https://wpt.live/css/css-grid/abspos/positioned-grid-descendants-001.html
2024-10-11 09:08:46 +02:00
Neil Viloria
9e2b70661e LibWeb/Layout: Unify grid justify-content handling for grid area 2024-10-10 13:37:08 +02:00
Neil Viloria
b9e7c6a2f6 LibWeb/Layout: Implement align-content for grid layout 2024-10-08 21:30:03 +02:00
Neil Viloria
4bda65c8b3 LibWeb/Layout: Implement justify-content for column spacing in grid 2024-10-05 19:21:49 +02:00
Aliaksandr Kalenik
91b2cd7d31 LibWeb: Account for x-axis in static position for inline items
..and delay static position calculation in IFC until trailing
whitespace are removed, because otherwise it's not possible to correctly
calculate x offset.
2024-09-21 20:10:49 +02:00
Aliaksandr Kalenik
19afc5b11b LibWeb: Align to padding edge only auto positioned abspos grid items
Containing block for abspos grid items depends on their grid placement:
- if element has definite grid position, then corresponding grid area
  should be used as a containing block
- if element does not have definite grid position, then padding edge of
  grid container should be used as a containing block

So offset should be adjusted for paddings only for boxes without
definite grid position.
2024-09-21 20:10:49 +02:00
Aliaksandr Kalenik
5f74da6ae8 LibWeb: Fix "box-sizing: border-box" resolution for abspos items
The `calculate_inner_width()` and `calculate_inner_height()` resolve
percentage paddings using the width returned by
`containing_block_width_for()`. However, this function does not account
for grids where the containing block is defined by the grid area to
which an item belongs.

This change fixes the issue by modifying `calculate_inner_width()` and
`calculate_inner_height()` to use the already resolved paddings from the
layout state. Corresponding changes ensure that paddings are resolved
and saved in the state before box-sizing is handled.

As a side effect, this change also improves abspos layout for BFC where
now paddings are resolved using padding box of containing block instead
of content box of containing block.
2024-09-17 07:56:18 +02:00
Aliaksandr Kalenik
805b0fed13 LibWeb: Use grid area size for abspos grid items alignment
Fixes yet another case of GFC bug, where Node::containing_block() should
not be used for grid items, because their containing block is grid area
which is not represented in layout tree.
2024-09-17 07:51:50 +02:00
Aliaksandr Kalenik
6481ef821d LibWeb: Use available size in calculate_inner_height()
Although the parameter is named "available size," it is always supposed
to represent the containing block size whenever it has a definite value.
Therefore, it is possible to simply use this value instead of performing
a containing block lookup.

This change actually improves correctness for grid items whose
containing block is defined by the grid area, as
`Node::containing_block()` does not account for this.
2024-09-15 18:00:08 +02:00
Aliaksandr Kalenik
de3c007d79 LibWeb: Fix min-width and max-width resolution for grid items
Change try_compute_width() to check whether min-width/max-width or width
is auto instead of always using `computed_values.width()`.

`grid/min-max-content.html` test is affected but it's progression.
2024-09-13 11:59:51 +02:00
Aliaksandr Kalenik
a64d182583 LibWeb: Use grid area as available size for abspos contained in GFC
Fixes incorrect percentage length resolution for abspos boxes contained
by a grid.
2024-09-12 21:07:41 +02:00
Aliaksandr Kalenik
863416e3ac LibWeb: Make FC of containing block responsible for abspos layout
Before this change, a formatting context was responsible for layout of
absolutely positioned boxes whose FC root box was their parent (either
directly or indirectly). This only worked correctly when the containing
block of the absolutely positioned child did not escape the FC root.
This is because the width and height of an absolutely positioned box are
resolved based on the size of its containing block, so we needed to
ensure that the containing block's layout was completed before laying
out an absolutely positioned box.

With this change, the layout of absolutely positioned boxes is delayed
until the FC responsible for the containing block's layout is complete.
This has affected the way we calculate the static position. It is no
longer possible to ask the FC for a box's static position, as this FC's
state might be gone by the time the layout for absolutely positioned
elements occurs. Instead, the "static position rectangle" (a concept
from the spec) is saved in the layout state, along with information on
how to align the box within this rectangle when its width and height are
resolved.
2024-09-12 07:36:32 +02:00
Gingeh
1d30d84f41 LibWeb: Add tests for justify-*: left/right 2024-09-10 10:40:07 +01:00
Aliaksandr Kalenik
ee41dbfec3 LibWeb: Fix wrong assumption that repeat() is always first track [GFC]
Fixes crashing in
https://wpt.live/css/css-grid/grid-definition/grid-auto-fit-columns-001.html
2024-09-09 22:05:30 +02:00