Commit graph

233 commits

Author SHA1 Message Date
Andreas Kling
181fc6cead LibWeb: Pack flex container from opposite end in *-reverse directions 2022-10-04 09:42:17 +02:00
Andreas Kling
b13a8706e1 LibWeb: Make intrinsic heights dependent on available width
After speaking with fantasai at CSSWG about this, it turns out I had
misunderstood intrinsic heights. I originally believed all intrinsic
sizes had to be computed with no influence from the surrounding context.

As it turns out, intrinsic heights *are* influenced by the available
width, since it's needed to determine where lines break.

The APIs for calculating min-content and max-content heights now take
the available width as inputs. This instantly improves layout in many
cases where we'd previously make things way too wide.
2022-10-03 23:49:23 +02:00
Andreas Kling
9c44634ca5 LibWeb: Reorganize layout algorithms around available space
This is a big and messy change, and here's the gist:

- AvaliableSpace is now 2x AvailableSize (width and height)

- Layout algorithms are redesigned around the idea of available space

- When doing layout across nested formatting contexts, the parent
  context tells the child context how much space is available for the
  child's root box in both axes.

- "Available space" replaces "containing block width" in most places.

- The width and height in a box's UsedValues are considered to be
  definite after they're assigned to. Marking something as having
  definite size is no longer a separate step,

This probably introduces various regressions, but the big win here is
that our layout system now works with available space, just like the
specs are written. Fixing issues will be much easier going forward,
since you don't need to do nearly as much conversion from "spec logic"
to "LibWeb logic" as you previously did.
2022-10-02 21:14:02 +02:00
Andreas Kling
d64a8c3d2a LibWeb: Resolve cross-axis flex item margins in the common case 2022-09-29 20:09:52 +02:00
Andreas Kling
9e4226f353 LibWeb: Create flex items for empty generated boxes
I couldn't find anything in the specs about this, but GMail uses
empty generated boxes (`::before` and `::after` with `content: ""`)
inside a flexbox container in order to vertically center things.

The flexbox spec tells us to not generate flex items for empty
*anonymous* boxes, so we continue not doing that, but generated boxes
(any pseudo-element box) now always produce a flex item. This probably
isn't perfect either, and we'll have to revisit it for stuff like
`::first-letter`.
2022-09-29 20:09:49 +02:00
Andreas Kling
f161e20e57 LibWeb: Make FormattingContext::run() take available space as input
Instead of formatting contexts flailing around to figure out from the
"inside" how much space is available on the "outside", we should
provide the amount of available space in both axes as an input to run().

This basically means that when something creates a nested formatting
context, the parent context is responsible for telling the nested context
how much space is available for layout. This information is provided
immediately when invoking run().

Note that this commit doesn't pass accurate values in all cases yet.
This first step just makes it build, and passes available values in some
cases where getting them was trivial.
2022-09-29 18:33:41 +02:00
Andreas Kling
0843960235 LibWeb: Use CSS::Size for computed size and max-size values
This patch changes the *computed* representation of the following CSS
properties to use CSS::Size:

- width, min-width, max-width
- height, min-height, max-height

A few things had to change in order for things to keep working,
but I tried to keep the diff to a minimum.

The main trouble was that `min-width` and `max-width` can't actually be
`auto`, but they *can* be `none`. We previously treated `auto` as a
valid value (and it behaved mostly like `none`).
2022-09-25 17:51:43 +02:00
Andreas Kling
416fa7bd4f LibWeb: Bring flex basis calculation a little closer to spec
This ends up having a big impact on performance, as we now correctly
treat a used flex-basis of `content` as `max-content` which means
we can use cacheable intrinsic sizes for flex items in the majority
of cases.
2022-09-24 14:09:56 +02:00
Andreas Kling
a8e1599ae1 LibWeb: Use automatic_content_height() in flex item internal layouts 2022-09-24 13:47:58 +02:00
Andreas Kling
62974160da LibWeb: Add FormattingContext::automatic_content_height()
This function should return the automatic height of the formatting
context's root box.

