Commit graph

203 commits

Author SHA1 Message Date
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
Andreas Kling
89ba00304c LibWeb: Account for negative margins when calculating float intrusion
If a box has a negative margin-left, it may have a negative effective
offset within its parent BFC root coordinate system.

We can account for this when calculating the amount of left-side float
intrusion by flooring the X offset at 0.
2023-06-04 18:14:12 +02:00
Simon Wanner
870bcd56df LibWeb: Make disclosure marker bounds square
This makes sure we actually render an equilateral triangle
inside a square.
2023-06-03 05:54:49 +02:00
Simon Wanner
293ece2292 LibWeb: Support list-style-position
This moves the ::marker inside of <summary> actually inside. :^)
2023-06-03 05:54:49 +02:00
Andreas Kling
caa491b72a LibWeb: Measure the overflow for all scroll containers
Instead of just measuring the layout viewport, we now measure overflow
in every box that is a scroll container.

This has the side effect of no longer creating paintables for layout
boxes that didn't participate in layout. (For example, empty/anonymous
boxes that were ignored by flex itemization.)

Such boxes are now marked as "(not painted)" in the layout tree dumps,
as they have no paintable to dump geometry from.
2023-06-01 13:33:35 +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
Andi Gallo
7f9ede07bc LibWeb: Set margin, padding and border for replaced boxes
Separating the paths for replaced and non-replaced floating boxes lost
the logic for margin, padding and border which was done by
compute_width_for_floating_box. Set them the same way as we do for
block-level replaced elements, per the specification.
2023-05-30 10:09:47 +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
Andi Gallo
1e526af430 LibWeb: Fix width calculation for floating replaced elements
The path for floating, replaced elements must not fall through to the
path taken for floating, non-replaced elements. The former works like
inline replaced elements, while the latter uses a completely different
algorithm which doesn't account for intrinsic ratio. Falling through
overrides the correct value computed by the former.

Fixes #19061.
2023-05-26 21:20:56 +02:00
Aliaksandr Kalenik
7cc20f4cb5 LibWeb: Reset margin collapsing state only if box indeed add clearance
This fixes the issue when margin collapsing state was always reset if
a box has clear property not equal to none even if it does not actually
introduce clearance.
2023-05-26 18:11:35 +02:00
Aliaksandr Kalenik
202b24584f LibWeb: Sum horizontal margins to calculate space used by floats
This fixes the issue where max margin is used to find offset of
floating box although horizonal margins do not collapse so they need
to be summed instead.
2023-05-24 18:58:42 +02:00
Jelle Raaijmakers
90d8844c77 LibWeb: Remove Gfx::Rect<float> workarounds from BFC
No longer is the last horizontal line of pixels ignored during layout.
This used to be a bug in `Gfx::Rect<float>` that was fixed in
f391ccfe53.
2023-05-24 18:19:45 +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
Aliaksandr Kalenik
76aa17be86 LibWeb: Make sure collapsed margins are not ignored if box creates FC
Fixes a bug that if box creates new formatting context then all already
collapsed margins are ignored and only margin_top is used.
2023-05-22 12:51:24 +02:00
Andreas Kling
b2c899af11 LibWeb: Make standalone SVG document roots the size of the viewport
We have to special-case these, otherwise our normal CSS layout algorithm
will see that some SVG roots have width/height assigned, and make those
the used width/height.

When used in an SVG-as-image context, the outermost viewport must be the
authoritative root size.
2023-05-21 07:44:29 +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
Andreas Kling
411b28fc59 LibWeb: Make sure that margins don't collapse across a nested BFC
In order to fix this, I also had to reorganize the code so that we
create an independent formatting context even for block-level boxes
that don't have any children. This accidentally improves a table
layout test as well (for empty tables).
2023-05-19 15:09:09 +02:00
Andreas Kling
bab6796099 LibWeb: Rewrite calculation of available space between floats
This code now works in terms of *intrusion* by left and right side
floats into a given box whose insides we're trying to layout.

Previously, it worked in terms of space occupied by floats in the root
box of the BFC they participated in. That created a bunch of edge cases
since the code asking about the information wasn't operating in root
coordinate space, but in the coordinate space of some arbitrarily nested
block descendant of the root.

