1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-20 06:15:06 +00:00
Commit graph

1122 commits

Author SHA1 Message Date
Andreas Kling
31fc1990fa LibWeb: Set up both containing block sizes before intrinsic sizing
When calculating e.g the min-content height of some box, we would only
set its containing block's height to 0 in the temporary formatting
state. The containing block width was not touched at all.

This patch aims to do a bit better by resolving indefinite containing
block sizes to INFINITY before performing intrinsic sizing. We should
probably also find a way to resolve definite containing block sizes,
but I'll leave that for our future selves.
2022-07-12 02:46:21 +02:00
Andreas Kling
c81e5c9d82 LibWeb: Floor scaled flex shrink factor at 1 when spec asks us to 2022-07-12 02:46:21 +02:00
Andreas Kling
6ecf7db87b LibWeb: Take margin box into account when justifying flex items
Before this patch, we were justifying based on the content box only,
which led to misalignments along the main axis when items had non-zero
padding, borders or margins.
2022-07-12 02:46:21 +02:00
Andreas Kling
96c9ca502b LibWeb: Add safety mechanism to guard against non-finite layout sizes
Due to some yet-to-be-found bug(s) in intrinsic sizing, we can sometimes
end up deciding that some box has a non-finite intrinsic size.

This will create unpleasant results, and may lead to some layout
algorithms looping infinitely, so this patch adds a safeguard where
we simply turn non-finite intrinsic sizes into zero (and complain a
little bit in the debug log.)
2022-07-12 02:46:21 +02:00
Andreas Kling
2f0657739b LibWeb: Honor align-self over align-items when non-auto on flex item 2022-07-12 02:46:21 +02:00
Andreas Kling
4493702fb2 LibWeb: Honor preferred size as intrinsic cross size of flex items
I'm not 100% sure this is on-spec, but it seems to me that flex items
that have a specified non-auto cross size should honor that value in
its min-content and max-contribution.
2022-07-11 18:57:45 +02:00
Andreas Kling
9cae06de09 LibWeb: Implement step 9.2.3 of the flexbox layout algorithm
When sizing the flex container under a min-content or a max-content
constraint, flex items with a used flex basis of "content" should be
sized under the same constraint.
2022-07-11 18:57:45 +02:00
Andreas Kling
0cacaf025d LibWeb: Stop putting the FormattingState nodes in a slow hash map
Instead, put them in a Vector<OwnPtr<NodeState>>. Each layout node
has a unique index into the vector. It's a simple serial ID assigned
during layout tree construction. Every new layout restarts the sequence
at 0 for the next ICB.

This is a huge layout speed improvement on all content.
2022-07-11 18:57:45 +02:00
Andreas Kling
327938c945 LibWeb: Bring sizing of replaced elements closer to spec
We were prematurely resolving the computed size values, which meant
that `auto` values were swallowed before we could resolve them via
the intrinsic aspect ratio (if present)
2022-07-11 18:57:45 +02:00
Andreas Kling
17a6fcfde3 LibWeb: Try to work out the intrinsic size of <svg> elements
If the `width` and `height` attributes are provided, we derive the
intrinsic size and ratio from them.

Otherwise, we trace a rectangle around the geometry elements inside
the SVG and use the size of that as the intrinsic size.

This is definitely far from correct, but is still a much better guess
at the intrinsic size than nothing.
2022-07-11 18:57:45 +02:00
Andreas Kling
7dfd5afd37 LibWeb: Set 1:1 intrinsic aspect ratio for radio buttons 2022-07-11 18:57:45 +02:00
Andreas Kling
557006f5be LibWeb: Cache reference to <svg> element in SVGFormattingContext 2022-07-11 18:57:45 +02:00
Andreas Kling
e1dab7b63d LibWeb: Use the *outer* flex base size in intrinsic size calculation 2022-07-11 18:57:45 +02:00
Andreas Kling
aee3d79ad1 LibWeb: Use the "scaled flex shrink factor" where noted by the spec 2022-07-11 18:57:45 +02:00
Andreas Kling
f7750985fa LibWeb: Treat "flex-basis: 0px" like any other definite basis value 2022-07-11 18:57:45 +02:00
Andreas Kling
61c27815e4 LibWeb: More specialization of intrinsic sizing layout
This patch adds a separate entry point for this kind of layout.
We override it in BFC to set up initial width/height values for the
BFC root block.

Resulting dimensions are assigned as content_width and content_height
at the end of intrinsic sizing, for each axis, if it's either "auto"
or there's a min-content or max-content constraint in effect.
2022-07-11 18:57:45 +02:00
Andreas Kling
28eec22c83 LibWeb: Don't iterate over text content inside replaced elements
This fixes an issue where whitespace inside embedded <svg> elements
would create unexpected whitespace text content on the page.