Until now, we've been relying on some magical handshakes between parent
and child context, when negotiating the height of child context root
boxes. This is a step towards something more reasonable.
2022-09-24 13:41:08 +02:00
sin-ack
e9d5d2f74b LibWeb: Remove the flex item size cache
This was overly permissive as the FIXME stated and was causing layout
issues.
2022-09-18 18:55:06 +02:00
Andreas Kling
97b5230413 LibWeb: Subtract border & padding when using flex line size as item size
The flex line cross size includes the margin boxes of items, so when
we're taking the flex line's cross size to use as an item cross size,
we have to subtract the margin, border padding from both sides.

Previous we only subtracted the cross margins, which led to oversized
items in some cases.
2022-09-18 18:34:42 +02:00
Andreas Kling
7bf3b40867 LibWeb: Remove bogus main space restriction in wrapping flex layouts 2022-09-18 18:34:42 +02:00
Ben Wiederhake
8deced39a8 LibWeb: Resolve cyclic declaration/definitions involving Length
This remained undetected for a long time as HeaderCheck is disabled by
default. This commit makes the following file compile again:

    // file: compile_me.cpp
    #include <LibWeb/CSS/GridTrackSize.h>
    // That's it, this was enough to cause a compilation error.
2022-09-15 14:45:38 +01:00
Andreas Kling
f25203f245 LibWeb: Don't re-resolve "auto" flex item sizes after definitizing them
This is rather subtle and points to our architecture around definite
sizes not being exactly right, but...

At some points during flexbox layout, the spec tells us that the sizes
of certain flex items are considered definite from this point on.
We implement this by marking each item's associated UsedValues as
"has-definite-width/height".

However, this breaks code that tries to resolve computed "auto" sizes
by taking the corresponding size from the containing block. The end
result was that the 1st sizing pass in flexbox would find the right size
for an "auto" sized item, but the 2nd pass would override the correct
size with the containing block's content size in that axis instead.

To work around the issue, FFC now remembers when it "definitizes" an
item, and future attempts to resolve an "auto" computed size for that
value will bypass the computed-auto-is-resolved-against-containing-block
step of the algorithm. It's not perfect, and we'll need to think more
about how to really represent these intermediate states relating to
box sizes being definite..
2022-09-14 14:43:17 +02:00
Andreas Kling
b8aa6a4453 LibWeb: Use PercentageOr<T>::contains_percentage() in CSS layout
By asking if the value *contains* a percentage rather than whether it
*is* one, we cover many more cases where e.g `width: calc(100% - 10px)`
should be "treated as auto" etc.
2022-09-14 14:43:17 +02:00
Andreas Kling
a42506c8b9 LibWeb: Fix three accidental float truncations
We were doing this:

    max(0, some_floating_point_value)

This returns an `int` result based on the type of `0`, oops!
2022-09-07 17:47:33 +02:00
Andreas Kling
e65990f7a3 LibWeb: Treat cyclic percentage max-size as "auto" on the flex container
This allows things like `max-width: 100%` to work on flex containers
whose containing blocks themselves have automatic width.
2022-08-27 12:19:37 +02:00
watkinsr
35dbeb064a LibWeb: Render flex line items RTL (reversed items) for FlexEnd
This is a basic attempt at trying to handle parent container case
justify-content: flex-end.

Test-scenario:
Head to https://ryanwatkins.me and note that now the header nav is on
the right as opposed to the left in-line with how Chrome/Firefox would
respectively handle it also, i.e. 'flex-end'

