layout: Collect both start and end baselines for fragments (#31230)

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>
This commit is contained in:
Martin Robinson 2024-02-05 19:06:05 +01:00 committed by GitHub
parent 28bde741ed
commit 7f13316f24
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 112 additions and 101 deletions

View file

@ -13,6 +13,7 @@ use style::Zero;
use super::{BaseFragment, BaseFragmentInfo, CollapsedBlockMargins, Fragment};
use crate::cell::ArcRefCell;
use crate::formatting_contexts::Baselines;
use crate::geom::{
LengthOrAuto, LogicalRect, LogicalSides, PhysicalPoint, PhysicalRect, PhysicalSides,
PhysicalSize,
@ -44,10 +45,10 @@ pub(crate) struct BoxFragment {
/// <https://drafts.csswg.org/css2/#clearance>
pub clearance: Option<Length>,
/// When this box contains an inline formatting context, this tracks the baseline
/// offset of the last inflow line. This offset is used to propagate baselines to
/// ancestors of `display: inline-block` ancestors.
pub last_baseline_offset: Option<Length>,
/// When this [`BoxFragment`] is for content that has a baseline, this tracks
/// the first and last baselines of that content. This is used to propagate baselines
/// to things such as tables and inline formatting contexts.
pub baselines: Baselines,
pub block_margins_collapsed_with_children: CollapsedBlockMargins,
@ -73,7 +74,6 @@ impl BoxFragment {
border: LogicalSides<Length>,
margin: LogicalSides<Length>,
clearance: Option<Length>,
last_inflow_baseline_offset: Option<Length>,
block_margins_collapsed_with_children: CollapsedBlockMargins,
) -> BoxFragment {
let position = style.get_box().position;
@ -94,7 +94,6 @@ impl BoxFragment {
border,
margin,
clearance,
last_inflow_baseline_offset,
block_margins_collapsed_with_children,
PhysicalSize::new(width_overconstrained, height_overconstrained),
)
@ -109,7 +108,6 @@ impl BoxFragment {
border: LogicalSides<Length>,
margin: LogicalSides<Length>,
clearance: Option<Length>,
mut last_inflow_baseline_offset: Option<Length>,
block_margins_collapsed_with_children: CollapsedBlockMargins,
overconstrained: PhysicalSize<bool>,
) -> BoxFragment {
@ -126,10 +124,15 @@ impl BoxFragment {
// > value) a block-level or inline-level block container that is a scroll container
// > always has a last baseline set, whose baselines all correspond to its block-end
// > margin edge.
//
// This applies even if there is no baseline set, so we unconditionally set the value here
// and ignore anything that is set via [`Self::with_baselines`].
let mut baselines = Baselines::default();
if style.establishes_scroll_container() {
last_inflow_baseline_offset = Some(
content_rect.size.block + padding.block_end + border.block_end + margin.block_end,
);
baselines.last = Some(
(content_rect.size.block + padding.block_end + border.block_end + margin.block_end)
.into(),
)
}
BoxFragment {
@ -141,7 +144,7 @@ impl BoxFragment {
border,
margin,
clearance,
last_baseline_offset: last_inflow_baseline_offset,
baselines,
block_margins_collapsed_with_children,
scrollable_overflow_from_children,
overconstrained,
@ -149,6 +152,19 @@ impl BoxFragment {
}
}
pub fn with_baselines(mut self, baselines: Baselines) -> Self {
// From the https://drafts.csswg.org/css-align-3/#baseline-export section on "block containers":
// > However, for legacy reasons if its baseline-source is auto (the initial
// > value) a block-level or inline-level block container that is a scroll container
// > always has a last baseline set, whose baselines all correspond to its block-end
// > margin edge.
if !self.style.establishes_scroll_container() {
self.baselines.last = baselines.last;
}
self.baselines.first = baselines.first;
self
}
pub fn scrollable_overflow(
&self,
containing_block: &PhysicalRect<Length>,