Commit Graph

151 Commits

Author SHA1 Message Date
Tim Ledbetter
6b3d3468a1 LibWeb: Account for <col> span attribute during table grid formation
Previously, the column count was always incremented by 1. This led to a
mismatch with `compute_outer_content_sizes()`, which did use the `span`
attribute to advance the column index. This mismatch caused an
out-of-bounds access when the column index was greater than the
expected number of columns.
2026-02-24 12:14:54 +01:00
Tim Ledbetter
83bd30b957 LibWeb: Stop inline elements after table-cell being swallowed into table
The `is_ignorable_whitespace()` check in table fixup traverses anonymous
block wrappers to see if they contain only whitespace. It rejected
out-of-flow and text descendants but silently skipped in-flow non-text
elements like `<span>`, misclassifying wrappers with real content as
ignorable and absorbing them into the table structure.
2026-02-21 05:48:53 +00: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
Tim Ledbetter
66e9e2de4b LibWeb: Account for table padding in intrinsic table width calculation 2026-02-11 09:39:11 +01:00
Tim Ledbetter
0b346d1952 LibWeb: Distribute colspan cell width equally when baseline is zero
This matches the behavior of other engines.
2026-02-06 11:37:14 +00:00
Tim Ledbetter
04ec4c0256 LibWeb: Resolve horizontal box model metrics for table captions
Previously, horizontal padding, border, and margin were not being
resolved for table captions. This was visible in layout tests where
captions with padding showed 0 in the width metrics.
2026-02-03 14:47:51 +01:00
Tim Ledbetter
7d6ce58cf2 LibWeb: Constrain table caption available space to table's border-box
Previously, table captions were laid out using the parent's available
space before the table's width was calculated. This resulted in
captions not being properly constrained to the table's width.
2026-02-03 14:47: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
c9108a2ad5 LibWeb: Only set has_scrollable_overflow for scroll containers
Previously, has_scrollable_overflow was a purely geometric check, true
whenever content extended beyond the padding box regardless of the
overflow property. This caused unnecessary scroll frame allocation for
boxes with `overflow:visible`.

Per CSS Overflow 3, scrollable overflow is only defined for scroll
containers (overflow: auto/hidden/scroll). Gate the flag on
`is_scroll_container()` so that only actual scroll containers get scroll
frames assigned.
2026-01-29 14:59:32 +01:00
Jelle Raaijmakers
6a29b8cc03 LibWeb: Derive inline-block baseline from nested content
Compute inline-block baselines by traversing into nested block children
to find the last in-flow line box, using correct offsets relative to the
margin box edge.

Also ensure inline-flex and inline-grid containers always derive their
baseline from content (per CSS Align), and add special handling for
<input> elements which have `overflow: clip` in the UA stylesheet but
should still align adjacent text with their internal content.
2026-01-22 19:36:09 +01:00
Jelle Raaijmakers
d597bba5cf LibWeb: Align anonymous table-cell flex/grid wrappers to top
Vertical-align padding should not apply to anonymous table-cells that
wrap a flex/grid container, as the container handles its own alignment.
2026-01-21 23:44:23 +01:00
Psychpsyo
5c67ea640a LibWeb: Propagate overflow to viewport more correctly 2025-12-15 09:47:25 +00:00
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
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
Andreas Kling
3d97251da3 LibWeb: Wrap out-of-flow table children in anonymous table cells
This fixes an issue where floating children of a table box would not get
laid out at all if they were surrounded by nothing but whitespace.
2025-08-25 14:55:19 +02:00
Jelle Raaijmakers
f530ea5f7e Tests: Rename button test to something sensible
This had nothing to do with table cells.
2025-08-19 11:12:23 +02:00
Jelle Raaijmakers
b56d4e9bab Tests: Rebaseline Layout/input/table/th-default-text-align.html
Needed after edca2ab666.
2025-07-15 11:21:14 +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
9f7447f546 LibWeb: Prioritize inheriting text-align for <th>
Because we defined `th { text-align: center }` in our UA stylesheet, it
received a higher precedence than inherited (inline) styles. Firefox
deals with this by defining a custom `text-align` value that prioritizes
any inherited value before defaulting to `text-align: center`.

