Commit graph

209 commits

Author SHA1 Message Date
Andreas Kling
43e1343abf LibWeb: Treat % max-height as none when containing block size indefinite
Fixes #19371
2023-06-14 17:08:15 +02:00
Andreas Kling
b6f3369b66 LibWeb: Fix spelling of non_anonymous_containing_block() 2023-06-14 17:08:15 +02:00
Andreas Kling
41da9a4231 LibWeb: Resolve auto margins on abspos elements in more cases
Specifically, we now handle cases where all three of `left`, `width`
and `right` are non-`auto`.
2023-06-13 17:47:50 +02:00
Andreas Kling
434df52b91 LibWeb: Make stretch-fit return 0 when the available size is indefinite
The spec says the result of this algorithm is undefined in such cases,
and it appears that other engines yield a zero size.

More importantly, this prevents us from leaking a non-finite value into
the layout tree.
2023-06-13 16:14:45 +02:00
Aliaksandr Kalenik
147c3b3d97 LibWeb+WebContent: Forbid access to underlying type of CSSPixels
Although DistinctNumeric, which is supposed to abstract the underlying
type, was used to represent CSSPixels, we have a whole bunch of places
in the layout code that assume CSSPixels::value() returns a
floating-point type. This assumption makes it difficult to replace the
underlying type in CSSPixels with a non-floating type.

To make it easier to transition CSSPixels to fixed-point math, one step
we can take is to prevent access to the underlying type using value()
and instead use explicit conversions with the to_float(), to_double(),
and to_int() methods.
2023-06-13 06:08:27 +02:00
Sam Atkins
1051624084 LibWeb: Obey CSS aspect-ratio property during layout
Calculate a "preferred aspect ratio" based on the value of
`aspect-ratio` and the presence of a natural aspect ratio, and use that
in layout.

This is by no means complete or perfect, but we do now apply the given
aspect-ratio to things.

The spec is a bit vague, just saying to calculate sizes for
aspect-ratio'ed boxes the same as you would for replaced elements. My
naive solution here is to find everywhere we were checking for a
ReplacedBox, and then also accept a regular Box with a preferred aspect
ratio. This gets us pretty far. :^)

https://www.w3.org/TR/css-sizing-4/#aspect-ratio-minimum is not at all
implemented.
2023-06-09 20:37:51 +02:00
Sam Atkins
84e7216603 LibWeb: Move "natural size" concept into Layout::Box
Having this here instead of in ReplacedBox means we can access it when
figuring out what the "preferred aspect ratio" is.

There's some inconsistency between specs about what this is called, but
they're moving towards referring to this as "natural width/height/
aspect-ratio", so let's copy that terminology.
2023-06-09 20:37:51 +02:00
Andreas Kling
3365a1e034 LibWeb: Resolve cyclic % against 0 when available size is min-content
This fixes an issue where replaced elements with cyclic percentage width
would make an oversized min-content contribution to its container.
2023-06-08 13:54:11 +02:00
Andreas Kling
c197fb4037 LibWeb: Take box-sizing into account when sizing replaced elements
This fixes an issue where images with padding and/or border did not have
their size adjusted for `border-box`, thereby becoming larger than
intended by the author.
2023-06-05 09:00:00 +02:00
Andreas Kling
4fed7beb7b LibWeb: Make solve_replaced_size_constraint() into FormattingContext 2023-05-31 11:38:05 +02:00
Andreas Kling
42470d837e LibWeb: Move layout box rect helpers into FormattingContext
These are only used during layout, and always within formatting context
code, so we might as well put them in FormattingContext and avoid having
to pass the LayoutState around all the time.
2023-05-31 11:38:05 +02:00
Andreas Kling
4f08fcde29 LibWeb: Remove unnecessary static formatting context functions
At one point in the past, we had some functions that were called across
different formatting context types, which necessitated making them
static and taking the LayoutState as a parameter.

