Commit graph

86 commits

Author SHA1 Message Date
Oriol Brufau
66e0d543cf
Refactor PlacementAmongFloats (#30068)
- Add explanatory comments.
- Rename some methods.
- Store the ceiling instead of relying on the first band, this allows
  calling place() when current_bands is empty.
- Make current_bands_height() work when current_bands is empty.
- Add add_one_band() helper method.
- Make place() return a Rect. Follow-up patches will need to know the
  size of the area shrunk by floats.

This will be useful for #30057 and #30050.

Co-authored-by: Martin Robinson <mrobinson@igalia.com>
2023-08-04 08:19:41 +00:00
Oriol Brufau
8a5d5eaf13
Minor refactoring for PlacementAmongFloats (#30055)
No difference in behavior, just these changes:
- PlacementAmongFloats::new() initializes the top of the 1st band to the
  ceiling, so that other methods can just refer to the former without
  having to floor by the later.
- In fact, the 'ceiling' field becomes unnecessary, and is removed.
- top_of_placement_for_current_bands() is renamed to current_ceiling().
- try_place_once() is reorganized to reduce indentation.
- The condition 'len() > 0' becomes '!is_empty()'.
- The 1st band is now popped in place() instead of try_place_once(),
  then it's easier to see why the loop will end.
2023-08-01 13:22:32 +00:00
Oriol Brufau
9e4377af47
Fix interaction of margins and clearance for PlacementAmongFloats (#30038)
Consumers of PlacementAmongFloats weren't handling margins properly.
They were assuming that they would either get a positive adjustment,
or zero for no-op.

However, just like the regular clearance triggered by 'clear', the
clearance added onto blocks that establish an independent FC can be
zero or negative, and the effect is different than having no clearance.
2023-07-31 21:07:24 +00:00
Oriol Brufau
77c6a61dfa
Remove ClearSide enum (#30035)
Just use Clear instead, they have the same values.
2023-07-27 09:46:15 +00:00
Oriol Brufau
e38d21d33d
Run unit tests with both layout 2013 and layout 2020 (#30032)
Since #29950, unit tests were only running with the legacy layout, and
there was no way to run them for layout 2020.

This patch makes './mach test-unit' run unit tests for both.

Also doing some changes so that the layout 2020 floats.rs tests compile.
2023-07-27 05:04:55 +00:00
Oriol Brufau
e0e970af31
Remove calculate_clearance_and_adjoin_margin (#30033)
It was useful when it had 3 callers, but #29977 removed 2 of them.
2023-07-26 21:34:04 +00:00
Martin Robinson
ae3f33b9d0
Place replaced and non-auto inline size independent FCs next to floats (#29977)
* Place replaced and non-auto inline size independent FCs next to floats

The CSS2 specification says that replaced content and independent
formatting contexts should be placed next to floats. This change adds
support for that, but punts on support for independent formatting
contexts that have an auto inline size. With an auto inline size, we
which requires a much more complex layout algorithm.

Co-authored-by: Oriol Brufau <obrufau@igalia.com>

* Fix issue with where last band was taken into account for inline size

* adjustment_from_floats should prevent margin collapse

* Properly handle elements with 0 height

---------

Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2023-07-18 18:43:45 +00:00
Oriol Brufau
95832c999b Layout 2020: Properly calculate clearance
calculate_clearance() was not taking into account that adding clearance
prevents top margin from collapsing with earlier margins.
2023-06-30 16:51:39 +02:00
Oriol Brufau
6b2bbdd02d Layout 2020: implement clearance as Option<Length>
Clearance was implemented as a Length, where zero meant no clearance.
However, having a clearance of 0px should be different than having
no clearance, since the former can still prevent margin collapse.

This patch keeps the existing behavior, so it won't be possible to get
a clearance of Some(Length::zero()), but it prepares the terrain for
a follow-up to fix calculate_clearance to return the proper thing.
2023-06-29 11:00:45 +02:00
Martin Robinson
bb13702556 Properly position floats when subsequent boxes collapse margins with containing block
Margins should be able to collapse through floats when collapsing with
parent blocks (the containing block). To properly place floats in this
situation, we need to look at these subsequent floats to find out how
much of the margin will collapse with the parent.

This initial implementation is very basic and the second step would be
to cache this in order to avoid having to constantly recalculate it.

Fixes #29915.

Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2023-06-27 22:45:42 +02:00
bors-servo
fa7107ac12
Auto merge of #29894 - mrobinson:ditch-static-position-closure, r=Loirooriol
Simplify layout of absolutes with static insets

Absolutes with static insets need to be laid out at their ancestor containing blocks, but their position is dependent on their parent's layout. The static layout position is passed up the tree during hoisting and ancestors each add their own offset to the position until it is relative to the containing block that contains the absolute.

This is currently done with a closure and a fairly tricky "tree rank" numbering system that needs to be threaded through the entire layout. This change replaces that system.

Every time a child is laid out we create a positioning context to hold any absolute children (this can be optimized away at a later time). At each of these moments, we call a method to aggregate offsets to the static insets of hoisted absolutes. This makes the logic easier to follow and will also allow implementing this behavior for inline-blocks, which was impossible with the old system.

<!-- Please describe your changes on the following line: -->

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes do not require tests because it should not change behavior.

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
2023-06-21 08:16:49 +02:00
bors-servo
47714f767e
Auto merge of #29870 - mrobinson:float-root, r=Loirooriol
Layout 2020: Correct rendering of floated root

Fix two issues around floating a root element:

1. In the StackingContext code handle the case where a root element is a Float fragment and not a Box fragment. This fixes a debug assertion failure in the css/CSS2/float/float-root.html test.
2. When initializing the SequentialLayoutState, use the containing block width as the maximum inline float placement position instead of infinity. This fixes the rendering of css/CSS2/float/float-root.html.

Note that css/CSS2/float/float-root.html was passing before, because both the test and reference were subject to the same bug. This fixes a couple other tests as well.

<!-- Please describe your changes on the following line: -->

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] There are tests for these changes

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
2023-06-20 18:36:03 +02:00
Martin Robinson
4cb4332602
Correct rendering of floated root
Fix two issues around floating a root element:

1. In the StackingContext code handle the case where a root element is a
   Float fragment and not a Box fragment. This fixes a debug assertion
   failure in the css/CSS2/float/float-root.html test.
2. When initializing the SequentialLayoutState, use the containing block
   width as the maximum inline float placement position instead of
   infinity. This fixes the rendering of css/CSS2/float/float-root.html.

Note that css/CSS2/float/float-root.html was passing before, because
both the test and reference were subject to the same bug. This fixes a
couple other tests as well.
2023-06-20 17:46:45 +02:00
Martin Robinson
459a7d26aa
Simplify layout of absolutes with static insets
Absolutes with static insets need to be laid out at their ancestor
containing blocks, but their position is dependent on their parent's
layout. The static layout position is passed up the tree during hoisting
and ancestors each add their own offset to the position until it is
relative to the containing block that contains the absolute.

This is currently done with a closure and a fairly tricky "tree rank"
numbering system that needs to be threaded through the entire layout.
This change replaces that system.

Every time a child is laid out we create a positioning context to hold
any absolute children (this can be optimized away at a later time). At
each of these moments, we call a method to aggregate offsets to the
static insets of hoisted absolutes. This makes the logic easier to
follow and will also allow implementing this behavior for inline-blocks,
which was impossible with the old system.
2023-06-20 11:44:25 +02:00
Oriol Brufau
4ec6dd1783 Handle floats in BlockContainer::inline_content_sizes
Typically, block-level contents are stacked vertically, so this was just
taking the maximum size among all contents. However, floats can be
stacked horizontally, so we need to sum their sizes.
2023-06-19 16:02:35 +02:00
Martin Robinson
3b3dc4adbe
Layout 2020: Fix issues with float implementation documentation
Fix some rustdoc comments which won't process properly unless they start
with three '/' characters. In addition, improve the name of a function
and add some missing documentation.
2023-06-14 17:09:56 +02:00
Martin Robinson
bc58bb080f Layout 2020: Properly handle negative block margins in floats
If a float has negative block margins, it should be pushed upward, but
shouldn't affect the positioning of any floats that came before it. It
should lower the ceiling though when it still has some non-negative
block contribution. In order to implement this behavior, we should only
place the float considering its non-negative block length contribution. If
the float is pushed up completely past it's "natural" position, it
should be placed like a float with zero block size.
2023-06-11 11:47:56 +02:00
Martin Robinson
e563927718 Layout 2020: Move all Fragment code to the fragment_tree directory
This is a simple code organization change with no behavior change with
the idea of making Layout 2020 easier to understand by new folks to the
project. The idea is that we will have a cleaner separation between the
different parts of layout ie one directory for the fragment tree and one
(currently multiple) directory for the box tree.
2023-06-04 18:12:11 +02:00
Martin Robinson
5c5cc4b795 Fix the unit test
These were broken for various issues.
2023-06-03 06:10:17 +02:00
Martin Robinson
25f6cc04a2 Do not hoist floated fragments
Instead of hoisting floated fragments to be siblings of the fragment
created by their containing block formatting context, keep them in
"normal" fragment tree position and adjust their positioning to be
relative to the containing block. This means that float fragments follow
the existing invariants of the fragment tree and properly handle hit
testing, painting order, and relative positioning.

The tradeoff here is more complexity tracking the containing block
offsets from the block formatting context (including handling collapsed
margins), but less complexity dealing with hoisting / shared ownership
in addition to the correctness benefits.

Some tests are failing now because this change revealed some additional
shortcomings with clearing block formatting context content size past
the end of their contained floats. This will be fixed in a followup
change.

Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2023-06-03 06:10:17 +02:00
Patrick Walton
cdec48328e Place floats in layout 2020, but don't flow text around the floats yet.
This commit puts floats behind the `layout.floats.enabled` pref, because of the
following issues and unimplemented features:

* Inline formatting contexts don't take floats into account, so text doesn't
  flow around the floats yet.

* Non-floated block formatting contexts don't take floats into account, so BFCs
  can overlap floats.

* Block formatting contexts that contain floats don't expand vertically to
  contain all the floats. That is, floats can stick out the bottom of BFCs,
  contra spec.
2023-06-03 06:09:21 +02:00
Martin Robinson
72b5fcd0b6 Combine DOM-related concepts in Layout 2020 into dom.rs 2023-05-13 11:52:59 +02:00
Patrick Walton
362b64aa68 Use the size of the containing block, not the size of the block formatting
context, to place floats in layout 2020.

The containing block for a float is not necessarily the same as the block
formatting context the float is in per CSS 2.1 [1]:

"For other elements, if the element’s position is relative or static, the
containing block is formed by the content edge of the nearest block container
ancestor box."

This shows up in the simplest case:

	<html>
	<body>
	<div style="float: left">Hello</div>
	</body>
	</html>

In this case, the `<html>` element is the block formatting context with inline
size equal to the width of the window, but the `<body>` element with nonzero
inline margins is the containing block for the float. The float placement must
respect the content box of the `<body>` element (i.e. floats must not overlap
the `<body>` element's margins), not that of the `<html>` element.

Because a single block formatting context may contain floats with different
containing blocks, the left and right "walls" of that containing block become
properties of individual floats at the time of placement, not properties of the
float context itself.

Additionally, this commit generalizes the float placement logic a bit to allow
the placement of arbitrary objects, not just floats. This is intended to
support inline layout and block formatting context placement.

This commit updates the `FloatContext` and associated tests only and doesn't
actually wire the context up to the rest of layout, so floats in pages still
aren't actually laid out.

[1]: https://drafts.csswg.org/css2/#containing-block-details
2020-07-22 19:58:28 -07:00
Patrick Walton
5b36d211b4 Add an implementation of the core float and clear placement logic in layout
2020, not yet wired to the rest of layout.

This commit implements an object that handles the 10 rules in CSS 2.1:

https://www.w3.org/TR/CSS2/visuren.html#float-position

The implementation strategy is that of a persistent balanced binary search tree
of float bands. Binary search trees are commonly used for implementing float
positioning; e.g. by WebKit.  Persistence enables each object that interacts
with floats to efficiently contain a snapshot of the float list at the time
that object was laid out. That way, incremental layout can invalidate and start
reflow at any point in a containing block.

This commit features extensive use of
[QuickCheck](https://github.com/BurntSushi/quickcheck) to ensure that the rules
of the CSS specification are followed.

Because this is not yet connected to layout, floats will not actually be laid
out in Web pages yet.

Note that unit tests as set up in Servo currently require types that they
access to be public. Therefore, some internal layout 2020 types that were
previously private have been made public. This is somewhat unfortunate.

Part of #25167.
2020-07-20 12:42:34 -07:00
Anthony Ramine
235df94f2e Compute content sizes lazily in layout 2020 2020-06-18 14:11:02 +02:00
Martin Robinson
89855afa4d layout_2020: Tag fragments with their pseudo content type
This will allow us to answer queries and properly handle animations in
the future for fragments generated for pseudo content.
2020-06-06 17:25:08 +02:00
Fernando Jiménez Moreno
17948f3b39 Propagate text decoration where needed 2020-03-23 11:13:10 +01:00
Fernando Jiménez Moreno
a042f85083 Dump box tree state into json files and display it on layout 2020 viewer 2020-02-21 11:11:00 +01:00
Anthony Ramine
47944a39fc Remove the Node type parameter from Contents
We now pass the Node as an argument during DOM traversal in layout.
2019-12-13 17:51:06 +01:00
Simon Sapin
53ce714005 Fix a “Accessing content size that was not requested” panic
Percentage `width` are treated as `auto` for the purpose of
min/max-content computation, so they also need to be considered
when testing “wether width is auto”
2019-12-10 15:11:53 +01:00
Simon Sapin
38e8fd1e99 Replace boolean parameters by a new ContentSizesRequest enum 2019-12-04 15:10:11 +01:00
Simon Sapin
cfdd23ac16 Add a request_content_sizes parameter to IndependentFormattingContext::construct 2019-12-03 15:11:35 +01:00
Simon Sapin
aa925a5984 Un-allow and fix warnings in components/layout_2020 2019-12-02 16:32:34 +01:00
Simon Sapin
b2b3ea992c Make IndependentFormattingContext a struct that owns styles
… and has a private enum for its contents.

Privacy forces the rest of the code to go through methods
rather than matching on the enum,
reducing accidental layout-mode-specific behavior.
2019-11-26 15:42:27 +01:00
Anthony Ramine
4444c5a2ad Import victor's layout system 🍷 2019-09-11 10:36:30 +02:00
Simon Sapin
86904757e6 Import files from Victor
fdb11f3e87
2019-09-11 10:06:35 +02:00