When combined with something like `white-space: pre-wrap`, it ended
up generating a lot of surprising vertical offsets.
2022-07-11 18:57:45 +02:00
Andreas Kling
7b4a86ab80 LibWeb: Use max-content main size for flex items w/ definite cross size
If the main size is indefinite, that is.
2022-07-11 18:57:45 +02:00
Andreas Kling
e78282aebb LibWeb: Make sure we always apply size constraints in IFC
Pre-compute the effective containing block width in the IFC constructor
and use that throughout.
2022-07-11 18:57:45 +02:00
Andreas Kling
7713198e9c LibWeb: Cache a pointer to the containing block state in IFC 2022-07-11 18:57:45 +02:00
Andreas Kling
9784a567d2 LibWeb: Factor out BFC "layout this block-level box" to a function 2022-07-11 18:57:45 +02:00
Andreas Kling
64959a8504 LibWeb: Express intrinsic size layout via size constraints
Previously, we had three layout modes:

- Normal:
    - Everything uses the computed values from CSS.

- MinContent:
    - Containing blocks act as if they have 0 width.
    - All line breaking opportunities are taken.

- MaxContent:
    - Containing blocks act as if they have infinite width.
    - Only forced line breaks are accepted.

The above was based on a set of misunderstandings of CSS sizing.
A major problem with the above was that *all* containing blocks
behaved differently during intrinsic size layout, not just the
relevant one.

With this patch there are only two layout modes:

- Normal:
    - Everything uses the computed values from CSS.

- IntrinsicSizeDetermination:
    - One or more boxes have size constraints applied.

There are two size constraints per layout box, set here:

- FormattingState::NodeState::width_constraint
- FormattingState::NodeState::height_constraint

They are of type SizeConstraint and can be one of None, MinContent,
or MaxContent. The default is None.

When performing an IntrinsicSizeDetermination layout, we now assign
a size constraint to the box we're trying to determine the intrinsic
size of, which is then honored by using two new helpers to query
the dimensions of containing blocks:

- FormattingContext::containing_block_width_for(Box)
- FormattingContext::containing_block_height_for(Box)

If there's a relevant constraint in effect on the Box, the size of
its containing block is adjusted accordingly.

This is essentially an implementation of the "available space"
constraints from CSS-SIZING-3. I'm sure some things will break from
this, and we'll have to deal with that separately.

Spec: https://drafts.csswg.org/css-sizing-3/#available
2022-07-11 18:57:45 +02:00
Andreas Kling
66d08d2417 LibWeb: Move IFC result measurement from IFC to BFC
Before this change, IFC would first generate all of its line boxes
and then measure them. It would then write some of the values into
the state of the IFC's containing block.

We now move that up to BFC::layout_inline_children() instead, which
is a much more natural place to decide metrics for the block.
2022-07-11 18:57:45 +02:00
Andreas Kling
fd68be29ab LibWeb: Make BFC always drive IFC
Instead of allowing FormattingContext to instantiate an IFC for anything
that has inline children, move this logic to BFC.

This is fine, since only BFC deals with blocks having inline children
anyway.
2022-07-11 18:57:45 +02:00
Andreas Kling
db2d62671f LibWeb: Add FFC helpers for getting intrinsic size of flex items 2022-07-11 18:57:45 +02:00
Andreas Kling
4f6fc3d3a6 LibWeb: Only perform the requested form of intrinsic size calculation
Before, querying any of the four intrinsic sizes would cause us to
calculate all of them (the four being min-content width/height, and
max-content width/height).

Now, the helper functions only calculate the specific intrinsic size
requested. It's then cached at the root formatting context level,
so that it's never calculated twice within the same layout pass.
2022-07-11 18:57:44 +02:00
Andreas Kling
496cf39cf5 LibWeb: Make separate functions for calculating min/max content sizes
At first, these are just wrappers around calculate_intrinsic_sizes().
Eventually, we'll make them do only the work necessary for their
specific size.
2022-07-11 18:57:44 +02:00
Andreas Kling
1690d88887 LibWeb: Clamp intrinsic flex item main size contributions to min/max 2022-07-11 18:57:44 +02:00
Andreas Kling
89e65e0ea1 LibWeb: Support flex item cross sizing based on intrinsic aspect ratio
This patch implements case B from the "determine the flex base size
and hypothetical main size of each item" from the flexbox algorithm.

https://drafts.csswg.org/css-flexbox-1/#algo-main-item
2022-07-10 00:47:46 +02:00
Andreas Kling
8eb022a57d LibWeb: Don't include flex line margins in inner flex item cross sizes
In cases where flex item cross size is based on the flex line cross
size, the spec specifically says to transfer the *outer* cross size of
the line. We were ignoring the "outer" part.

This patch fixes that by subtracting the cross margins from the size.
2022-07-10 00:04:41 +02:00
Andreas Kling
030dbfd2a9 LibWeb: Improve support for flex-start/end with reversed flex-direction
We now pass the "flex-direction" test from the CSSWG flexbox test suite.
2022-07-10 00:04:41 +02:00
Andreas Kling
cefc931347 LibWeb: Make sure CSS::ComputedValues has initial size values
Instead of using Optional<LengthPercentage>, we now use LengthPercentage
for these values. The initial values are all `auto`.