Implementation:
Move cursor to the end and render in reverse backwards shifting the
cursor leftwards.
2022-08-16 09:55:49 +01:00
Andreas Kling
0258fd8043 LibWeb: Remove FFC helpers is_{main,cross}_axis_margin_first_auto()
We already cache these values with each flex item, so let's just use
those instead.
2022-07-26 01:53:41 +02:00
Andreas Kling
71ec46b8cc LibWeb: Don't treat calc() in used flex basis as definite for now
We'll eventually need some way to determine if a calc() value results
in a definite size.
2022-07-26 01:53:41 +02:00
Andreas Kling
7200b3a16c LibWeb: Make two passes in FFC where to support percentage min/max sizes
Percentage sizes of flex items are relative to the flex container, but
even when the flex container is automatically sized, we still have to
support them.

To make this work, we first do a pass where percentage sizes are ignored
(treated as "auto", basically) in order to get a "reference" value.

Then we do a second pass where percentages can be resolved against this
reference value.
2022-07-26 01:53:41 +02:00
Andreas Kling
3def9e47f6 LibWeb: Improve min/max content contribution calculations for flex items
Follow the spec more closely.
2022-07-26 01:53:41 +02:00
Andreas Kling
4c89252f6a LibWeb: Clamp flex items to min/max main size during intrinsic sizing
We were neglecting to clamp flex items when calculating the intrinsic
main size of the flex container. This was covered by a FIXME, which we
can now remove. :^)
2022-07-26 01:53:41 +02:00
Andreas Kling
dc66a3cad9 LibWeb: Simplify flex container main size determination
We had an older incomplete implementation of flex container max-content
sizing that we used for unconstrained main size determination.

This patch replaces the old implementation with a call to the new
max-content sizing code.

Note that this isn't a complete implementation of flex container sizing
still, but at least we've deduplicated some code.
2022-07-26 01:53:41 +02:00
Andreas Kling
18b1854aea LibWeb: Add FFC helpers for getting the computed main/cross size of box 2022-07-26 01:53:41 +02:00
Andreas Kling
a4d7dc40bf LibWeb: Move get_pixel_{width,height} helpers into FFC class 2022-07-26 01:53:41 +02:00
Andreas Kling
60ac258a48 LibWeb: Mark flex item cross sizes as definite when spec asks us to
The CSS-FLEXBOX-1 spec gives us two situations in which flex item cross
sizes should be considered definite. Both of them happen *during* flex
layout, which is super finicky but it is what it is.
2022-07-26 01:53:41 +02:00
Andreas Kling
97f53de8a2 LibWeb: Take size constraints into account in fit-content calculations
Also avoid calculating both min-content and max-content sizes when only
one of them is needed.
2022-07-26 01:53:41 +02:00
Andreas Kling
8f35c9a037 LibWeb: Resolve flexbox percent heights against containing block height
Percentage values for `min-height` and `max-height` should be resolved
against the containing block height, not its width.
2022-07-26 01:53:41 +02:00
Andreas Kling
4cbec00c44 LibWeb: Actually check if percentage used flex basis is definite
Previously, we considered all LengthPercentage values for used flex
basis to be definite. This is not accurate, as percentages should only
be considered definite if the reference value they resolve against is
a definite size.

Fix this by checking the flex container's main definite size flag.
2022-07-26 01:53:41 +02:00
Andreas Kling
8bdc6f5390 LibWeb: Don't override main size during flex item cross sizing
There's no need to override the sizes before calculating the cross size.

Besides, by the time we're calculating the hypothetical cross size of
flex items, we may already have established a definite main size anyway,
so overriding it would be wrong.
2022-07-26 01:53:41 +02:00
Andreas Kling
69243947d5 LibWeb: Some flex items have definite size after flexing
This patch implements two of the special "definite size" rules from
the CSS-FLEXBOX-1 spec.

https://drafts.csswg.org/css-flexbox-1/#definite-sizes
2022-07-26 01:53:41 +02:00
Andreas Kling
71a707480c LibWeb: Move "has-definite-width/height" flags to UsedValues
This state is less static than we originally assumed, and there are
special formatting context-specific rules that say certain sizes are
definite in special circumstances.

