Unify logic for laying out floats and atomic inlines (#33802)

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
Oriol Brufau 2024-10-11 20:26:00 +02:00 committed by GitHub
parent 0eb8d22d88
commit a86dcfc6e7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 224 additions and 320 deletions

View file

@ -26,11 +26,11 @@ use crate::context::LayoutContext;
use crate::dom::NodeExt; use crate::dom::NodeExt;
use crate::dom_traversal::{Contents, NodeAndStyleInfo}; use crate::dom_traversal::{Contents, NodeAndStyleInfo};
use crate::formatting_contexts::IndependentFormattingContext; use crate::formatting_contexts::IndependentFormattingContext;
use crate::fragment_tree::{BoxFragment, CollapsedBlockMargins, CollapsedMargin}; use crate::fragment_tree::{BoxFragment, CollapsedMargin};
use crate::geom::{LogicalRect, LogicalVec2, PhysicalPoint, PhysicalRect, Size, ToLogical}; use crate::geom::{LogicalRect, LogicalVec2, ToLogical};
use crate::positioned::{relative_adjustement, PositioningContext}; use crate::positioned::{relative_adjustement, PositioningContext};
use crate::style_ext::{Clamp, ComputedValuesExt, DisplayInside, PaddingBorderMargin}; use crate::style_ext::{DisplayInside, PaddingBorderMargin};
use crate::{AuOrAuto, ContainingBlock, IndefiniteContainingBlock}; use crate::ContainingBlock;
/// A floating box. /// A floating box.
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
@ -902,145 +902,13 @@ impl FloatBox {
containing_block, containing_block,
&style, &style,
|positioning_context| { |positioning_context| {
// Margin is computed this way regardless of whether the element is replaced self.contents
// or non-replaced. .layout_float_or_atomic_inline(
let pbm = style.padding_border_margin(containing_block);
let margin = pbm.margin.auto_is(Au::zero);
let pbm_sums = pbm.padding + pbm.border + margin;
let (content_size, children);
match self.contents {
IndependentFormattingContext::NonReplaced(ref mut non_replaced) => {
// Calculate inline size.
// https://drafts.csswg.org/css2/#float-width
let style = non_replaced.style.clone();
let box_size = style.content_box_size(containing_block, &pbm);
let max_box_size = style.content_max_box_size(containing_block, &pbm);
let min_box_size = style.content_min_box_size(containing_block, &pbm);
let available_inline_size =
containing_block.inline_size - pbm_sums.inline_sum();
let available_block_size = containing_block
.block_size
.non_auto()
.map(|block_size| block_size - pbm_sums.block_sum());
let tentative_block_size = box_size
.block
.maybe_resolve_extrinsic(available_block_size)
.map(|size| {
let min_block_size = min_box_size
.block
.maybe_resolve_extrinsic(available_block_size)
.unwrap_or_default();
let max_block_size = max_box_size
.block
.maybe_resolve_extrinsic(available_block_size);
size.clamp_between_extremums(min_block_size, max_block_size)
})
.map_or(AuOrAuto::Auto, AuOrAuto::LengthPercentage);
let mut get_content_size = || {
let containing_block_for_children =
IndefiniteContainingBlock::new_for_style_and_block_size(
&style,
tentative_block_size,
);
non_replaced.inline_content_sizes(
layout_context,
&containing_block_for_children,
)
};
let tentative_inline_size = box_size.inline.resolve(
Size::fit_content,
available_inline_size,
&mut get_content_size,
);
let min_inline_size = min_box_size
.inline
.resolve_non_initial(available_inline_size, &mut get_content_size)
.unwrap_or_default();
let max_inline_size = max_box_size
.inline
.resolve_non_initial(available_inline_size, &mut get_content_size);
let inline_size = tentative_inline_size
.clamp_between_extremums(min_inline_size, max_inline_size);
// Calculate block size.
// https://drafts.csswg.org/css2/#block-root-margin
// FIXME(pcwalton): Is a tree rank of zero correct here?
let containing_block_for_children = ContainingBlock {
inline_size,
block_size: tentative_block_size,
style: &non_replaced.style,
};
let independent_layout = non_replaced.layout(
layout_context, layout_context,
positioning_context, positioning_context,
&containing_block_for_children,
containing_block, containing_block,
);
let (block_size, inline_size) =
match independent_layout.content_inline_size_for_table {
Some(inline_size) => {
(independent_layout.content_block_size, inline_size)
},
None => {
let stretch_size = available_block_size
.unwrap_or(independent_layout.content_block_size);
let mut get_content_size =
|| independent_layout.content_block_size.into();
let min_block_size = min_box_size
.block
.resolve_non_initial(stretch_size, &mut get_content_size)
.unwrap_or_default();
let max_block_size = max_box_size
.block
.resolve_non_initial(stretch_size, &mut get_content_size);
let block_size = tentative_block_size
.auto_is(|| independent_layout.content_block_size)
.clamp_between_extremums(min_block_size, max_block_size);
(block_size, inline_size)
},
};
content_size = LogicalVec2 {
inline: inline_size,
block: block_size,
};
children = independent_layout.fragments;
},
IndependentFormattingContext::Replaced(ref replaced) => {
// https://drafts.csswg.org/css2/#float-replaced-width
// https://drafts.csswg.org/css2/#inline-replaced-height
content_size = replaced.contents.used_size_as_if_inline_element(
containing_block,
&replaced.style,
&pbm,
);
children = replaced.contents.make_fragments(
&replaced.style,
containing_block,
content_size.to_physical_size(containing_block.style.writing_mode),
)
},
};
let containing_block_writing_mode = containing_block.style.writing_mode;
let content_rect = PhysicalRect::new(
PhysicalPoint::zero(),
content_size.to_physical_size(containing_block_writing_mode),
);
BoxFragment::new(
self.contents.base_fragment_info(),
style.clone(),
children,
content_rect,
pbm.padding.to_physical(containing_block_writing_mode),
pbm.border.to_physical(containing_block_writing_mode),
margin.to_physical(containing_block_writing_mode),
// Clearance is handled internally by the float placement logic, so there's no need
// to store it explicitly in the fragment.
None, // clearance
CollapsedBlockMargins::zero(),
) )
.fragment
}, },
) )
} }

