We want to selectively enable right-to-left writing modes per layout
context. This change makes that possible by allowing access to
`writing-mode` though an interface that always returns the default
horizontal top-to-bottom (implicitly left-to-right) writing mode.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Rakhi Sharma <atbrakhi@igalia.com>
This converts all geometry in the FragmentTree into physical geometry,
doing conversions ahead of time instead of when traversing the fragment
tree. This is necessary to properly implement BiDi in Servo as we need
to know what side borders are on in mixed RTL and LTR contexts.
In addition, fragments are laid out in a particular context and only
that context knows its writing mode. There were issues where were using
one writing mode to lay out and another to convert to phyisical
coordinates. This isn't an issue now since we only use the default
writing mode, but starts to be an issue with BiDi text.
Closes#25564.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Make using the logical geometry types more ergonomic by having them all
implement `Copy` (at most 4 64-bit numbers), similar to what `euclid`
does. In addition add an implementation of `Neg` for `LogicalVec` and
`LogicalSides` as it will be used in upcoming table implementation code.
This change adds a very simple implementation of `border-collapse` for
tables. No harmonization or merging is done at all for borders. Instead,
the largest border for every continuous border sets the size. Instead of
merging different border styles, they are squashed to half size -- which
isn't great, but ensures appropriate positioning.
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
Tables should always be at least as big as their min-content size, even
if we would expect a smaller size according to CSS sizing properties.
#31455 implemented it for in-flow tables participting in flow layout,
but a few cases remained. This patch addresses floated tables.
This change makes changes to allow Servo to compile with the 1.78
version of Rust:
- Dead code is removd (Rust seems to have gotten better at detecting
it).
- The `FlowRef` `DerefMut` is updated according to @SimonSapin's advice
[^1].
- The `imports.rs` now explicitly silences warnings about unused
imports.
[^1]: https://github.com/servo/servo/issues/6503#issuecomment-2066088179
<!-- 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 they 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. -->
* make margin in pbm use app unit
* Simplification
* Consistently resolve inline margins as Au, like block margins
---------
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
* Fix size of tables in flow layout
The contents of a table can make it bigger than what we would expect
from its 'width', 'min-width', 'height' and ' min-height' properties.
Also, 'width: auto' doesn't stretch it to fill the containing block.
We had to refactor the resolution of margins to happen after layout,
otherwise 'auto' margins wouldn't align correctly.
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
* Feedback
* Consistently use `containing_block_for_table` in table layout
* Update test result
---------
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This change starts collecting the starting baseline set for fragments,
which is necessary for some layout modes (flex and tables, namely) as
well as being important for the implementation of `align-items`. In
addition, it converts baseline measurement to use `Au` everywhere.
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
* use app unit in replaced elements
* more app unit usage
* Avoid unnecessary into()
* Run ./mach fmt
* use scaleby
* update
---------
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
* layout: Implement support for `line-height` and `vertical-align`
This is an initial implementation of proper `line-height` and
`vertical-align` support. While this change includes the bulk of the
work there are still many missing pieces for full support. In particular
some big missing things are:
- Flex containers do not properly compute their baselines. The idea is
to tackle this in a followup change. This causes various flex tests
to start failing because everything used to be top aligned.
- The implementation of the line-height quirks (only active in quirks
mode) are incomplete. While the quirk works in many cases, there are
still some cases where it is handled incorrectly. This requires more
redesign and refinement, better suited for a followup.
- Most of the features are CSS 3 such as precision control of the
baseline and first and last baselines are not implemented. This
change gets us close to CSS 2.x support.
While there are many new test passes with this change some tests are
starting to fail. An accounting of new failures:
Tests failing also in Layout 2013:
- /css/css2/positioning/toogle-abspos-on-relpos-inline-child.html (only passes in Chrome)
- /css/CSS2/fonts/font-applies-to-001.xht (potentially an issue with font size)
Invalid tests:
- /css/CSS2/visudet/inline-block-baseline-003.xht
- /css/CSS2/visudet/inline-block-baseline-004.xht
- These are are failing in all browsers. See https://bugs.chromium.org/p/chromium/issues/detail?id=1222151.
Missing table support:
- /_mozilla/mozilla/table_valign_middle.html
Missing `font-size-adjust` support :
- /css/css-fonts/font-size-adjust-zero-2.html (also failing in 2013)
Incomplete form field support :
- /html/rendering/widgets/the-select-element/option-add-label-quirks.html (label isn't rendered so button isn't the right size in quirks mode due to line height quirk)
Need support for calculating flexbox baseline:
- /css/css-flexbox/fieldset-baseline-alignment.html
- /css/css-flexbox/flex-inline.html
- /css/css-flexbox/flexbox-baseline-multi-line-horiz-001.html
- /css/css-flexbox/flexbox-baseline-single-item-001a.html
- /css/css-flexbox/flexbox-baseline-single-item-001b.html
Failing because we don't create anonymous inline boxes for text children of blocks:
- /css/CSS2/linebox/anonymous-inline-inherit-001.html
Passes locally (potentially related to fonts):
- /css/CSS2/css1/c414-flt-fit-004.xht
- /css/css-transforms/transform-input-017.html
- /html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-min-intrinsic-size.html
- /css/css-fonts/first-available-font-005.html
- /css/css-fonts/first-available-font-006.html
* Some cleanups after live review with @mukilan
Also update results.
When a box has overflow, any floats placed in that box will lower the
float ceiling into the overflow. If no float is placed in the box
though, the ceiling should be the block position where the overflow
starts. We already know where this is, because we might be passing a
negative value for the new block position after processing a box
(content_size - actual_size would be negative). This negative value
never raises the ceiling though since a maximum is used.
In the case that there is overflow, this change allows raising the
ceiling, but never passed the lowest float. This necessitates keeping
two values for the ceiling: one for floats and one for non-floats.
Fixes#30304.
This makes the names of flow relative geometry consistent with what is
used in the style crate and removes them from a module. With this change
it's more obvious what makes these types different from the ones in
`euclid`.
PlacementAmongFloats would stop iterating when current_bands would be
empty, even if next_band wasn't at infinity.
Then the BFC root or replaced block was placed after all the floats,
even if it could fit next to some of them.
This patch moves the next_band into current_bands so that the loop
keeps considering bands.
PlacementAmongFloats was assuming that there would always be a FloatBand
at a position smaller than or equal to the given ceiling, but this was
not the case for negative ceilings.
The reason is that the FloatContext initialized the FloatBandTree with
a band at 0, and another at +∞.
This patch changes the initial bands to −∞ and +∞. This seems more
consistent and matches the expectation of PlacementAmongFloats.
- 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>
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.
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.
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.
* 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>
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.
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>
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. -->
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. -->
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.
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.
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.
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.
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.
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.