This avoids having to check `has_value()` in a ton of places.
2022-07-09 22:16:35 +02:00
MacDue
61a703816c LibWeb: Base marker size on font height rather than line height
This fixes the oversized markers on GitHub
2022-07-09 09:28:31 +01:00
Andreas Kling
8abbbdf6fa LibWeb: Cache a pointer to the IFC root in InlineLevelIterator 2022-07-06 20:31:27 +02:00
Andreas Kling
4935055407 LibWeb: Keep the "remaining free space" across flexbox algo steps
Instead of recomputing the "remaining free space" per flex line,
remember it after calculating it during the "resolve flexible lengths"
step so we can reuse it later.
2022-07-06 20:31:24 +02:00
Andreas Kling
83a6be593c LibWeb: Add a 1-entry lookup cache to FormattingState
This makes repeated lookups of the state for the same box much faster
by bypassing the HashMap.
2022-07-06 20:31:22 +02:00
Andreas Kling
d2b7d2440f LibWeb: Cache flex item main sizes to avoid relayout during same cycle
This makes twitter.com actually load & render (although not very well.)
2022-07-06 00:22:42 +02:00
Andreas Kling
13b4d91f66 LibWeb: Always apply min/max cross size constraints to flex items
We were neglecting to apply min-size and max-size constraints in the
fast path for flex items with a definite cross size.
2022-07-04 22:30:59 +02:00
Andreas Kling
7953bd8391 LibWeb: Implement "transferred size suggestion" for flex items 2022-06-22 18:36:17 +02:00
Andreas Kling
75e8b1305d LibWeb: Actually distribute free space to flex items with auto margins
We were not applying the distributed space to the used offset of flex
items, as we were only assigning the margins to the layout state of the
box, not the internal FlexItem::margins.
2022-06-21 21:18:00 +02:00
Andreas Kling
99e96f951f LibWeb: Implement (some of) "automatic minimum size" for flex items 2022-06-21 21:06:19 +02:00
Andreas Kling
967b257518 LibWeb: Make FFC prepare replaced child boxes for layout
Before we ask a replaced box about its intrinsic dimensions, we have
to "prepare" the box, which tells it to go and work out what its
intrinsic dimensions are.

I've added a FIXME about how this is silly (and clearly bug-prone)
but this patch only patches it locally in FFC for now.
2022-06-21 20:40:26 +02:00
Andreas Kling
85f2f8ab3f LibWeb: Make sure we layout absolutely positioned children of FFC 2022-06-21 20:17:28 +02:00
MacDue
28c78b45ca LibWeb: Keep both horizontal and vertical border radii till painting 2022-06-13 09:43:45 +01:00
Karol Kosek
a0bea0b86f LibWeb: Calculate floating elements width using min- and max-width
Previously, floating elements computed the width by only using the
`width` property. Now, they will also use the `min-width` and
`max-width` properties. :^)

The new steps are from "10.4. Minimum and maximum widths: 'min-width'
and 'max-width'" in the CSS 2 spec.

Found it when looking at curl.se.
2022-06-06 09:14:42 +01:00
Sam Atkins
7c91fda088 LibWeb: Allow multiple text-decoration-lines
The spec grammar for `text-decoration-line` is:

`none | [ underline || overline || line-through || blink ]`

Which means that it's either `none`, or any combination of the other
values. This patch makes that parse for `text-decoration-line` and
`text-decoration`, stores the results as a Vector, and adjusts
`paint_text_decoration()` to run as a loop over all the values that are
provided.

As noted, storing a Vector of values is a bit wasteful, as they could be
stored as flags in a single `u8`. But I was getting too confused trying
to do that in a nice way.
2022-04-14 21:54:10 +02:00
Sam Atkins
e941f07931 LibWeb: Make StyleProperties::property() always return a value
By the time that property() gets called, we've already given every
single property a value, so we can just return it. This simplifies a
lot of places that were manually handling a lack of value
unnecessarily.
2022-04-14 14:54:06 +02:00
Sam Atkins
a797a92990 LibWeb: Stop including StyleValue.h in a few places
I don't know how much this will actually help compile times, but it's
something!
2022-04-14 14:54:06 +02:00
Sam Atkins
4d42885327 LibWeb: Return Optional from StyleProperties::box_sizing()
This function was written as if it returned `Optional<CSS::BoxSizing>`
but actually returned a plain `CSS::BoxSizing`, meaning if the property
was not set or was invalid, it would return whichever enum value was
first. This wasn't visible because we don't yet pay any attention to
the `box-sizing` property.
2022-04-14 14:54:06 +02:00
Andreas Kling
6712bbc0ee LibWeb: Tidy up Layout::TreeBuilder ancestor stack a little bit
- Make it a vector of references since we never put null pointers on
  the ancestor stack.

- Use Vector::in_reverse() to iterate backwards.
2022-04-13 19:52:25 +02:00