In all cases, those functions were used to do incorrect hacks, all of
which we've replaced with more correct solutions. :^)
2023-05-31 11:38:05 +02:00
Aliaksandr Kalenik
787f2d2a10 LibWeb: Remove Layout::TableCellBox
Special box types for inner table boxes might conflict with special
types for <button>, <input> or <label>.
2023-05-29 21:36:17 +02:00
Andreas Kling
af004ff0ef LibWeb: Support min-content for width, min-width and max-width
We're gonna need to handle this in many more places, this patch only
adds it to calculate_inner_width().
2023-05-29 21:29:25 +02:00
Andreas Kling
97c510329c LibWeb: Support max-content for width, min-width and max-width
We're gonna need to handle this in many more places, this patch only
adds it to calculate_inner_width().
2023-05-29 21:29:25 +02:00
Aliaksandr Kalenik
258f3ea952 LibWeb: Remove Layout::TableBox
Solves conflict in layout tree "type system" when elements <label> (or
<button>) can't have `display: table` because Box can't be
Layout::Label (or Layout::ButtonBox) and Layout::TableBox at the same
time.
2023-05-29 14:12:29 +02:00
Andreas Kling
1bb4e5c428 LibWeb: Support fit-content width for block-level boxes 2023-05-27 05:47:54 +02:00
Andreas Kling
299775345d LibWeb: Allow calculating intrinsic sizes of non-FC-roots
In order to support intrinsic size keywords (such as fit-content), we
need to be able to calculate the intrinsic sizes of any element, not
just those that form their own formatting context.

When a non-FC-root element is passed to calculate_some_intrinsic_size(),
we now create a synthetic BFC to handle sizing of them.
2023-05-27 05:47:54 +02:00
Andi Gallo
5cec517153 LibWeb: Get reference height from closest non-anonymous ancestor
Ignore anonymous block boxes when resolving percentage weights that
would refer to them, per the CSS 2 visual formatting model
specification. This fixes the case when we create an anonymous block
between an image which uses a percentage height relative to a parent
which specifies a definite height.

Fixes #19052.
2023-05-26 14:53:53 +02:00
Andreas Kling
655d9d1462 LibWeb: Make CSSPixels and Length use 64-bit (double) floating point
This fixes a plethora of rounding problems on many websites.
In the future, we may want to replace this with fixed-point arithmetic
(bug #18566) for performance (and consistency with other engines),
but in the meantime this makes the web look a bit better. :^)

There's a lot more things that could be converted to doubles, which
would reduce the amount of casting necessary in this patch.
We can do that incrementally, however.
2023-05-24 14:40:35 +02:00
Jelle Raaijmakers
f391ccfe53 LibGfx+Everywhere: Change Gfx::Rect to be endpoint exclusive
Previously, calling `.right()` on a `Gfx::Rect` would return the last
column's coordinate still inside the rectangle, or `left + width - 1`.
This is called 'endpoint inclusive' and does not make a lot of sense for
`Gfx::Rect<float>` where a rectangle of width 5 at position (0, 0) would
return 4 as its right side. This same problem exists for `.bottom()`.

This changes `Gfx::Rect` to be endpoint exclusive, which gives us the
nice property that `width = right - left` and `height = bottom - top`.
It enables us to treat `Gfx::Rect<int>` and `Gfx::Rect<float>` exactly
the same.

All users of `Gfx::Rect` have been updated accordingly.
2023-05-23 12:35:42 +02:00
Andreas Kling
f0560fd087 LibWeb: Support <svg> elements with display: block
There are a couple of things that went into this:

- We now calculate the intrinsic width/height and aspect ratio of <svg>
  elements based on the spec algorithm instead of our previous ad-hoc
  guesswork solution.

- Replaced elements with automatic size and intrinsic aspect ratio but
  no intrinsic dimensions are now sized with the stretch-fit width
  formula.

