Commit graph

322 commits

Author SHA1 Message Date
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
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
Aliaksandr Kalenik
4eb16b144e LibWeb: Skip abspos boxes layout in intrinsic sizing mode
Some checks are pending
CI / Lagom (false, NO_FUZZ, macos-14, macOS, Clang) (push) Waiting to run
CI / Lagom (false, NO_FUZZ, ubuntu-22.04, Linux, GNU) (push) Waiting to run
CI / Lagom (true, NO_FUZZ, ubuntu-22.04, Linux, Clang) (push) Waiting to run
CI / Lagom (false, FUZZ, ubuntu-22.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (macos-14, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (ubuntu-22.04, Linux, 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
Push notes / build (push) Waiting to run
Absolutely positioned boxes do not affect the size of the formatting
context box they belong to, so it's safe to skip their layout entirely
when calculating intrinsic size.
2024-09-11 07:59:52 +02:00
Aliaksandr Kalenik
90b8bfc04c LibWeb: Save layout mode inside formatting context object
FormattingContext::run() does not allow reentrancy, so it's safe to
save and access layout mode from FC object. This avoids need to drill it
through methods of a formatting context and makes it clear that this
value could never be changed after FC construction.
2024-09-11 07:59:52 +02:00
Aliaksandr Kalenik
623e358d7a LibWeb: Remove box argument from FormattingContext::run()
Root formatting context box is passed into constructor and saved in FC,
so it's possible to access it from there instead of passing the same
box into run().
2024-09-11 07:59:52 +02:00
Gingeh
4a3a9e6ec4 LibWeb: Implement justify-*: left/right 2024-09-10 10:40:07 +01:00
BenJilks
46649fbe1b LibWeb: Add support for flex-wrap: wrap-reverse
Reverse the order of flex lines, when the `flex-wrap` property is set to
`wrap-reverse`. This will also swap the cross-start and cross-end
directions.
2024-09-02 17:42:11 +02:00
BenJilks
e2c1fe7255 LibWeb: Only reverse each line of a reverse flex-direction
When a flex container with a reverse `flex-direction` is wrapped. Only
each line should be reversed, not all items.
2024-09-02 17:42:11 +02:00
Andreas Kling
bde2d3dc7b LibWeb: Adjust flex item intrinsic contributions through aspect ratio
When determining the intrinsic cross size contribution of a flex item
with a preferred aspect ratio, we have to account for any min/max
constraints in the main axis.
2024-08-21 13:38:39 +02:00
BenJilks
82989554ab LibWeb: Use reverse direction on flex containers with rtl direction
If a flex container has `direction: rtl` set, reverse the row direction.
2024-08-13 15:19:51 +01:00
Jelle Raaijmakers
7a783d3a89 LibWeb: Account for intrinsic width or height in flex base size
In calculating the base size of a flex item, we have a piece of ad-hoc
code that deals with an item that does have an instrinsic aspect ratio,
but not a cross size to resolve that ratio against. In determining the
actual flex item size however, we also take into account the minimum
content width and height, which assumes the box' intrinsic width or
height when available. This would break having an image as a flex item,
which gets stretched to its maximum size within the flex container
instead of the flex item being shrunk to the instrinsic size of the
image.

Fix this by only stretching flex items that do not have an instrinsic
width nor height set.
2024-08-09 17:01:50 +01:00
Jelle Raaijmakers
d82f8a4b16 LibWeb: Update two spec URIs
No functional changes.
2024-08-09 17:01:50 +01:00
Jelle Raaijmakers
89d21335a1 LibWeb: Remove unused includes
No functional changes.
2024-08-09 17:01:50 +01:00
Edwin Hoksberg
de84e6f93a LibWeb: Move css_clamp function to FormattingContext
Since we need it in the FlexFormattingContext and
GridFormatting context now.
2024-07-25 13:12:26 +02:00
BenJilks
47aee289d8 LibWeb: Change flex remaining space distribution to include gap
The remaining space is in addition to, not of in place of the
main gap.
2024-07-05 21:31:41 +02:00
Andreas Kling
db1faef786 LibWeb: Fix overeager fallback to stretch-fit width for some flex items
If a flex item has a preferred aspect ratio and the flex basis is not
definite, we were falling back to using stretch-fit for the main size,
since that appeared to match other browsers.

However, we missed the case where we actually have a definite cross size
through which the preferred aspect ratio can be naturally resolved.
2024-06-23 19:15:24 +02:00
Andreas Kling
9c02ace897 LibWeb: Allow flex-basis: {min,max,fit}-content 2024-06-23 19:15:24 +02:00
Tim Ledbetter
c57d395a48 LibWeb: Use IterationDecision in single level Node iteration methods
`Node::for_each_child()` and `Node::for_each_child_of_type()` callbacks
now return an `IterationDecision`, which allows us to break early if
required.
2024-05-07 16:45:28 -06:00
Andreas Kling
d37c0a2cab LibWeb: Don't make flex layout responsible for flex container cross size
Although the flex algorithm as specified does say to determine the cross
size of the flex container, this is not how our layout engine works.

The parent formatting context is responsible for sizing its children,
and since that's already happening, we can simply remove the cross
sizing step from FFC.
2024-03-27 16:43:04 +01:00
implicitfield
54d8e58a68 LibWeb: Account for margin and padding of justified abspos flex items 2024-03-09 16:02:17 +01:00
implicitfield
3888a91c5b LibWeb: Account for margin and padding of aligned abspos flex items
This patch also makes FlexFormattingContext::calculate_static_position
use computed values for margins and borders, since this function may be
called before the box's state has been finalized.
2024-03-09 16:02:17 +01:00
Andreas Kling
a61f09a010 LibWeb: Stretch-fit flex items with aspect ratio but no fixed sizes
This solves a particular issue with SVG as flex items, where the SVG has
an intrinsic aspect ratio via its viewBox, but no explicit natural width
or height.

Makes all corporate sponsor logos show up on https://ziglang.org/ :^)
2024-02-25 14:06:06 +01:00
Andreas Kling
b079f4d590 LibWeb: Make flexbox special definite size cases explicit
The CSS-FLEXBOX-1 spec has a bunch of special cases where sizes are
considered definite after reaching a specific point of the layout
algorithm.

Before this change, we were relying on set_content_width/height also
implicitly marking those content sizes as definite.

To prepare for that implicit behavior going away, this patch makes
the special cases explicit.
2024-02-21 17:54:05 +01:00
Andreas Kling
1583e6ce07 LibWeb: Clamp justification space between flex items to 0
Before this change, it was possible for flex lines with negative
remaining space (due to overflowing items) to put a negative amount
of space between items for some values of `justify-content`.

This makes https://polar.sh/SerenityOS look much better :^)
2024-01-25 15:10:21 +01:00
Andreas Kling
7fedf806c2 LibWeb: Cache pointer to UsedValues for each FlexItem
This avoids expensive repeated LayoutState hash lookups.
2024-01-24 07:53:33 +01:00
Bastian Neumann
7cd489d6aa LibWeb: Remove early continue in size parsing
Step 5 of parsing was always skipped because step 4 continues.

Running step 5 causes some of the denominators to be 0 and causes
divide by zero error in CSSPixelFraction.

SVG Image with height of 0 will cause divide by zero error when
calculating intrinsic aspect ratio of SVGDecoderImageData.

We also get a divide by zero error in AlignContent::SpaceBetween of the
FlexFormatingContext.

During auto track stretching in GridFormatingContext there is a
possibility for count_of_auto_max_sizing_tracks to stay 0.
2024-01-20 15:22:25 +01:00
Andreas Kling
2d50dee920 LibWeb: Use correct max-size in intrinsic sizing of column flex layout
Regressed in 72dd37438d
2024-01-16 13:14:00 +01:00
Andreas Kling
72dd37438d LibWeb: Treat flex item cross axis max-size as "none" in more cases
There are a bunch of situations where we need to treat cross axis
max-size properties as "none", notably percentage values when the
reference containing block size is an intrinsic sizing constraint.

This fixes an issue where flex items with definite width would get
shrunk to 0px by "max-width: 100%" in case the item itself is an
SVG with no natural width or height.

For consistency, we now use the should_treat_max_width/height_as_none
helpers throughout FFC.

This makes the search/account/cart icons show up in the top right
on https://twinings.co.uk :^)
2024-01-15 12:55:47 +01:00
Andreas Kling
bfa4143e70 LibWeb: Avoid an unnecessary LayoutState lookup in FlexFormattingContext
The containing block of a flex item is always formed by the flex
container, duh. :^)
2024-01-13 14:34:39 +01:00
Andreas Kling
5af02a914c LibWeb: Let parent formatting context determine size of flex containers
Until now, we had implemented flex container sizing by awkwardly doing
exactly what the spec said (basically having FFC size the container)
despite that not really making sense in the big picture. (Parent
formatting contexts should be responsible for sizing and placing their
children)

This patch moves us away from the Flexbox spec text a little bit, by
removing the logic for sizing the flex container in FFC, and instead
making sure that all formatting contexts can set both width and height
of flex container children.

This required changes in BFC and IFC, but it's actually quite simple!
Width was already not a problem, and it turns out height isn't either,
since the automatic height of a flex container is max-content.
With this in mind, we can simply determine the height of flex containers
before transferring control to FFC, and everything flows nicely.

With this change, we can remove all the virtuals and FFC logic for
negotiating container size with the parent formatting context.
We also don't need the "available space for flex container" stuff
anymore either, so that's gone as well.

There are some minor diffs in layout test results from this, but the
new results actually match other browsers more closely, so that's fine.

This should make flex layout, and indeed layout in general, easier to
understand, since this was the main weird special case outside of
BFC/IFC where a formatting context delegates work to its parent instead
of the other way around. :^)
2024-01-10 16:28:12 +01:00
Andreas Kling
aa245f9f18 LibWeb: Fix reverse flex layout with justify-content: normal
Before this change, we used the wrong insertion point for flex items
in reverse layouts with `justify-content: normal`. This caused flex
items to overflow the flex containers "backwards" from the start edge.
2024-01-08 14:42:19 +01:00
Aliaksandr Kalenik
39abd9095e LibWeb: Return CSSPixels from calculate_inner_height()
Similar to calculate_inner_width(), let's make the caller responsible
for handling "auto" instead of returning the input height as is when
when it cannot be resolved.
2024-01-07 09:03:57 +01:00
Aliaksandr Kalenik
05a1dbeb91 LibWeb: Return CSSPixels from calculate_inner_width()
Initially, this function was made to return CSS::Length because some of
its callers were expecting it to ignore "auto" width on input and
return it as is. Instead, let's just forbid using "auto" for input
width and always return CSSPixels.
2024-01-07 09:03:57 +01:00
Aliaksandr Kalenik
56ff9bffae LibWeb: Support "normal" and "stretch" justify-content in CSS parser 2024-01-04 09:47:20 +01:00
Aliaksandr Kalenik
b395cfccb0 LibWeb: Add support for "align-content: normal" in CSS parser 2024-01-04 09:47:20 +01:00
Andreas Kling
3250a424f0 LibWeb: Don't offset abspos children of flex container by padding twice
We were incorrectly offsetting the static position of abspos children of
flex containers by the padding twice. This was a misguided attempt to
adjust to the abspos containing block being the padding box, not the
content box.

Fixes #21344.
2023-10-08 09:06:30 +02:00
Zaggy1024
34c5043cbe LibWeb: Use CSSPixelFraction to represent aspect ratios
This allows us to retain perfect precision for aspect ratios derived
from either the intrinsic sizes of replaced elements, or the
`aspect-ratio` CSS property.
2023-09-04 12:40:17 +02:00
MacDue
71baa8c31a LibWeb: Add CSSPixels::nearest_value_for(FloatingPoint)
This is intended to annotate conversions from unknown floating-point
values to CSSPixels, and make it more obvious the fp value will be
rounded to the nearest fixed-point value.
2023-08-26 23:53:45 +02:00
MacDue
360c0eb509 LibWeb: Remove implicit conversion from float and double to CSSPixels
In general it is not safe to convert any arbitrary floating-point value
to CSSPixels. CSSPixels has a resolution of 0.015625, which for small
values (e.g. scale factors between 0 and 1), can produce bad results
if converted to CSSPixels then scaled back up. In the worst case values
can underflow to zero and produce incorrect results.
2023-08-26 23:53:45 +02:00
Andreas Kling
90e95d38d7 LibWeb: Make align-items: normal behave like stretch on flex items
CSS-ALIGN-3 tells us that `normal` behavior inside flex containers is
simply to behave as `stretch` so this patch makes them behave the same
inside FFC.

Furthermore, we change the `align-items` initial value to `normal`,
matching other engines.
2023-08-20 19:37:50 +02:00
Aliaksandr Kalenik
e9a718ff88 LibWeb/Layout: Replace INFINITY with CSSPixels::min() or max() 2023-08-17 20:03:13 +02:00
Aliaksandr Kalenik
8b99366b9d LibWeb: Replace to_px() with to_px_or_zero() in FlexFormattingContext
to_px() usage should be avoided because it might leak saturated
(infinite) values into layout calculations.
2023-08-12 20:06:01 +02:00
Aliaksandr Kalenik
e25b1f76e1 LibWeb: Forbid usage of indefinite width in calculate_min{max}_height
Changing `calculate_min_content_heigh()` and
`calculate_min_content_heigh()` to accept width as `CSSPixels`, instead
of `AvailableSize` that might be indefinite, makes it more explicit
that width is supposed to be known by the time height is measured.

This change has a bit of collateral damage which is rows height
calculation regression in `table/inline-table-width` that worked before
by accident.
2023-08-12 16:26:08 +02:00
Andreas Kling
41e7c5766e LibWeb: Support more kinds of indefinite widths on flex column items
This stuff is pretty hairy since the specifications don't give any
guidance on which widths to use when calculating the intrinsic height of
flex items in a column layout.

However, our old behavior of "treat anything indefinite as fit-content"
was definitely not good enough, so this patch improves the situation by
considering values like `min-content`, `max-content` and `fit-content`
separately from `auto`, and making the whole flex layout pipeline aware
of them (in the cross axis context).
2023-08-05 10:58:12 +02:00
Andreas Kling
15440b156f LibWeb: Ignore flex container size constraints during intrinsic sizing
Properties like min-width, max-width, etc, should be ignored while we're
trying to determine the intrinsic size of a flex container.

This fixes an infinite recursion when using an intrinsic size keyword as
the max-width of a flex column container.

Note that this behavior is marked as AD-HOC in code comments because
specs don't tell us how to achieve intrinsic sizing.

We can now load product pages on the Twinings site, such as
https://twinings.co.uk/products/earl-grey-100-tea-bags :^)
2023-08-01 20:15:20 +02:00
PaddiM8
6de701b5c3 LibWeb: Handle auto margins with flex and justify-content
Auto margins used together with justify-content would previously
result in children being positioned outside their parent. This was
solved by letting auto margins take precedence when they are used,
which was already implemented to some extent before, but not
fully.
2023-07-26 08:35:23 +02:00
PaddiM8
a26f2f0aab LibWeb: Handle flex reverse togther with justify-content
Containers with both flex reverse and justify content would
sometimes place children outside the container. This happened
because it assumed any reversed container would have items
aligned to the right, which isn't true when using eg. `flex-end`.

Both `justify-content: start` and `justify-content: end` are now
also independent of the reverseness.
2023-07-26 08:35:23 +02:00
Aliaksandr Kalenik
152ce88984 LibWeb: Avoid leaking infinite remaining_free_space in FFC calculation
After switching to fixed-point arithmetic in CSSPixels, it no longer
supports representing infinite values, which was previously the case
for remaining_free_space in FFC. Using Optional that is not empty only
when value is finite to store remaining_free_space ensures that
infinity is avoided in layout calculations.
2023-07-26 05:17:56 +02:00
Aliaksandr Kalenik
849cf894d8 LibWeb: Fix division by zero in distribute_any_remaining_free_space
This change fixes division by zero in case flex container has
"justify-content: space-between" and only single item.
2023-07-25 14:51:50 +02:00
Aliaksandr Kalenik
bec07d4af7 LibWeb: Use fixed-point saturated arithmetics for CSSPixels
Using fixed-point saturated arithmetics for CSSPixels allows to avoid
accumulating floating-point errors.

This implementation is not complete yet: currently saturated
arithmetics implemented only for addition. But it is enough to not
regress any of layout tests we have :)

See https://github.com/SerenityOS/serenity/issues/18566
2023-07-25 11:52:02 +02:00