This finally allows horizontal margins in the containing block chain to
affect floats and nested content correctly, and it also allows us to
remove a bogus workaround in InlineFormattingContext.
2023-05-16 14:35:10 +02:00
Andreas Kling
1ebae7a779 LibWeb: Stop changing width of block-level flex containers during layout
If the parent BFC can come up with a nice stretch-fit width for the flex
container, it will have already done so *before* even entering flex
layout. There's no need to do it again, midway through the flex layout
algorithm.

This wasn't just unnecessary, but we were also doing it incorrectly and
not taking margins into account when calculating the amount of available
space for stretch-fit. This led to oversized flex containers in the
presence of negative margins.

Fixes #18614
2023-05-08 15:56:00 +02:00
Aliaksandr Kalenik
771208d2e2 LibWeb: Fix auto height calculation for table inside BFC
`calculate_max_content_height` expects the available width as the
second argument. However, the available height was mistakenly passed
before. This did not seem to cause any problems because TFC currently
does not respect height sizing constraints but still needs to be fixed.
2023-05-08 14:52:48 +02:00
Aliaksandr Kalenik
038283f3fc LibWeb: Rename function to find table box width inside table wrapper
compute_table_box_width_inside_table_wrapper should be a better name
considering what this function does.
2023-05-07 06:31:53 +02:00
Aliaksandr Kalenik
3a605d8c19 LibWeb: Set width in compute_width_for_table_wrapper()
Width of table wrapper need to be set to to calculate width of table
box inside. Otherwise TFC will set wrong width assuming width of
containing block is 0.
2023-05-07 06:31:53 +02:00
Andreas Kling
6ccb77a9b8 LibWeb: Stop using weird Length::resolved() in {Block,}FormattingContext 2023-05-06 21:14:38 +02:00
Andreas Kling
1d76126abe LibWeb: Don't use weird Length::resolved() for padding in BFC 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
0GreenClover0
8bb2663a22 LibWeb: Zero out margins if width is not 'auto' in BFC's compute_width
Reverse the condition to satisfy the spec comment. Probably a typo.
A 3 year old typo! :^)
2023-05-05 13:26:41 +02:00
Aliaksandr Kalenik
853ecb8d8e LibWeb: Narrow width of boxes that create BFC to avoid overlap of float
https://www.w3.org/TR/CSS22/visuren.html#floats says that when a box
establishes BFC it should not overlap with floats. The way to avoid
overlaps is up to implementor. This change implements avoiding overlap
by narrowing width of a box because it seems like what other engines
do (in the scenarios I tested).
2023-05-04 06:14:58 +02:00
Aliaksandr Kalenik
bf41af6b9d LibWeb: Calculate y of a box before resolving width in BFC
Calculating width of a box in BFC requires having resolved y to be able
to check if a box overlaps with any floating boxes.

This change makes compute_width() to be called after finding y
position. That also required to move resolving of vertical metrics
in the beginning of a box layout process to have vertical margins
resolved before finding y position.
2023-05-04 06:14:58 +02:00
Andreas Kling
590723aa3b LibWeb: Implement the "The html element fills the viewport quirk"
Fixes #18037.
2023-05-03 20:44:30 +02:00
Andreas Kling
508927cae2 LibWeb: Take floats into account when measuring automatic width of IFC
When there are floats present inside an IFC, we must coordinate with
the parent BFC to calculate the automatic width of the IFC's block box.
This is because the IFC is not directly aware of floats. Only the BFC
knows enough about them to account for them in automatic sizing.
2023-05-03 19:49:43 +02:00
Aliaksandr Kalenik
09d698e0a0 LibWeb: Exclude table-wrapper margins from table available width
Table should not take up more width than is available inside wrapper
after margins are taken in account.
2023-05-03 15:03:56 +02:00
Aliaksandr Kalenik
f6ff37398c LibWeb: Fix intrinsic sizing when min or max width is specified
Fixes the problem that width is incorrectly computed in intrinsic
sizing mode when there are blocks that have min-width or max-width
specified.