- We take care to assign both used width and used height to <svg>
  elements before running their SVG formatting contexts. This ensures
  that the inside SVG content is laid out with knowledge of its
  viewport geometry.

- We avoid infinite recursion in tentative_height_for_replaced_element()
  by using the already-calculated used width instead of calling the
  function that calculates the used width (since that may call us right
  back again).
2023-05-20 08:49:42 +02:00
Andi Gallo
9a6a635e51 LibWeb: Fix for absolutely positioned elements with specified height
Use inner height since the paintable adds padding back.

Fixes #18842.
2023-05-16 14:34:53 +02:00
MacDue
1012947a30 LibWeb: Use .to_px_or_zero() in tentative_height_for_replaced_element()
If just .to_px() is used the height can end up as the float `inf` or
`nan`. This caused an OOM when loading Polygon as this `inf` would
become a `nan` and propagate to the SVG painting, which then attempts
to draw a path with nan control points, which would make the
Gfx::Painter infinitely split the path till it OOM'd.
2023-05-12 05:37:44 +02:00
Andreas Kling
197efc8985 LibWeb: Improve handling of min/max constraint violations on images
Instead of bailing after resolving one violated constraint, we have to
continue down the list of remaining constraints.

We now also call the constraint solver for all replaced elements with
"auto" for both width and height.

Co-authored-by: 0GreenClover0 <clovers02123@gmail.com>
2023-05-09 12:11:28 +02:00
Andreas Kling
90b21890c5 LibWeb: Remove dead code in compute_width_for_replaced_element() 2023-05-09 12:11:28 +02:00
Andreas Kling
fc3c3aef22 LibWeb: Enforce min/max height constraints on abspos replaced boxes
Fixes #18658
2023-05-07 06:28:47 +02:00
Andreas Kling
6ccb77a9b8 LibWeb: Stop using weird Length::resolved() in {Block,}FormattingContext 2023-05-06 21:14:38 +02:00
Andreas Kling
07815dacf8 LibWeb: Don't use weird resolved() when calculating abspos box height 2023-05-06 21:14:38 +02:00
Andreas Kling
7eb9e730e0 LibWeb: Remove unused variable in FormattingContext 2023-05-06 21:14:38 +02:00
Andreas Kling
4699365a64 LibWeb: Stop using weird resolved() in calculate_inner_{width,height}() 2023-05-06 21:14:38 +02:00
Andreas Kling
452a527ff3 LibWeb: Don't use weird resolved() for insets in FormattingContext 2023-05-06 21:14:38 +02:00
Andreas Kling
ca1fa5f748 LibWeb: Use the new to_px() helpers in CSS, SVG and layout code
There should be no behavior change from this, only slightly less
verbosity. :^)
2023-05-06 18:41:34 +02:00
Andreas Kling
f09391dd7f LibWeb: Remove debug spam when creating a dummy formatting context
This will go away when we get rid of the dummy context. There's no value
in spamming the debug console about it.
2023-05-06 18:41:34 +02:00
Andreas Kling
ecd3d0935a LibWeb: Re-lookup the intrinsic sizing cache slot after doing the layout
It's not safe to hold on to a pointer to the cache slot across layout
work, since the nested layout may end up causing new entries to get
added to the cache, potentially invalidating a cache slot pointer.
2023-05-06 18:41:34 +02:00
Aliaksandr Kalenik
34b1186272 LibWeb: Remove early resolve to auto while calculating border-box width
`Length::resolved(Node&)` transforms infinite values to "auto".

Following transformations:
Infinite (Length) -> "auto" -> 0 (px)
cause border-box width to be resolved in zero when it should be inf px.

Removing `Length::resolved(Node&)` makes it work right:
Infinite (Length) -> Infinite (px)

Fixes #18649
2023-05-05 10:01:28 +02:00
Aliaksandr Kalenik
0318ac5ce4 LibWeb: Remove setting length to 0px if it is not definite
If available width (or height) is max-content and width (or height)
value is 100% it should be resolved in infinite px, not 0 px.