To be able to support this, we move the has-definite-size flags from
the layout node to the UsedValues struct instead.
2022-07-26 01:53:41 +02:00
Andreas Kling
bd48d9521a LibWeb: Simplify more code with CSS::LengthPercentage::is_auto() 2022-07-26 00:04:21 +02:00
Andreas Kling
fac4529082 LibWeb: Honor flex container sizing constraints in available space 2022-07-25 15:03:18 +02:00
Andreas Kling
050e70cc7e LibWeb: Position abspos children of flex container after parent layout
If we wait until after the parent context has laid out the flex
container, abspos children are able to use the final results of the
parent sizing the flex container.

This makes `height:auto` work on abspos children of a flex container.
2022-07-25 15:03:18 +02:00
Andreas Kling
7aa9e03e85 LibWeb: Simplify some code with CSS::LengthPercentage::is_auto() 2022-07-25 15:03:18 +02:00
Andreas Kling
3145f92bc0 LibWeb: Count flex item's *outer* size towards container intrinsic size
This isn't in the spec, but it's visually obvious that we need to count
item margin boxes towards the main intrinsic size of the flex container.
2022-07-25 15:03:18 +02:00
Andreas Kling
237fbe4d54 LibWeb: Remember the used flex basis for each flex item
This will be consulted later on in the flex layout algorithm.
2022-07-21 01:46:26 +02:00
Andreas Kling
b7003194d2 LibWeb: Use right offset for justify-content: flex-end
Offsets in this algorithm are relative to the starting position, so it
should be 0 whether its `flex-start` or `flex-end`.
2022-07-21 01:46:25 +02:00
Andreas Kling
da0cc9d401 LibWeb: Floor hypothetical main size at 0
The spec asks us to do this. It doesn't become relevant until we
implement box-sizing, but might as well do it anyway.
2022-07-21 01:46:25 +02:00
Andreas Kling
ed8930fff5 LibWeb: Add accessors for UsedValues::computed_{width,height}
This is preparation for doing some more work when assigning to these
values.
2022-07-19 15:40:41 +02:00
Andreas Kling
c517dfde12 LibWeb: Honor the flexbox spec's "automatic minimum size" everywhere
`min-width: auto` and `min-height: auto` have special behavior on flex
items. We already handled it in many cases but there were two places
where it was incorrectly treated as 0. This fixes that.
2022-07-19 12:45:50 +02:00
Andreas Kling
52862c72d0 LibWeb: Rename FormattingState to LayoutState
This seems a bit more descriptive (and also a bit shorter).
2022-07-17 14:11:36 +02:00
Andreas Kling
0d8f9019c8 LibWeb: Implement basic stretch alignment for flex-wrap: wrap
We currently ignore the `align-content` property, that's a FIXME
for our future selves.
2022-07-17 14:11:36 +02:00
Andreas Kling
9fc43d5766 LibWeb: Update flex container intrinsic size algorithm to draft spec
The CSSWG draft Flexbox spec is a bit clearer on some details, so let's
update our implementation to match the latest version.
2022-07-17 14:11:36 +02:00
Andreas Kling
884b7fad48 LibWeb: Remove weird is_undefined_or_auto() helper in FFC
This was a leftover from when ComputedValues stored sizes in Optionals.
Now that we've gotten rid of the "undefined" state, there's no need for
this helper, we can just access the size values directly.
2022-07-15 14:11:19 +02:00
Andreas Kling
0636e1db61 LibWeb: Update flex line "remaining free space" when finished
Since we re-use this value later in the layout algorithm, we have to
update it before leaving the "resolve flexible lengths" step.
2022-07-15 14:11:19 +02:00
Andreas Kling
7d7d5f0b1b LibWeb: Use fit-content size for flex items with indefinite cross size 2022-07-12 23:12:11 +02:00