We now do this as well :^)
2025-07-15 10:05:48 +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
9e232a70c3 LibWeb: Allow descendant boxes to contribute in overflow rect of parent
...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
c03210e858 LibWeb: Dump PaintableBox dimensions for inline layout nodes
We were only dumping a PaintableBox' dimensions if its layout node was a
Layout::Box as well, causing us to not dump the dimensions of paintables
for inline nodes in the paintable tree.
2025-07-03 22:16:48 +02: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
Psychpsyo
3fd13485ab Meta: Add doctypes to all table layout tests 2025-05-04 11:23:17 +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
Andreas Kling
47f5da7523 LibWeb: Actually, don't align all inline content to alphabetic baseline
This essentially reverts 1b46a52cfc
and adds more tests.

The reverted change was an incorrect workaround for the real issue,
which was that we weren't creating anonymous wrapper boxes around inline
children of table-cell boxes.

Now that this has been fixed, we can go back to aligning text properly.
2025-02-25 23:55:36 +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
stasoid
a90b7026fb LibWeb/Layout: Account for box-sizing in table width/height calculations
Fixes #1726

Fixes
wpt/css/CSS2/abspos/abspos-containing-block-initial-004c.xht
wpt/css/CSS2/abspos/abspos-containing-block-initial-004d.xht
wpt/css/CSS2/abspos/abspos-containing-block-initial-005b.xht
wpt/css/CSS2/abspos/abspos-containing-block-initial-005d.xht
2024-11-29 15:43:59 +01:00
Hermes Junior
5dabd468ed LibWeb: Fix out-of-bound crash when there's more table cells than cols
Added a getter to ensure we are within a valid range.
This behavior is accepted by other browsers,
and crashed on some pages.
2024-11-06 09:36:33 +00:00
Gingeh
d1b967bca5 LibWeb: Consider every row when calculating table width 2024-11-05 10:58:11 +00: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
Aliaksandr Kalenik
6a549f6270 LibWeb: Replace InlinePaintable with PaintableWithLines created per line
InlinePaintable was an ad-hoc paintable type required to support the
fragmentation of inline nodes across multiple lines. It existed because
there was no way to associate multiple paintables with a single layout
node. This resulted in a lot of duplicated code between PaintableBox and
InlinePaintable. For example, most of the CSS properties like
background, border, shadows, etc. and hit-testing are almost identical
for both of them. However, the code had to be duplicated to account for
the fact that InlinePaintable creates a box for each line. And we had
quite many places that operate on paintables with a code like:
```
if (box.is_paintable_box()) {
  // do something
} else (box.is_inline_paintable()) {
  // do exactly the same as for paintable box but using InlinePaintable
}
```

This change replaces the usage of `InlinePaintable` with
`PaintableWithLines` created for each line, which is now possible
because we support having multiple paintables per layout node. By doing
that, we remove lots of duplicated code and bring our implementation
closer to the spec.
2024-10-16 20:25: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
Tim Ledbetter
140dc95e67 LibWeb: Map dimension attributes for table elements 2024-10-02 09:50:54 +02:00
Aliaksandr Kalenik
9621439db0 LibWeb: Assign static position for abspos boxes nested into TFC
TFC is not aware of how to correctly calculate a static position for
abspos boxes, but assigning (0, 0) is better than crashing during abspos
item layout.