Fixes #18639
2023-05-05 06:20:44 +02:00
Andreas Kling
968db96101 LibWeb: Show formatting context roots in layout tree dumps
This patch does three things:

- Factors out the code that determines whether a box will create a new
  formatting context for its children (and which type of context)

- Uses that code to mark all formatting context roots in layout tree
  dumps. This makes it much easier to follow along with layout since
  you can now see exactly where control is transferred to a new
  formatting context.

- Rebaselines all existing layout tests, since the output format has
  changed slightly.
2023-05-03 13:14:36 +02:00
matcool
cc33a57620 LibWeb: Use intrinsic aspect ratio when calculating max content height 2023-04-05 16:23:56 +02:00
Andreas Kling
ca290b27ea LibWeb: Make box content sizes indefinite before intrinsic sizing
When calculating the intrinsic width of a box, we now make its content
width & height indefinite before entering the intrinsic sizing layout.
This ensures that any geometry assigned to the box by its parent
formatting context is ignored.

For intrinsic heights, we only make the content height indefinite.
This is because used content width is a valid (but optional) input
to intrinsic height calculation.
2023-03-27 23:28:07 +02:00
Andreas Kling
4bf10674fa LibWeb: Don't allow resolved height of abspos elements to become negative
We have to clamp the resulting height to 0 when solving for it.
2023-03-25 19:41:31 +01:00
Andreas Kling
3f6f3966b9 LibWeb: Don't allow resolved width of abspos elements to become negative
We have to clamp the resulting width to 0 when solving for it.
2023-03-25 19:41:31 +01:00
Andreas Kling
00999a245c LibWeb: Let FormattingContext decide the automatic width of its root
Instead of special-casing FlexFormattingContext in the intrinsic sizing
layout helpers, add FormattingContext::automatic_content_width() and let
each context subclass decide what that means.

No behavior change here, just moving this responsibility.
2023-03-20 17:57:58 +01:00
Matthew Olsson
7c0c1c8f49 LibJS+LibWeb: Wrap raw JS::Cell*/& fields in GCPtr/NonnullGCPtr 2023-03-15 08:48:49 +01:00
Andreas Kling
24d5a9d7df LibWeb: Fix bogus percentage vertical padding with box-sizing:border-box
The padding-top and padding-bottom properties are relative to the
*width* of the containing block, not the height.

It's funny how we keep making this same mistake again and again. :^)
2023-03-10 13:38:34 +01:00
Andreas Kling
7e76a51cb0 LibWeb: Rename Layout::InitialContainingBlock to Layout::Viewport
The name "initial containing block" was wrong for this, as it doesn't
correspond to the HTML element, and that's specifically what it's
supposed to do! :^)
2023-02-28 12:21:56 +01:00
Sam Atkins
dca19b764b LibWeb: Port CSS::Display to new Strings 2023-02-15 12:48:26 -05:00
Andreas Kling
4e06e86438 LibWeb: Make min-content height equivalent to max-content as appropriate
Per CSS-SIZING-3, the min-content block size should be equivalent to the
max-content block size for some boxes.

Honoring this gives more correct results, and avoids unnecessary work in
many cases since the cached max-content size can be reused.
2023-01-24 11:44:03 +01:00
Andreas Kling
8fe748bb89 LibWeb: Make grid containers be Layout::Box
Grid containers were incorrectly represented as BlockContainer before.
Furthermore, GridFormattingContext had a bogus inheritance relationship
with BlockFormattingContext.

This patch brings our architecture closer to spec by making grid
containers be plain boxes and making GFC not inherit from BFC.
2023-01-24 11:44:03 +01:00
Andreas Kling
d5480a44e5 LibWeb: Allow BFC auto height calculation on any Layout::Box
This algorithm is reused in abspos sizing, and so should not be specific
to block containers (even if the name suggests it.)
2023-01-24 11:44:03 +01:00