View file

@ -117,17 +117,18 @@ use crate::context::LayoutContext;
use crate::flow::float::{FloatBox, SequentialLayoutState}; use crate::flow::float::{FloatBox, SequentialLayoutState};
use crate::flow::{CollapsibleWithParentStartMargin, FlowLayout}; use crate::flow::{CollapsibleWithParentStartMargin, FlowLayout};
use crate::formatting_contexts::{ use crate::formatting_contexts::{
Baselines, IndependentFormattingContext, NonReplacedFormattingContextContents, Baselines, IndependentFormattingContext, IndependentLayoutResult,
NonReplacedFormattingContextContents,
}; };
use crate::fragment_tree::{ use crate::fragment_tree::{
BoxFragment, CollapsedBlockMargins, CollapsedMargin, Fragment, FragmentFlags, BoxFragment, CollapsedBlockMargins, CollapsedMargin, Fragment, FragmentFlags,
PositioningFragment, PositioningFragment,
}; };
use crate::geom::{LogicalRect, LogicalVec2, PhysicalPoint, PhysicalRect, Size, ToLogical}; use crate::geom::{LogicalRect, LogicalVec2, ToLogical};
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext}; use crate::positioned::{AbsolutelyPositionedBox, PositioningContext};
use crate::sizing::ContentSizes; use crate::sizing::ContentSizes;
use crate::style_ext::{Clamp, ComputedValuesExt, PaddingBorderMargin}; use crate::style_ext::{ComputedValuesExt, PaddingBorderMargin};
use crate::{AuOrAuto, ContainingBlock, IndefiniteContainingBlock}; use crate::{ContainingBlock, IndefiniteContainingBlock};
// From gfxFontConstants.h in Firefox. // From gfxFontConstants.h in Firefox.
static FONT_SUBSCRIPT_OFFSET_RATIO: f32 = 0.20; static FONT_SUBSCRIPT_OFFSET_RATIO: f32 = 0.20;
@ -1907,173 +1908,27 @@ impl IndependentFormattingContext {
offset_in_text: usize, offset_in_text: usize,
bidi_level: Level, bidi_level: Level,
) { ) {
let style = self.style();
let container_writing_mode = layout.containing_block.style.writing_mode;
let pbm = style.padding_border_margin(layout.containing_block);
let margin = pbm.margin.auto_is(Au::zero);
let pbm_sums = pbm.padding + pbm.border + margin;
// We need to know the inline size of the atomic before deciding whether to do the line break. // We need to know the inline size of the atomic before deciding whether to do the line break.
let (fragments, content_rect, baselines, mut child_positioning_context) = match self { let mut child_positioning_context = PositioningContext::new_for_style(self.style())
IndependentFormattingContext::Replaced(replaced) => {
let size = replaced
.contents
.used_size_as_if_inline_element(layout.containing_block, &replaced.style, &pbm)
.to_physical_size(container_writing_mode);
let fragments = replaced.contents.make_fragments(
&replaced.style,
layout.containing_block,
size,
);
let content_rect = PhysicalRect::new(PhysicalPoint::zero(), size);
(fragments, content_rect, None, None)
},
IndependentFormattingContext::NonReplaced(non_replaced) => {
let box_size = non_replaced
.style
.content_box_size(layout.containing_block, &pbm);
let max_box_size = non_replaced
.style
.content_max_box_size(layout.containing_block, &pbm);
let min_box_size = non_replaced
.style
.content_min_box_size(layout.containing_block, &pbm);
let available_inline_size =
layout.containing_block.inline_size - pbm_sums.inline_sum();
let available_block_size = layout
.containing_block
.block_size
.non_auto()
.map(|block_size| block_size - pbm_sums.block_sum());
let tentative_block_size = box_size
.block
.maybe_resolve_extrinsic(available_block_size)
.map(|v| {
let min_block_size = min_box_size
.block
.maybe_resolve_extrinsic(available_block_size)
.unwrap_or_default();
let max_block_size = max_box_size
.block
.maybe_resolve_extrinsic(available_block_size);
v.clamp_between_extremums(min_block_size, max_block_size)
})
.map_or(AuOrAuto::Auto, AuOrAuto::LengthPercentage);
let style = non_replaced.style.clone();
let mut get_content_size = || {
let containing_block_for_children =
IndefiniteContainingBlock::new_for_style_and_block_size(
&style,
tentative_block_size,
);
non_replaced
.inline_content_sizes(layout.layout_context, &containing_block_for_children)
};
// https://drafts.csswg.org/css2/visudet.html#inlineblock-width
let tentative_inline_size = box_size.inline.resolve(
Size::fit_content,
available_inline_size,
&mut get_content_size,
);
// https://drafts.csswg.org/css2/visudet.html#min-max-widths
// In this case “applying the rules above again” with a non-auto inline-size
// always results in that size.
let min_inline_size = min_box_size
.inline
.resolve_non_initial(available_inline_size, &mut get_content_size)
.unwrap_or_default();
let max_inline_size = max_box_size
.inline
.resolve_non_initial(available_inline_size, &mut get_content_size);
let inline_size =
tentative_inline_size.clamp_between_extremums(min_inline_size, max_inline_size);
let containing_block_for_children = ContainingBlock {
inline_size,
block_size: tentative_block_size,
style: &non_replaced.style,
};
assert_eq!(
layout.containing_block.style.writing_mode.is_horizontal(),
containing_block_for_children
.style
.writing_mode
.is_horizontal(),
"Mixed horizontal and vertical writing modes are not supported yet"
);
let mut positioning_context =
PositioningContext::new_for_style(&non_replaced.style)
.unwrap_or_else(|| PositioningContext::new_for_subtree(true)); .unwrap_or_else(|| PositioningContext::new_for_subtree(true));
let independent_layout = non_replaced.layout( let IndependentLayoutResult {
mut fragment,
baselines,
pbm_sums,
} = self.layout_float_or_atomic_inline(
layout.layout_context, layout.layout_context,
&mut positioning_context, &mut child_positioning_context,
&containing_block_for_children,
layout.containing_block, layout.containing_block,
); );
let (inline_size, block_size) = match independent_layout
.content_inline_size_for_table
{
Some(inline) => (inline, independent_layout.content_block_size),
None => {
// https://drafts.csswg.org/css2/visudet.html#block-root-margin
let stretch_size =
available_block_size.unwrap_or(independent_layout.content_block_size);
let mut get_content_size = || independent_layout.content_block_size.into();
let min_block_size = min_box_size
.block
.resolve_non_initial(stretch_size, &mut get_content_size)
.unwrap_or_default();
let max_block_size = max_box_size
.block
.resolve_non_initial(stretch_size, &mut get_content_size);
let block_size = tentative_block_size
.auto_is(|| independent_layout.content_block_size)
.clamp_between_extremums(min_block_size, max_block_size);
(inline_size, block_size)
},
};
let content_rect = PhysicalRect::new(
PhysicalPoint::zero(),
LogicalVec2 {
block: block_size,
inline: inline_size,
}
.to_physical_size(container_writing_mode),
);
(
independent_layout.fragments,
content_rect,
Some(independent_layout.baselines),
Some(positioning_context),
)
},
};
// Offset the content rectangle by the physical offset of the padding, border, and margin. // Offset the content rectangle by the physical offset of the padding, border, and margin.
let container_writing_mode = layout.containing_block.style.writing_mode;
let pbm_physical_offset = pbm_sums let pbm_physical_offset = pbm_sums
.start_offset() .start_offset()
.to_physical_size(container_writing_mode); .to_physical_size(container_writing_mode);
let content_rect = content_rect.translate(pbm_physical_offset.to_vector()); fragment.content_rect = fragment
.content_rect
let fragment = BoxFragment::new( .translate(pbm_physical_offset.to_vector());
self.base_fragment_info(),
self.style().clone(),
fragments,
content_rect,
pbm.padding.to_physical(container_writing_mode),
pbm.border.to_physical(container_writing_mode),
margin.to_physical(container_writing_mode),
None, /* clearance */
CollapsedBlockMargins::zero(),
);
// Apply baselines if necessary. // Apply baselines if necessary.
let mut fragment = match baselines { let mut fragment = match baselines {
@ -2083,14 +1938,18 @@ impl IndependentFormattingContext {
// Lay out absolutely positioned children if this new atomic establishes a containing block // Lay out absolutely positioned children if this new atomic establishes a containing block
// for absolutes. // for absolutes.
if let Some(positioning_context) = child_positioning_context.as_mut() { let positioning_context = if matches!(self, IndependentFormattingContext::Replaced(_)) {
None
} else {
if fragment if fragment
.style .style
.establishes_containing_block_for_absolute_descendants(fragment.base.flags) .establishes_containing_block_for_absolute_descendants(fragment.base.flags)
{ {
positioning_context.layout_collected_children(layout.layout_context, &mut fragment); child_positioning_context
} .layout_collected_children(layout.layout_context, &mut fragment);
} }
Some(child_positioning_context)
};
if layout.text_wrap_mode == TextWrapMode::Wrap && if layout.text_wrap_mode == TextWrapMode::Wrap &&
!layout !layout
@ -2122,7 +1981,7 @@ impl IndependentFormattingContext {
AtomicLineItem { AtomicLineItem {
fragment, fragment,
size, size,
positioning_context: child_positioning_context, positioning_context,
baseline_offset_in_parent, baseline_offset_in_parent,
baseline_offset_in_item: baseline_offset, baseline_offset_in_item: baseline_offset,
bidi_level, bidi_level,

View file

@ -14,7 +14,7 @@ use style::computed_values::clear::T as Clear;
use style::computed_values::float::T as Float; use style::computed_values::float::T as Float;
use style::properties::ComputedValues; use style::properties::ComputedValues;
use style::servo::selector_parser::PseudoElement; use style::servo::selector_parser::PseudoElement;
use style::values::computed::Size; use style::values::computed::Size as StyleSize;
use style::values::specified::align::AlignFlags; use style::values::specified::align::AlignFlags;
use style::values::specified::{Display, TextAlignKeyword}; use style::values::specified::{Display, TextAlignKeyword};
use style::Zero; use style::Zero;
@ -25,14 +25,15 @@ use crate::flow::float::{
ContainingBlockPositionInfo, FloatBox, PlacementAmongFloats, SequentialLayoutState, ContainingBlockPositionInfo, FloatBox, PlacementAmongFloats, SequentialLayoutState,
}; };
use crate::formatting_contexts::{ use crate::formatting_contexts::{
Baselines, IndependentFormattingContext, IndependentLayout, NonReplacedFormattingContext, Baselines, IndependentFormattingContext, IndependentLayout, IndependentLayoutResult,
NonReplacedFormattingContext,
}; };
use crate::fragment_tree::{ use crate::fragment_tree::{
BaseFragmentInfo, BoxFragment, CollapsedBlockMargins, CollapsedMargin, Fragment, FragmentFlags, BaseFragmentInfo, BoxFragment, CollapsedBlockMargins, CollapsedMargin, Fragment, FragmentFlags,
}; };
use crate::geom::{ use crate::geom::{
AuOrAuto, LogicalRect, LogicalSides, LogicalVec2, PhysicalRect, PhysicalSides, ToLogical, AuOrAuto, LogicalRect, LogicalSides, LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSides,
ToLogicalWithContainingBlock, Size, ToLogical, ToLogicalWithContainingBlock,
}; };
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext, PositioningContextLength}; use crate::positioned::{AbsolutelyPositionedBox, PositioningContext, PositioningContextLength};
use crate::replaced::ReplacedContent; use crate::replaced::ReplacedContent;
@ -1904,13 +1905,182 @@ impl<'container> PlacementState<'container> {
} }
} }
fn block_size_is_zero_or_intrinsic(size: &Size, containing_block: &ContainingBlock) -> bool { fn block_size_is_zero_or_intrinsic(size: &StyleSize, containing_block: &ContainingBlock) -> bool {
match size { match size {
Size::Auto | Size::MinContent | Size::MaxContent | Size::FitContent | Size::Stretch => true, StyleSize::Auto |
Size::LengthPercentage(ref lp) => { StyleSize::MinContent |
StyleSize::MaxContent |
StyleSize::FitContent |
StyleSize::Stretch => true,
StyleSize::LengthPercentage(ref lp) => {
// TODO: Should this resolve definite percentages? Blink does it, Gecko and WebKit don't. // TODO: Should this resolve definite percentages? Blink does it, Gecko and WebKit don't.
lp.is_definitely_zero() || lp.is_definitely_zero() ||
(lp.0.has_percentage() && containing_block.block_size.is_auto()) (lp.0.has_percentage() && containing_block.block_size.is_auto())
}, },
} }
} }
impl IndependentFormattingContext {
pub(crate) fn layout_float_or_atomic_inline(
&mut self,
layout_context: &LayoutContext,
child_positioning_context: &mut PositioningContext,
containing_block: &ContainingBlock,
) -> IndependentLayoutResult {
let style = self.style();
let container_writing_mode = containing_block.style.writing_mode;
let pbm = style.padding_border_margin(containing_block);
let margin = pbm.margin.auto_is(Au::zero);
let pbm_sums = pbm.padding + pbm.border + margin;
let (fragments, content_rect, baselines) = match self {
IndependentFormattingContext::Replaced(replaced) => {
// https://drafts.csswg.org/css2/visudet.html#float-replaced-width
// https://drafts.csswg.org/css2/visudet.html#inline-replaced-height
let content_size = replaced
.contents
.used_size_as_if_inline_element(containing_block, &replaced.style, &pbm)
.to_physical_size(container_writing_mode);
let fragments = replaced.contents.make_fragments(
&replaced.style,
containing_block,
content_size,
);
let content_rect = PhysicalRect::new(PhysicalPoint::zero(), content_size);
(fragments, content_rect, None)
},
IndependentFormattingContext::NonReplaced(non_replaced) => {
let style = non_replaced.style.clone();
let box_size = style.content_box_size(containing_block, &pbm);
let max_box_size = style.content_max_box_size(containing_block, &pbm);
let min_box_size = style.content_min_box_size(containing_block, &pbm);
let available_inline_size = containing_block.inline_size - pbm_sums.inline_sum();
let available_block_size = containing_block
.block_size
.non_auto()
.map(|block_size| block_size - pbm_sums.block_sum());
let tentative_block_size = box_size
.block
.maybe_resolve_extrinsic(available_block_size)
.map(|size| {
let min_block_size = min_box_size
.block
.maybe_resolve_extrinsic(available_block_size)
.unwrap_or_default();
let max_block_size = max_box_size
.block
.maybe_resolve_extrinsic(available_block_size);
size.clamp_between_extremums(min_block_size, max_block_size)
})
.map_or(AuOrAuto::Auto, AuOrAuto::LengthPercentage);
let mut get_content_size = || {
let containing_block_for_children =
IndefiniteContainingBlock::new_for_style_and_block_size(
&style,
tentative_block_size,
);
non_replaced
.inline_content_sizes(layout_context, &containing_block_for_children)
};
// https://drafts.csswg.org/css2/visudet.html#float-width
// https://drafts.csswg.org/css2/visudet.html#inlineblock-width
let tentative_inline_size = box_size.inline.resolve(
Size::fit_content,
available_inline_size,
&mut get_content_size,
);
// https://drafts.csswg.org/css2/visudet.html#min-max-widths
// In this case “applying the rules above again” with a non-auto inline-size
// always results in that size.
let min_inline_size = min_box_size
.inline
.resolve_non_initial(available_inline_size, &mut get_content_size)
.unwrap_or_default();
let max_inline_size = max_box_size
.inline
.resolve_non_initial(available_inline_size, &mut get_content_size);
let inline_size =
tentative_inline_size.clamp_between_extremums(min_inline_size, max_inline_size);
let containing_block_for_children = ContainingBlock {
inline_size,
block_size: tentative_block_size,
style: &style,
};
assert_eq!(
container_writing_mode.is_horizontal(),
style.writing_mode.is_horizontal(),
"Mixed horizontal and vertical writing modes are not supported yet"
);
let independent_layout = non_replaced.layout(
layout_context,
child_positioning_context,
&containing_block_for_children,
containing_block,
);
let (inline_size, block_size) = match independent_layout
.content_inline_size_for_table
{
Some(inline) => (inline, independent_layout.content_block_size),
None => {
// https://drafts.csswg.org/css2/visudet.html#block-root-margin
let stretch_size =
available_block_size.unwrap_or(independent_layout.content_block_size);
let mut get_content_size = || independent_layout.content_block_size.into();
let min_block_size = min_box_size
.block
.resolve_non_initial(stretch_size, &mut get_content_size)
.unwrap_or_default();
let max_block_size = max_box_size
.block
.resolve_non_initial(stretch_size, &mut get_content_size);
let block_size = tentative_block_size
.auto_is(|| independent_layout.content_block_size)
.clamp_between_extremums(min_block_size, max_block_size);
(inline_size, block_size)
},
};
let content_size = LogicalVec2 {
block: block_size,
inline: inline_size,
}
.to_physical_size(container_writing_mode);
let content_rect = PhysicalRect::new(PhysicalPoint::zero(), content_size);
(
independent_layout.fragments,
content_rect,
Some(independent_layout.baselines),
)
},
};
let fragment = BoxFragment::new(
self.base_fragment_info(),
self.style().clone(),
fragments,
content_rect,
pbm.padding.to_physical(container_writing_mode),
pbm.border.to_physical(container_writing_mode),
margin.to_physical(container_writing_mode),
// Floats can have clearance, but it's handled internally by the float placement logic,
// so there's no need to store it explicitly in the fragment.
// And atomic inlines don't have clearance.
None, /* clearance */
CollapsedBlockMargins::zero(),
);
IndependentLayoutResult {
fragment,
baselines,
pbm_sums,
}
}
}

View file

@ -14,7 +14,8 @@ use crate::dom::NodeExt;
use crate::dom_traversal::{Contents, NodeAndStyleInfo}; use crate::dom_traversal::{Contents, NodeAndStyleInfo};
use crate::flexbox::FlexContainer; use crate::flexbox::FlexContainer;
use crate::flow::BlockFormattingContext; use crate::flow::BlockFormattingContext;
use crate::fragment_tree::{BaseFragmentInfo, Fragment, FragmentFlags}; use crate::fragment_tree::{BaseFragmentInfo, BoxFragment, Fragment, FragmentFlags};
use crate::geom::LogicalSides;
use crate::positioned::PositioningContext; use crate::positioned::PositioningContext;
use crate::replaced::ReplacedContent; use crate::replaced::ReplacedContent;
use crate::sizing::{self, ContentSizes}; use crate::sizing::{self, ContentSizes};
@ -91,6 +92,12 @@ pub(crate) struct IndependentLayout {
pub baselines: Baselines, pub baselines: Baselines,
} }
pub(crate) struct IndependentLayoutResult {
pub fragment: BoxFragment,
pub baselines: Option<Baselines>,
pub pbm_sums: LogicalSides<Au>,
}
impl IndependentFormattingContext { impl IndependentFormattingContext {
pub fn construct<'dom, Node: NodeExt<'dom>>( pub fn construct<'dom, Node: NodeExt<'dom>>(
context: &LayoutContext, context: &LayoutContext,