Actually that is just the fix of a symptom of the larger problem that
Length::to_px() returns 0 when value is auto regardless of available
size.
2023-05-02 18:50:26 +02:00
Aliaksandr Kalenik
6cec431720 LibWeb: Set zero underflow when calculating intrinsic width of block
This fix resolves issue where calculating the min size of a block could
result in incorrect value if width of the block's children was
compensated by margins to fit into container width (which is equal to 0
during min size calculation).
2023-05-02 12:41:45 +02:00
Andreas Kling
5236819f58 LibWeb: Resolve horizontal auto margins for images with display: block 2023-04-30 05:52:19 +02:00
Aliaksandr Kalenik
9ee64b5694 LibWeb: Prevent margin double-counting with "collapse through" boxes
If there is a remaining margin-bottom in margin collapsing state
tracker after laying out all boxes in the current BFC, it must be
assigned to the last in-flow child since margin collapsing cannot
occur across a formatting context boundary.

The current issue where margin-bottom may be counted twice due to
"collapse through" margins in the last in-flow child box is addressed
with this fix by excluding such boxes during the search for a box to
assign the remaining margin.

Test case coming with this fix has a layout bug with incorrectly
computed line height.
2023-04-27 07:52:12 +02:00
Andreas Kling
b97229c9b5 LibWeb: Ignore preferred width when calculating intrinsic width of block
When calculating the intrinsic width of a block-level box, we now ignore
the preferred width entirely, and not just when the preferred width
should be treated as auto.

The condition for this was both confused and wrong, as it looked at the
available width around the box, but didn't check for a width constraint
on the box itself.

Just because the available width has an intrinsic sizing constraint
doesn't mean that the box is undergoing intrinsic sizing. It could also
be the box's containing block!
2023-04-06 16:47:40 +02:00
Andreas Kling
4f752ca791 LibWeb: Pass available inner space to BFC root auto height calculation 2023-03-27 23:28:07 +02:00
Andreas Kling
96f8cf2971 LibWeb: Consider inline content (line boxes) when measuring overflow
Fixes #13628
2023-03-22 12:56:44 +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
Andreas Kling
db545b51ef LibWeb: Make sure float: left boxes get pushed down if they can't fit 2023-03-15 11:43:54 +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
92eaad8f2e LibWeb: Consider entire stack of floated boxes when floating new box
If normal flow layout has caused us to progress past the current
innermost float in the block axis, we still need to consider the floats
stacked outside of it.

Fix this by always walking the currently stacked floats from innermost
to outermost when placing new floats.
2023-03-12 18:10:32 +01:00
Andreas Kling
b71c7a6e44 Userland: Use Font::pixel_size_rounded_up() instead of glyph_height()
The only remaining clients of this API are specific to bitmap fonts and
editing thereof.
2023-03-04 00:29:38 +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
Aliaksandr Kalenik
2ed5415750 LibWeb: Fix clearance to update y offset within current block
If a box has clearance and margin bottom of preceding box is greater
than static y of the box then it should also affect y offset in current
block container so subsequent boxes will get correct y position too.
2023-02-10 20:55:33 +01:00
Aliaksandr Kalenik
0cd63f851e LibWeb: Store y offset of current block container in BFC member
This change should make it possible to access y offset of current block
container in BFC without explicitly passing it using method parameters.
2023-02-10 20:55:33 +01:00
Aliaksandr Kalenik
f43f4feb1e LibWeb: Table wrappers should not be ignored in auto height calculation
Though table wrappers are anonymous block containers (because
TableWrapper is inherited from BlockContainer) with no lines they
should not be skipped in block auto height calculation.
2023-02-07 17:04:38 +01:00
Aliaksandr Kalenik
00f8b5a911 LibWeb: Ignore only anonymous blocks in block auto height calculation
Previously block auto height calculation was changed to skip boxes with
collapsed margins and then condition to skip anonymous boxes with no
lines was also removed in 6c5ba10bb0 to
avoid skipping anonymous wrappers of tables.

Skipping boxes with collapsed margins (currently it's check that
height is 0) is wrong because it makes empty boxes with clearance to
be skipped which is not correct while anonymous boxes with no lines
should be skipped and it's no longer causes problems with tables
(fixed in 87f0e835eb)
2023-01-26 12:34:29 +01:00