Fixes https://github.com/LadybirdBrowser/ladybird/issues/1382
2024-09-14 15:04:08 +02:00
BenJilks
0d63269cb7 LibGfx+LibWeb: Use harfbuzz for text shaping
This replaces glyph positioning system with harfbuzz's shaping
algorithm. Adding support for bidirectional encoded text.
2024-08-16 22:28:34 +02:00
BenJilks
963cf1c2c4 LibWeb: Add additional padding to the end of the scrollable overflow
Adds additional padding to the end-side of the scrollable overflow
rectangle as necessary to enable a scroll position that satisfies
the requirements of `place-content: end` alignment.
2024-08-02 08:07:56 +02:00
Sam Atkins
9e32c9329a LibWeb: Reserve enough space for span>1 columns in BorderConflictFinder
This code previously only allocated enough space in
m_col_elements_by_index for 1 slot per column, meaning that columns
with a span > 1 would write off the end of it.
2024-07-27 20:23:14 +01:00
BenJilks
3c897e7cf3 LibWeb: Propagate margin and offset when computing a box's baseline
When traversing the layout tree to find an appropriate box child to
derive the baseline from. Only the child's margin and offset was being
applied. Now we sum each offset on the recursive call.
2024-07-15 21:31:51 +02:00
Andreas Kling
34f2cbf202 LibWeb: Honor intrinsic constraints on available space in table widths
When a table's containing block provides min-content or max-content
available space, we now size the table's width accordingly.
2024-05-01 11:13:48 +02:00
Aliaksandr Kalenik
7b75d0c1f0 LibWeb: Fix height distribution in "vertical-align: baseline" in TFC
This line changes padding top to align cell content to baseline:
`cell.padding_top += m_rows[cell.row_index].baseline - cell.baseline`

Which means available for distribution height `height_diff` could have
changed so it needs to be refreshed before assigning the rest of it to
padding bottom:
`cell_state.padding_bottom += height_diff;`

Fixes https://github.com/SerenityOS/serenity/issues/22032
2024-04-19 10:55:28 +02:00
implicitfield
0243278587 LibWeb: Account for absolutely positioned table wrappers
Table wrappers don't quite behave the same as most elements, in that
their computed height and width are not meant to be used for layout.
Instead, we now calculate suitable widths and heights based on the
contents of the table wrapper when performing absolute layout.

Fixes the layout of
http://wpt.live/css/css-position/position-absolute-center-007.html
2024-03-07 08:09:04 +01:00
implicitfield
b08fd1b9ae LibWeb: Improve support for 'vertical-align: middle'
This rebaselines a few table-related layout tests since our default
stylesheet applies 'vertical-align: middle' to a few table-related
elements.
2024-02-28 16:11:05 -05:00
Aliaksandr Kalenik
2960bf4ec8 LibWeb: Make inline paintables own their fragments
The paintable tree structure more closely matches the painting order
when fragments are owned by corresponding inline paintables. This
change does not affect the layout tree, as it is more convenient for
layout purposes to have all fragments owned by a block container in
one place.

Additionally, this improves performance significantly on pages with
many fragments, as we no longer have to walk the ancestor chain up
to the closest block container to determine if a fragment belongs
to an inline paintable.
2024-01-13 18:46:41 +01:00
Aliaksandr Kalenik
de32b77ceb LibWeb: Use separate structure to represent fragments in paintable tree
This is a part of refactoring towards making the paintable tree
independent of the layout tree. Now, instead of transferring text
fragments from the layout tree to the paintable tree during the layout
commit phase, we allocate separate PaintableFragments that contain only
the information necessary for painting. Doing this also allows us to
get rid LineBoxes, as they are used only during layout.
2024-01-13 10:53:38 +01:00
Andreas Kling
e7de5cb4d2 LibWeb: Bring CSS line-height closer to other engines
This patch makes a few changes to the way we calculate line-height:

- `line-height: normal` is now resolved using metrics from the used
  font (specifically, round(A + D + lineGap)).

- `line-height: calc(...)` is now resolved at style compute time.

- `line-height` values are now absolutized at style compute time.

As a consequence of the above, we no longer need to walk the DOM
ancestor chain looking for line-heights during style computation.
Instead, values are inherited, resolved and absolutized locally.

This is not only much faster, but also makes our line-height metrics
match those of other engines like Gecko and Blink.
2024-01-12 15:04:06 +01:00