layout: Remove IndependentNonReplacedContents (#37971)

With the work to unify the layout logic for replaced and non-replaced
boxes (#37942), I think the `IndependentNonReplacedContents` enum does
no longer make much sense.

Therefore, this removes `IndependentNonReplacedContents`, merging its
values into `IndependentFormattingContextContents`.

The methods defined on `IndependentFormattingContextContents` can now be
on `IndependentFormattingContext`, in particular this implies that the
layout results of a replaced box will now be cached.

Testing: Unneeded (no behavior change)
This part of #37942

Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
Oriol Brufau 2025-07-10 09:46:04 +02:00 committed by GitHub
parent 07247cd4fd
commit ff050b71fa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 245 additions and 323 deletions

View file

@ -18,7 +18,6 @@ use crate::flow::inline::construct::InlineFormattingContextBuilder;
use crate::flow::{BlockContainer, BlockFormattingContext}; use crate::flow::{BlockContainer, BlockFormattingContext};
use crate::formatting_contexts::{ use crate::formatting_contexts::{
IndependentFormattingContext, IndependentFormattingContextContents, IndependentFormattingContext, IndependentFormattingContextContents,
IndependentNonReplacedContents,
}; };
use crate::layout_box_base::LayoutBoxBase; use crate::layout_box_base::LayoutBoxBase;
use crate::style_ext::{ComputedValuesExt, DisplayGeneratingBox}; use crate::style_ext::{ComputedValuesExt, DisplayGeneratingBox};
@ -72,9 +71,7 @@ impl<'dom> ModernContainerJob<'dom> {
let info: &NodeAndStyleInfo = anonymous_info; let info: &NodeAndStyleInfo = anonymous_info;
let formatting_context = IndependentFormattingContext { let formatting_context = IndependentFormattingContext {
base: LayoutBoxBase::new(info.into(), info.style.clone()), base: LayoutBoxBase::new(info.into(), info.style.clone()),
contents: IndependentFormattingContextContents::NonReplaced( contents: IndependentFormattingContextContents::Flow(block_formatting_context),
IndependentNonReplacedContents::Flow(block_formatting_context),
),
}; };
Some(ModernItem { Some(ModernItem {

View file

@ -123,9 +123,7 @@ use crate::context::LayoutContext;
use crate::dom_traversal::NodeAndStyleInfo; use crate::dom_traversal::NodeAndStyleInfo;
use crate::flow::CollapsibleWithParentStartMargin; use crate::flow::CollapsibleWithParentStartMargin;
use crate::flow::float::{FloatBox, SequentialLayoutState}; use crate::flow::float::{FloatBox, SequentialLayoutState};
use crate::formatting_contexts::{ use crate::formatting_contexts::{Baselines, IndependentFormattingContext};
Baselines, IndependentFormattingContext, IndependentNonReplacedContents,
};
use crate::fragment_tree::{ use crate::fragment_tree::{
BoxFragment, CollapsedBlockMargins, CollapsedMargin, Fragment, FragmentFlags, BoxFragment, CollapsedBlockMargins, CollapsedMargin, Fragment, FragmentFlags,
PositioningFragment, PositioningFragment,
@ -2153,9 +2151,7 @@ impl IndependentFormattingContext {
BaselineSource::First => baselines.first, BaselineSource::First => baselines.first,
BaselineSource::Last => baselines.last, BaselineSource::Last => baselines.last,
BaselineSource::Auto => match &self.contents { BaselineSource::Auto => match &self.contents {
IndependentFormattingContextContents::NonReplaced( IndependentFormattingContextContents::Flow(_) => baselines.last,
IndependentNonReplacedContents::Flow(_),
) => baselines.last,
_ => baselines.first, _ => baselines.first,
}, },
} }

View file

@ -39,14 +39,7 @@ pub(crate) struct IndependentFormattingContext {
#[derive(Debug, MallocSizeOf)] #[derive(Debug, MallocSizeOf)]
pub(crate) enum IndependentFormattingContextContents { pub(crate) enum IndependentFormattingContextContents {
NonReplaced(IndependentNonReplacedContents),
Replaced(ReplacedContents), Replaced(ReplacedContents),
}
// Private so that code outside of this module cannot match variants.
// It should got through methods instead.
#[derive(Debug, MallocSizeOf)]
pub(crate) enum IndependentNonReplacedContents {
Flow(BlockFormattingContext), Flow(BlockFormattingContext),
Flex(FlexContainer), Flex(FlexContainer),
Grid(TaffyContainer), Grid(TaffyContainer),
@ -86,16 +79,18 @@ impl IndependentFormattingContext {
let contents = match display_inside { let contents = match display_inside {
DisplayInside::Flow { is_list_item } | DisplayInside::Flow { is_list_item } |
DisplayInside::FlowRoot { is_list_item } => { DisplayInside::FlowRoot { is_list_item } => {
IndependentNonReplacedContents::Flow(BlockFormattingContext::construct( IndependentFormattingContextContents::Flow(
context, BlockFormattingContext::construct(
node_and_style_info, context,
non_replaced_contents, node_and_style_info,
propagated_data, non_replaced_contents,
is_list_item, propagated_data,
)) is_list_item,
),
)
}, },
DisplayInside::Grid => { DisplayInside::Grid => {
IndependentNonReplacedContents::Grid(TaffyContainer::construct( IndependentFormattingContextContents::Grid(TaffyContainer::construct(
context, context,
node_and_style_info, node_and_style_info,
non_replaced_contents, non_replaced_contents,
@ -103,7 +98,7 @@ impl IndependentFormattingContext {
)) ))
}, },
DisplayInside::Flex => { DisplayInside::Flex => {
IndependentNonReplacedContents::Flex(FlexContainer::construct( IndependentFormattingContextContents::Flex(FlexContainer::construct(
context, context,
node_and_style_info, node_and_style_info,
non_replaced_contents, non_replaced_contents,
@ -120,7 +115,7 @@ impl IndependentFormattingContext {
&node_and_style_info.style, &node_and_style_info.style,
); );
base_fragment_info.flags.insert(FragmentFlags::DO_NOT_PAINT); base_fragment_info.flags.insert(FragmentFlags::DO_NOT_PAINT);
IndependentNonReplacedContents::Table(Table::construct( IndependentFormattingContextContents::Table(Table::construct(
context, context,
node_and_style_info, node_and_style_info,
table_grid_style, table_grid_style,
@ -131,7 +126,7 @@ impl IndependentFormattingContext {
}; };
Self { Self {
base: LayoutBoxBase::new(base_fragment_info, node_and_style_info.style.clone()), base: LayoutBoxBase::new(base_fragment_info, node_and_style_info.style.clone()),
contents: IndependentFormattingContextContents::NonReplaced(contents), contents,
} }
}, },
Contents::Replaced(contents) => { Contents::Replaced(contents) => {
@ -166,14 +161,8 @@ impl IndependentFormattingContext {
layout_context: &LayoutContext, layout_context: &LayoutContext,
constraint_space: &ConstraintSpace, constraint_space: &ConstraintSpace,
) -> InlineContentSizesResult { ) -> InlineContentSizesResult {
match &self.contents { self.base
IndependentFormattingContextContents::NonReplaced(contents) => self .inline_content_sizes(layout_context, constraint_space, &self.contents)
.base
.inline_content_sizes(layout_context, constraint_space, contents),
IndependentFormattingContextContents::Replaced(contents) => self
.base
.inline_content_sizes(layout_context, constraint_space, contents),
}
} }
/// Computes the tentative intrinsic block sizes that may be needed while computing /// Computes the tentative intrinsic block sizes that may be needed while computing
@ -193,7 +182,6 @@ impl IndependentFormattingContext {
// See <https://github.com/w3c/csswg-drafts/issues/12333> regarding the difference // See <https://github.com/w3c/csswg-drafts/issues/12333> regarding the difference
// in behavior for the replaced and non-replaced cases. // in behavior for the replaced and non-replaced cases.
match &self.contents { match &self.contents {
IndependentFormattingContextContents::NonReplaced(_) => None,
IndependentFormattingContextContents::Replaced(contents) => { IndependentFormattingContextContents::Replaced(contents) => {
// For replaced elements with no ratio, the returned value doesn't matter. // For replaced elements with no ratio, the returned value doesn't matter.
let ratio = preferred_aspect_ratio?; let ratio = preferred_aspect_ratio?;
@ -202,6 +190,7 @@ impl IndependentFormattingContext {
let block_size = ratio.compute_dependent_size(Direction::Block, inline_size); let block_size = ratio.compute_dependent_size(Direction::Block, inline_size);
Some(block_size.into()) Some(block_size.into())
}, },
_ => None,
} }
} }
@ -225,32 +214,6 @@ impl IndependentFormattingContext {
) )
} }
pub(crate) fn preferred_aspect_ratio(
&self,
padding_border_sums: &LogicalVec2<Au>,
) -> Option<AspectRatio> {
match &self.contents {
IndependentFormattingContextContents::NonReplaced(content) => {
content.preferred_aspect_ratio()
},
IndependentFormattingContextContents::Replaced(content) => {
content.preferred_aspect_ratio(self.style(), padding_border_sums)
},
}
}
#[inline]
pub(crate) fn layout_style(&self) -> LayoutStyle {
match &self.contents {
IndependentFormattingContextContents::NonReplaced(content) => {
content.layout_style(&self.base)
},
IndependentFormattingContextContents::Replaced(content) => {
content.layout_style(&self.base)
},
}
}
pub(crate) fn repair_style( pub(crate) fn repair_style(
&mut self, &mut self,
context: &SharedStyleContext, context: &SharedStyleContext,
@ -259,13 +222,83 @@ impl IndependentFormattingContext {
) { ) {
self.base.repair_style(new_style); self.base.repair_style(new_style);
match &mut self.contents { match &mut self.contents {
IndependentFormattingContextContents::NonReplaced(content) => {
content.repair_style(context, node, new_style);
},
IndependentFormattingContextContents::Replaced(..) => {}, IndependentFormattingContextContents::Replaced(..) => {},
IndependentFormattingContextContents::Flow(block_formatting_context) => {
block_formatting_context.repair_style(node, new_style);
},
IndependentFormattingContextContents::Flex(flex_container) => {
flex_container.repair_style(new_style)
},
IndependentFormattingContextContents::Grid(taffy_container) => {
taffy_container.repair_style(new_style)
},
IndependentFormattingContextContents::Table(table) => {
table.repair_style(context, new_style)
},
} }
} }
#[inline]
pub(crate) fn is_table(&self) -> bool {
matches!(
&self.contents,
IndependentFormattingContextContents::Table(_)
)
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn layout_without_caching(
&self,
layout_context: &LayoutContext,
positioning_context: &mut PositioningContext,
containing_block_for_children: &ContainingBlock,
containing_block: &ContainingBlock,
preferred_aspect_ratio: Option<AspectRatio>,
depends_on_block_constraints: bool,
lazy_block_size: &LazySize,
) -> CacheableLayoutResult {
match &self.contents {
IndependentFormattingContextContents::Replaced(replaced) => replaced.layout(
layout_context,
containing_block_for_children,
preferred_aspect_ratio,
&self.base,
depends_on_block_constraints,
lazy_block_size,
),
IndependentFormattingContextContents::Flow(bfc) => bfc.layout(
layout_context,
positioning_context,
containing_block_for_children,
depends_on_block_constraints,
),
IndependentFormattingContextContents::Flex(fc) => fc.layout(
layout_context,
positioning_context,
containing_block_for_children,
depends_on_block_constraints,
lazy_block_size,
),
IndependentFormattingContextContents::Grid(fc) => fc.layout(
layout_context,
positioning_context,
containing_block_for_children,
containing_block,
),
IndependentFormattingContextContents::Table(table) => table.layout(
layout_context,
positioning_context,
containing_block_for_children,
containing_block,
depends_on_block_constraints,
),
}
}
#[servo_tracing::instrument(
name = "IndependentFormattingContext::layout_with_caching",
skip_all
)]
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub(crate) fn layout( pub(crate) fn layout(
&self, &self,
@ -277,94 +310,7 @@ impl IndependentFormattingContext {
depends_on_block_constraints: bool, depends_on_block_constraints: bool,
lazy_block_size: &LazySize, lazy_block_size: &LazySize,
) -> CacheableLayoutResult { ) -> CacheableLayoutResult {
match &self.contents { if let Some(cache) = self.base.cached_layout_result.borrow().as_ref() {
IndependentFormattingContextContents::NonReplaced(content) => content.layout(
layout_context,
positioning_context,
containing_block_for_children,
containing_block,
&self.base,
depends_on_block_constraints,
lazy_block_size,
),
IndependentFormattingContextContents::Replaced(content) => content.layout(
layout_context,
containing_block_for_children,
preferred_aspect_ratio,
&self.base,
depends_on_block_constraints,
lazy_block_size,
),
}
}
#[inline]
pub(crate) fn is_table(&self) -> bool {
matches!(
&self.contents,
IndependentFormattingContextContents::NonReplaced(
IndependentNonReplacedContents::Table(_)
)
)
}
}
impl IndependentNonReplacedContents {
pub(crate) fn layout_without_caching(
&self,
layout_context: &LayoutContext,
positioning_context: &mut PositioningContext,
containing_block_for_children: &ContainingBlock,
containing_block: &ContainingBlock,
depends_on_block_constraints: bool,
lazy_block_size: &LazySize,
) -> CacheableLayoutResult {
match self {
IndependentNonReplacedContents::Flow(bfc) => bfc.layout(
layout_context,
positioning_context,
containing_block_for_children,
depends_on_block_constraints,
),
IndependentNonReplacedContents::Flex(fc) => fc.layout(
layout_context,
positioning_context,
containing_block_for_children,
depends_on_block_constraints,
lazy_block_size,
),
IndependentNonReplacedContents::Grid(fc) => fc.layout(
layout_context,
positioning_context,
containing_block_for_children,
containing_block,
),
IndependentNonReplacedContents::Table(table) => table.layout(
layout_context,
positioning_context,
containing_block_for_children,
containing_block,
depends_on_block_constraints,
),
}
}
#[servo_tracing::instrument(
name = "IndependentNonReplacedContents::layout_with_caching",
skip_all
)]
#[allow(clippy::too_many_arguments)]
pub(crate) fn layout(
&self,
layout_context: &LayoutContext,
positioning_context: &mut PositioningContext,
containing_block_for_children: &ContainingBlock,
containing_block: &ContainingBlock,
base: &LayoutBoxBase,
depends_on_block_constraints: bool,
lazy_block_size: &LazySize,
) -> CacheableLayoutResult {
if let Some(cache) = base.cached_layout_result.borrow().as_ref() {
let cache = &**cache; let cache = &**cache;
if cache.containing_block_for_children_size.inline == if cache.containing_block_for_children_size.inline ==
containing_block_for_children.size.inline && containing_block_for_children.size.inline &&
@ -390,64 +336,58 @@ impl IndependentNonReplacedContents {
&mut child_positioning_context, &mut child_positioning_context,
containing_block_for_children, containing_block_for_children,
containing_block, containing_block,
preferred_aspect_ratio,
depends_on_block_constraints, depends_on_block_constraints,
lazy_block_size, lazy_block_size,
); );
*base.cached_layout_result.borrow_mut() = Some(Box::new(CacheableLayoutResultAndInputs { *self.base.cached_layout_result.borrow_mut() =
result: result.clone(), Some(Box::new(CacheableLayoutResultAndInputs {
positioning_context: child_positioning_context.clone(), result: result.clone(),
containing_block_for_children_size: containing_block_for_children.size.clone(), positioning_context: child_positioning_context.clone(),
})); containing_block_for_children_size: containing_block_for_children.size.clone(),
}));
positioning_context.append(child_positioning_context); positioning_context.append(child_positioning_context);
result result
} }
#[inline] #[inline]
pub(crate) fn layout_style<'a>(&'a self, base: &'a LayoutBoxBase) -> LayoutStyle<'a> { pub(crate) fn layout_style(&self) -> LayoutStyle {
match self { match &self.contents {
IndependentNonReplacedContents::Flow(fc) => fc.layout_style(base), IndependentFormattingContextContents::Replaced(fc) => fc.layout_style(&self.base),
IndependentNonReplacedContents::Flex(fc) => fc.layout_style(), IndependentFormattingContextContents::Flow(fc) => fc.layout_style(&self.base),
IndependentNonReplacedContents::Grid(fc) => fc.layout_style(), IndependentFormattingContextContents::Flex(fc) => fc.layout_style(),
IndependentNonReplacedContents::Table(fc) => fc.layout_style(None), IndependentFormattingContextContents::Grid(fc) => fc.layout_style(),
IndependentFormattingContextContents::Table(fc) => fc.layout_style(None),
} }
} }
#[inline] #[inline]
pub(crate) fn preferred_aspect_ratio(&self) -> Option<AspectRatio> { pub(crate) fn preferred_aspect_ratio(
// TODO: support preferred aspect ratios on non-replaced boxes. &self,
None padding_border_sums: &LogicalVec2<Au>,
} ) -> Option<AspectRatio> {
match &self.contents {
fn repair_style( IndependentFormattingContextContents::Replaced(replaced) => {
&mut self, replaced.preferred_aspect_ratio(self.style(), padding_border_sums)
context: &SharedStyleContext,
node: &ServoLayoutNode,
new_style: &Arc<ComputedValues>,
) {
match self {
IndependentNonReplacedContents::Flow(block_formatting_context) => {
block_formatting_context.repair_style(node, new_style);
}, },
IndependentNonReplacedContents::Flex(flex_container) => { // TODO: support preferred aspect ratios on non-replaced boxes.
flex_container.repair_style(new_style) _ => None,
},
IndependentNonReplacedContents::Grid(taffy_container) => {
taffy_container.repair_style(new_style)
},
IndependentNonReplacedContents::Table(table) => table.repair_style(context, new_style),
} }
} }
} }
impl ComputeInlineContentSizes for IndependentNonReplacedContents { impl ComputeInlineContentSizes for IndependentFormattingContextContents {
fn compute_inline_content_sizes( fn compute_inline_content_sizes(
&self, &self,
layout_context: &LayoutContext, layout_context: &LayoutContext,
constraint_space: &ConstraintSpace, constraint_space: &ConstraintSpace,
) -> InlineContentSizesResult { ) -> InlineContentSizesResult {
match self { match self {
Self::Replaced(inner) => {
inner.compute_inline_content_sizes(layout_context, constraint_space)
},
Self::Flow(inner) => inner Self::Flow(inner) => inner
.contents .contents
.compute_inline_content_sizes(layout_context, constraint_space), .compute_inline_content_sizes(layout_context, constraint_space),

View file

@ -585,7 +585,6 @@ impl ReplacedContents {
depends_on_block_constraints: bool, depends_on_block_constraints: bool,
lazy_block_size: &LazySize, lazy_block_size: &LazySize,
) -> CacheableLayoutResult { ) -> CacheableLayoutResult {
// TODO: consider caching the result in LayoutBoxBase like we do for non-replaced.
let writing_mode = base.style.writing_mode; let writing_mode = base.style.writing_mode;
let inline_size = containing_block_for_children.size.inline; let inline_size = containing_block_for_children.size.inline;
let content_block_size = self.content_size( let content_block_size = self.content_size(

View file

@ -25,7 +25,6 @@ use crate::dom_traversal::{Contents, NodeAndStyleInfo, NonReplacedContents, Trav
use crate::flow::{BlockContainerBuilder, BlockFormattingContext}; use crate::flow::{BlockContainerBuilder, BlockFormattingContext};
use crate::formatting_contexts::{ use crate::formatting_contexts::{
IndependentFormattingContext, IndependentFormattingContextContents, IndependentFormattingContext, IndependentFormattingContextContents,
IndependentNonReplacedContents,
}; };
use crate::fragment_tree::BaseFragmentInfo; use crate::fragment_tree::BaseFragmentInfo;
use crate::layout_box_base::LayoutBoxBase; use crate::layout_box_base::LayoutBoxBase;
@ -121,9 +120,7 @@ impl Table {
let ifc = IndependentFormattingContext { let ifc = IndependentFormattingContext {
base: LayoutBoxBase::new((&table_info).into(), table_style), base: LayoutBoxBase::new((&table_info).into(), table_style),
contents: IndependentFormattingContextContents::NonReplaced( contents: IndependentFormattingContextContents::Table(table),
IndependentNonReplacedContents::Table(table),
),
}; };
(table_info, ifc) (table_info, ifc)
@ -875,7 +872,7 @@ impl<'dom> TraversalHandler<'dom> for TableBuilderTraversal<'_, 'dom> {
}); });
let caption = old_caption.unwrap_or_else(|| { let caption = old_caption.unwrap_or_else(|| {
let contents = IndependentNonReplacedContents::Flow( let contents = IndependentFormattingContextContents::Flow(
BlockFormattingContext::construct( BlockFormattingContext::construct(
self.context, self.context,
info, info,
@ -888,9 +885,7 @@ impl<'dom> TraversalHandler<'dom> for TableBuilderTraversal<'_, 'dom> {
ArcRefCell::new(TableCaption { ArcRefCell::new(TableCaption {
context: IndependentFormattingContext { context: IndependentFormattingContext {
base: LayoutBoxBase::new(info.into(), info.style.clone()), base: LayoutBoxBase::new(info.into(), info.style.clone()),
contents: IndependentFormattingContextContents::NonReplaced( contents,
contents,
),
}, },
}) })
}); });

View file

@ -136,6 +136,7 @@ impl taffy::LayoutPartialTree for TaffyContainerContext<'_> {
// TODO: re-evaluate sizing constraint conversions in light of recent layout changes // TODO: re-evaluate sizing constraint conversions in light of recent layout changes
let containing_block = &self.content_box_size_override; let containing_block = &self.content_box_size_override;
let style = independent_context.style(); let style = independent_context.style();
let writing_mode = style.writing_mode;
// Adjust known_dimensions from border box to content box // Adjust known_dimensions from border box to content box
let pbm = independent_context let pbm = independent_context
@ -154,43 +155,44 @@ impl taffy::LayoutPartialTree for TaffyContainerContext<'_> {
.height .height
.map(|height| height - pb_sum.block), .map(|height| height - pb_sum.block),
}; };
let preferred_aspect_ratio =
independent_context.preferred_aspect_ratio(&pbm.padding_border_sums);
match &independent_context.contents { // TODO: unify the replaced and non-replaced logic.
IndependentFormattingContextContents::Replaced(replaced) => { if let IndependentFormattingContextContents::Replaced(replaced) =
let content_box_size = replaced &independent_context.contents
.used_size_as_if_inline_element_from_content_box_sizes( {
containing_block, let content_box_size = replaced
style, .used_size_as_if_inline_element_from_content_box_sizes(
independent_context containing_block,
.preferred_aspect_ratio(&pbm.padding_border_sums), style,
LogicalVec2 { preferred_aspect_ratio,
block: &Sizes::new( LogicalVec2 {
option_f32_to_size(content_box_known_dimensions.height), block: &Sizes::new(
Size::Initial, option_f32_to_size(content_box_known_dimensions.height),
Size::Initial, Size::Initial,
), Size::Initial,
inline: &Sizes::new( ),
option_f32_to_size(content_box_known_dimensions.width), inline: &Sizes::new(
Size::Initial, option_f32_to_size(content_box_known_dimensions.width),
Size::Initial, Size::Initial,
), Size::Initial,
}, ),
Size::FitContent.into(), },
pbm.padding_border_sums + pbm.margin.auto_is(Au::zero).sum(), Size::FitContent.into(),
) pbm.padding_border_sums + pbm.margin.auto_is(Au::zero).sum(),
.to_physical_size(self.style.writing_mode); )
.to_physical_size(writing_mode);
// Create fragments if the RunMode if PerformLayout // Create fragments if the RunMode if PerformLayout
// If the RunMode is ComputeSize then only the returned size will be used // If the RunMode is ComputeSize then only the returned size will be used
if inputs.run_mode == RunMode::PerformLayout { if inputs.run_mode == RunMode::PerformLayout {
child.child_fragments = replaced.make_fragments( child.child_fragments =
self.layout_context, replaced.make_fragments(self.layout_context, style, content_box_size);
style, }
content_box_size,
);
}
let computed_size = taffy::Size { let computed_size =
taffy::Size {
width: inputs.known_dimensions.width.unwrap_or_else(|| { width: inputs.known_dimensions.width.unwrap_or_else(|| {
content_box_size.width.to_f32_px() + pb_sum.inline content_box_size.width.to_f32_px() + pb_sum.inline
}), }),
@ -198,98 +200,96 @@ impl taffy::LayoutPartialTree for TaffyContainerContext<'_> {
content_box_size.height.to_f32_px() + pb_sum.block content_box_size.height.to_f32_px() + pb_sum.block
}), }),
}; };
let size = inputs.known_dimensions.unwrap_or(computed_size); let size = inputs.known_dimensions.unwrap_or(computed_size);
taffy::LayoutOutput { taffy::LayoutOutput {
size, size,
..taffy::LayoutOutput::DEFAULT ..taffy::LayoutOutput::DEFAULT
} }
}, } else {
// Compute inline size
IndependentFormattingContextContents::NonReplaced(non_replaced) => { let inline_size = content_box_known_dimensions.width.unwrap_or_else(|| {
// Compute inline size let constraint_space = ConstraintSpace {
let inline_size = content_box_known_dimensions.width.unwrap_or_else(|| { // TODO: pass min- and max- size
let constraint_space = ConstraintSpace { block_size: SizeConstraint::new(
// TODO: pass min- and max- size inputs.parent_size.height.map(Au::from_f32_px),
block_size: SizeConstraint::new( Au::zero(),
inputs.parent_size.height.map(Au::from_f32_px), None,
Au::zero(), ),
None, writing_mode,
), preferred_aspect_ratio,
writing_mode: self.style.writing_mode,
preferred_aspect_ratio: non_replaced.preferred_aspect_ratio(),
};
let result = independent_context
.inline_content_sizes(self.layout_context, &constraint_space);
let adjusted_available_space = inputs
.available_space
.width
.map_definite_value(|width| width - content_box_inset.inline);
resolve_content_size(adjusted_available_space, result.sizes)
});
// Return early if only inline content sizes are requested
if inputs.run_mode == RunMode::ComputeSize &&
inputs.axis == RequestedAxis::Horizontal
{
return taffy::LayoutOutput::from_outer_size(taffy::Size {
width: inline_size + pb_sum.inline,
// If RequestedAxis is Horizontal then height will be ignored.
height: 0.0,
});
}
let content_box_size_override = ContainingBlock {
size: ContainingBlockSize {
inline: Au::from_f32_px(inline_size),
block: content_box_known_dimensions
.height
.map(Au::from_f32_px)
.map_or_else(SizeConstraint::default, SizeConstraint::Definite),
},
style,
}; };
let lazy_block_size = match content_box_known_dimensions.height { let result = independent_context
// FIXME: use the correct min/max sizes. .inline_content_sizes(self.layout_context, &constraint_space);
None => LazySize::intrinsic(), let adjusted_available_space = inputs
Some(height) => Au::from_f32_px(height).into(), .available_space
}; .width
.map_definite_value(|width| width - content_box_inset.inline);
child.positioning_context = PositioningContext::default(); resolve_content_size(adjusted_available_space, result.sizes)
let layout = non_replaced.layout_without_caching( });
self.layout_context,
&mut child.positioning_context,
&content_box_size_override,
containing_block,
false, /* depends_on_block_constraints */
&lazy_block_size,
);
child.child_fragments = layout.fragments; // Return early if only inline content sizes are requested
self.child_specific_layout_infos[usize::from(node_id)] = if inputs.run_mode == RunMode::ComputeSize &&
layout.specific_layout_info; inputs.axis == RequestedAxis::Horizontal
{
let block_size = lazy_block_size return taffy::LayoutOutput::from_outer_size(taffy::Size {
.resolve(|| layout.content_block_size)
.to_f32_px();
let computed_size = taffy::Size {
width: inline_size + pb_sum.inline, width: inline_size + pb_sum.inline,
height: block_size + pb_sum.block, // If RequestedAxis is Horizontal then height will be ignored.
}; height: 0.0,
let size = inputs.known_dimensions.unwrap_or(computed_size); });
}
taffy::LayoutOutput { let content_box_size_override = ContainingBlock {
size, size: ContainingBlockSize {
first_baselines: taffy::Point { inline: Au::from_f32_px(inline_size),
x: None, block: content_box_known_dimensions
y: layout.baselines.first.map(|au| au.to_f32_px()), .height
}, .map(Au::from_f32_px)
..taffy::LayoutOutput::DEFAULT .map_or_else(SizeConstraint::default, SizeConstraint::Definite),
} },
}, style,
};
let lazy_block_size = match content_box_known_dimensions.height {
// FIXME: use the correct min/max sizes.
None => LazySize::intrinsic(),
Some(height) => Au::from_f32_px(height).into(),
};
child.positioning_context = PositioningContext::default();
let layout = independent_context.layout_without_caching(
self.layout_context,
&mut child.positioning_context,
&content_box_size_override,
containing_block,
preferred_aspect_ratio,
false, /* depends_on_block_constraints */
&lazy_block_size,
);
child.child_fragments = layout.fragments;
self.child_specific_layout_infos[usize::from(node_id)] =
layout.specific_layout_info;
let block_size = lazy_block_size
.resolve(|| layout.content_block_size)
.to_f32_px();
let computed_size = taffy::Size {
width: inline_size + pb_sum.inline,
height: block_size + pb_sum.block,
};
let size = inputs.known_dimensions.unwrap_or(computed_size);
taffy::LayoutOutput {
size,
first_baselines: taffy::Point {
x: None,
y: layout.baselines.first.map(|au| au.to_f32_px()),
},
..taffy::LayoutOutput::DEFAULT
}
} }
}, },
) )

View file

@ -19,9 +19,7 @@ use crate::construct_modern::{ModernContainerBuilder, ModernItemKind};
use crate::context::LayoutContext; use crate::context::LayoutContext;
use crate::dom::LayoutBox; use crate::dom::LayoutBox;
use crate::dom_traversal::{NodeAndStyleInfo, NonReplacedContents}; use crate::dom_traversal::{NodeAndStyleInfo, NonReplacedContents};
use crate::formatting_contexts::{ use crate::formatting_contexts::IndependentFormattingContext;
IndependentFormattingContext, IndependentFormattingContextContents,
};
use crate::fragment_tree::Fragment; use crate::fragment_tree::Fragment;
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext}; use crate::positioned::{AbsolutelyPositionedBox, PositioningContext};
@ -178,10 +176,7 @@ impl TaffyItemBox {
fn is_in_flow_replaced(&self) -> bool { fn is_in_flow_replaced(&self) -> bool {
match &self.taffy_level_box { match &self.taffy_level_box {
TaffyItemBoxInner::InFlowBox(fc) => match fc.contents { TaffyItemBoxInner::InFlowBox(fc) => fc.is_replaced(),
IndependentFormattingContextContents::NonReplaced(_) => false,
IndependentFormattingContextContents::Replaced(_) => true,
},
TaffyItemBoxInner::OutOfFlowAbsolutelyPositionedBox(_) => false, TaffyItemBoxInner::OutOfFlowAbsolutelyPositionedBox(_) => false,
} }
} }