Commit graph

193 commits

Author SHA1 Message Date
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
Aliaksandr Kalenik
6eb2f4bfee LibWeb: Fix reset of floats y offset
Commit 7dc0edcb86 was supposed to prevent
floats from being placed higher than preceding boxes but the change
turned out to be completely wrong and caused regressions because:
1. Call to `clear()` in `layout_block_level_children` would reset
   floating boxes only after layout of box with _not_ inline children
although the same should happen after layout of IFC.
2. `clear()` causes offset y of floats to be reset but it also clears
   all currently enocuntered floating boxes which means the next box
   that has actual clearance will get wrong y position.
2023-01-26 12:34:29 +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
Aliaksandr Kalenik
56ceb6a106 LibWeb: Fix floats y offset calculation
There is a difference in y offset position calculation for floats when
LineBuilder provides final y position while for blocks it needs to be
adjusted by `y_offset`. This difference already accounted in floating
box position calculation and this patch also makes it accounted in check
whether a floating boxes on the same line intersect between each other.
2023-01-21 14:45:09 +01:00
Aliaksandr Kalenik
87f0e835eb LibWeb: Improve auto height calculation for tables
Change `compute_auto_height_for_block_level_element` to use max height
(`m_automatic_content_height` produced from TFC) for tables with auto
height which is more correct behaviour than treating them like block
containers.
2023-01-20 18:04:17 +01:00
Aliaksandr Kalenik
7dc0edcb86 LibWeb: Prevent floats from being placed higher than preceding blocks
CSS 2.2 section 9.5.1:
The outer top of a floating box may not be higher than the
outer top of any _block_ or floated box generated by an
element earlier in the source document.

Where block is `BlockContainer` in LibWeb type system.
Which means `current_boxes` need to be cleared before
leaving block container.

```html
<style>
.wrapper {
  width: 100px;
  height: 300px;
  background-color: lightgray;
}

.box {
  margin: 10px;
  width: 50px;
  height: 50px;
  float: left;
}

.a { background-color: salmon; }
.b { background-color: slateblue; }
.c { background-color: green; }
</style>
<div class="wrapper">
	<div class="box a"></div>
	<div class="box b"></div>
</div>
<div class="box c">
</div>
```
2023-01-16 09:45:16 +01:00
Aliaksandr Kalenik
709fe01f52 LibWeb: Override width calculation for table wrappers
Introduce `TableWrapper` type so table wrappers could be
distinguished from block containers and override width
calculation for table wrappers (CSS 2.2 spec, section 17.5.2)
 inside BFCs in the way that their width should be equal to
width of table box they wrap.
2023-01-14 19:22:08 +01:00
Aliaksandr Kalenik
30b51b06b9 LibWeb: Fix y position calculation for blocks with clearance
This change fixes problem that y position of blocks with
clearance might not include border_top and padding_top
by changing `place_block_level_element_in_normal_flow_vertically`
to accept y position without `border_box_top` and adding it
on the last step when clearance is already taken in account.

Bug reproducer:
```html
<style>
.a {
    border: 10px salmon solid;
    width: 50px;
    height: 50px;
    float: left;
}
.b {
    clear: both;
    border: 20px slateblue solid;
    width: 50px;
    height: 50px;
}
</style>
<div class="a"></div><div class="b"></div><div class="c"></div>
```
2023-01-10 10:24:05 +01:00
Aliaksandr Kalenik
6c5ba10bb0 LibWeb: Remove redundant check for empty anonymous blocks
It is incorrect to skip anonymous block containers without
line boxes during block auto height calculation because there
might be table roots wrapped in anonymous table boxes after fixup
and their height should be taken in account so leaving just
condition to skip child boxes which margins are "collapsed
through" (`border_box_height() == 0`) sufficient to skip
anonymous blocks without lines but still consider table wrappers.
2023-01-09 11:47:31 +01:00
Sam Atkins
c70dcaefcd LibWeb: Convert LayoutState to new pixel units 2023-01-05 17:42:31 +01:00
Sam Atkins
76047d1932 LibWeb: Convert InlineLevelIterator/LineBox/LineBuilder to new px units 2023-01-05 17:42:31 +01:00