aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/layout_2020/construct_modern.rs17
-rw-r--r--components/layout_2020/dom_traversal.rs10
-rw-r--r--components/layout_2020/flexbox/layout.rs75
-rw-r--r--components/layout_2020/flow/inline/mod.rs15
-rw-r--r--components/layout_2020/flow/mod.rs335
-rw-r--r--components/layout_2020/flow/root.rs6
-rw-r--r--components/layout_2020/formatting_contexts.rs215
-rw-r--r--components/layout_2020/layout_box_base.rs61
-rw-r--r--components/layout_2020/lib.rs1
-rw-r--r--components/layout_2020/lists.rs4
-rw-r--r--components/layout_2020/positioned.rs34
-rw-r--r--components/layout_2020/replaced.rs4
-rw-r--r--components/layout_2020/table/construct.rs41
-rw-r--r--components/layout_2020/table/layout.rs6
-rw-r--r--components/layout_2020/table/mod.rs4
-rw-r--r--components/layout_2020/taffy/layout.rs34
16 files changed, 423 insertions, 439 deletions
diff --git a/components/layout_2020/construct_modern.rs b/components/layout_2020/construct_modern.rs
index 5ff9aa08216..713954a39c8 100644
--- a/components/layout_2020/construct_modern.rs
+++ b/components/layout_2020/construct_modern.rs
@@ -15,9 +15,10 @@ use crate::dom_traversal::{Contents, NodeAndStyleInfo, TraversalHandler};
use crate::flow::inline::construct::InlineFormattingContextBuilder;
use crate::flow::{BlockContainer, BlockFormattingContext};
use crate::formatting_contexts::{
- IndependentFormattingContext, NonReplacedFormattingContext,
- NonReplacedFormattingContextContents,
+ IndependentFormattingContext, IndependentFormattingContextContents,
+ IndependentNonReplacedContents,
};
+use crate::layout_box_base::LayoutBoxBase;
use crate::style_ext::DisplayGeneratingBox;
/// <https://drafts.csswg.org/css-flexbox/#flex-items>
@@ -173,16 +174,12 @@ where
BlockContainer::InlineFormattingContext(inline_formatting_context),
);
let info = &self.info.new_anonymous(anonymous_style.clone().unwrap());
- let non_replaced = NonReplacedFormattingContext {
- base_fragment_info: info.into(),
- style: info.style.clone(),
- content_sizes_result: Default::default(),
- contents: NonReplacedFormattingContextContents::Flow(
- block_formatting_context,
+ let formatting_context = IndependentFormattingContext {
+ base: LayoutBoxBase::new(info.into(), info.style.clone()),
+ contents: IndependentFormattingContextContents::NonReplaced(
+ IndependentNonReplacedContents::Flow(block_formatting_context),
),
};
- let formatting_context =
- IndependentFormattingContext::NonReplaced(non_replaced);
Some(ModernItem {
kind: ModernItemKind::InFlow,
diff --git a/components/layout_2020/dom_traversal.rs b/components/layout_2020/dom_traversal.rs
index c6a920aa060..2c532e2ebc4 100644
--- a/components/layout_2020/dom_traversal.rs
+++ b/components/layout_2020/dom_traversal.rs
@@ -16,7 +16,7 @@ use style::values::generics::counters::{Content, ContentItem};
use crate::context::LayoutContext;
use crate::dom::{BoxSlot, LayoutBox, NodeExt};
use crate::fragment_tree::{BaseFragmentInfo, FragmentFlags, Tag};
-use crate::replaced::ReplacedContent;
+use crate::replaced::ReplacedContents;
use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside, DisplayOutside};
#[derive(Clone, Copy, Debug)]
@@ -126,7 +126,7 @@ pub(super) enum Contents {
NonReplaced(NonReplacedContents),
/// Example: an `<img src=…>` element.
/// <https://drafts.csswg.org/css2/conform.html#replaced-element>
- Replaced(ReplacedContent),
+ Replaced(ReplacedContents),
}
#[derive(Debug)]
@@ -141,7 +141,7 @@ pub(super) enum NonReplacedContents {
#[derive(Debug)]
pub(super) enum PseudoElementContentItem {
Text(String),
- Replaced(ReplacedContent),
+ Replaced(ReplacedContents),
}
pub(super) trait TraversalHandler<'dom, Node>
@@ -216,7 +216,7 @@ fn traverse_element<'dom, Node>(
) where
Node: NodeExt<'dom>,
{
- let replaced = ReplacedContent::for_element(element, context);
+ let replaced = ReplacedContents::for_element(element, context);
let style = element.style(context);
match Display::from(style.get_box().display) {
Display::None => element.unset_all_boxes(),
@@ -421,7 +421,7 @@ where
},
ContentItem::Image(image) => {
if let Some(replaced_content) =
- ReplacedContent::from_image(element, context, image)
+ ReplacedContents::from_image(element, context, image)
{
vec.push(PseudoElementContentItem::Replaced(replaced_content));
}
diff --git a/components/layout_2020/flexbox/layout.rs b/components/layout_2020/flexbox/layout.rs
index 0848c3ab2f0..2acdc862de4 100644
--- a/components/layout_2020/flexbox/layout.rs
+++ b/components/layout_2020/flexbox/layout.rs
@@ -30,7 +30,9 @@ use super::{
};
use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
-use crate::formatting_contexts::{Baselines, IndependentFormattingContext, IndependentLayout};
+use crate::formatting_contexts::{
+ Baselines, IndependentFormattingContextContents, IndependentLayout,
+};
use crate::fragment_tree::{BoxFragment, CollapsedBlockMargins, Fragment, FragmentFlags};
use crate::geom::{AuOrAuto, LogicalRect, LogicalSides, LogicalVec2, Size};
use crate::positioned::{
@@ -1893,8 +1895,8 @@ impl FlexItem<'_> {
}),
};
- let context = &self.box_.independent_formatting_context;
- let item_writing_mode = context.style().writing_mode;
+ let independent_formatting_context = &self.box_.independent_formatting_context;
+ let item_writing_mode = independent_formatting_context.style().writing_mode;
let item_is_horizontal = item_writing_mode.is_horizontal();
let flex_axis = flex_context.config.flex_axis;
let cross_axis_is_item_block_axis = cross_axis_is_item_block_axis(
@@ -1922,7 +1924,7 @@ impl FlexItem<'_> {
item_writing_mode,
self.preferred_aspect_ratio,
);
- context
+ independent_formatting_context
.inline_content_sizes(flex_context.layout_context, &constraint_space)
.sizes
.shrink_to_fit(stretch_size)
@@ -1945,26 +1947,25 @@ impl FlexItem<'_> {
};
let container_writing_mode = containing_block.style.writing_mode;
- match context {
- IndependentFormattingContext::Replaced(replaced) => {
- let size = replaced
- .contents
- .used_size_as_if_inline_element_from_content_box_sizes(
- containing_block,
- &replaced.style,
- self.preferred_aspect_ratio,
- LogicalVec2 {
- inline: Size::Numeric(inline_size),
- block: block_size.non_auto().map_or(Size::Initial, Size::Numeric),
- },
- flex_axis
- .vec2_to_flow_relative(self.content_min_size)
- .map(|size| Size::Numeric(*size)),
- flex_axis
- .vec2_to_flow_relative(self.content_max_size)
- .map(|size| size.map_or(Size::Initial, Size::Numeric)),
- flex_axis.vec2_to_flow_relative(self.pbm_auto_is_zero),
- );
+ let item_style = independent_formatting_context.style();
+ match &independent_formatting_context.contents {
+ IndependentFormattingContextContents::Replaced(replaced) => {
+ let size = replaced.used_size_as_if_inline_element_from_content_box_sizes(
+ containing_block,
+ item_style,
+ self.preferred_aspect_ratio,
+ LogicalVec2 {
+ inline: Size::Numeric(inline_size),
+ block: block_size.non_auto().map_or(Size::Initial, Size::Numeric),
+ },
+ flex_axis
+ .vec2_to_flow_relative(self.content_min_size)
+ .map(|size| Size::Numeric(*size)),
+ flex_axis
+ .vec2_to_flow_relative(self.content_max_size)
+ .map(|size| size.map_or(Size::Initial, Size::Numeric)),
+ flex_axis.vec2_to_flow_relative(self.pbm_auto_is_zero),
+ );
let hypothetical_cross_size = flex_axis.vec2_to_flex_relative(size).cross;
if let Some(non_stretch_layout_result) = non_stretch_layout_result {
@@ -1979,10 +1980,8 @@ impl FlexItem<'_> {
}
}
- let fragments = replaced.contents.make_fragments(
- &replaced.style,
- size.to_physical_size(container_writing_mode),
- );
+ let fragments = replaced
+ .make_fragments(item_style, size.to_physical_size(container_writing_mode));
Some(FlexItemLayoutResult {
hypothetical_cross_size,
@@ -2000,7 +1999,7 @@ impl FlexItem<'_> {
baseline_relative_to_margin_box: None,
})
},
- IndependentFormattingContext::NonReplaced(non_replaced) => {
+ IndependentFormattingContextContents::NonReplaced(non_replaced) => {
let calculate_hypothetical_cross_size = |content_block_size| {
self.content_box_size
.cross
@@ -2020,7 +2019,7 @@ impl FlexItem<'_> {
let item_as_containing_block = ContainingBlock {
inline_size,
block_size,
- style: &non_replaced.style,
+ style: item_style,
};
if let Some(non_stretch_layout_result) = non_stretch_layout_result {
@@ -2067,7 +2066,7 @@ impl FlexItem<'_> {
let item_writing_mode_is_orthogonal_to_container_writing_mode =
flex_context.config.writing_mode.is_horizontal() !=
- non_replaced.style.writing_mode.is_horizontal();
+ item_style.writing_mode.is_horizontal();
let has_compatible_baseline = match flex_axis {
FlexAxis::Row => !item_writing_mode_is_orthogonal_to_container_writing_mode,
FlexAxis::Column => item_writing_mode_is_orthogonal_to_container_writing_mode,
@@ -2752,8 +2751,9 @@ impl FlexItemBox {
.collects_for_nearest_positioned_ancestor(),
);
- match &self.independent_formatting_context {
- IndependentFormattingContext::Replaced(replaced) => {
+ let style = self.independent_formatting_context.style();
+ match &self.independent_formatting_context.contents {
+ IndependentFormattingContextContents::Replaced(replaced) => {
content_box_size.inline = content_box_size.inline.map(|v| v.max(Au::zero()));
if intrinsic_sizing_mode == IntrinsicSizingMode::Size {
content_box_size.block = AuOrAuto::Auto;
@@ -2761,10 +2761,9 @@ impl FlexItemBox {
max_size.block = None;
}
replaced
- .contents
.used_size_as_if_inline_element_from_content_box_sizes(
flex_context.containing_block,
- &replaced.style,
+ style,
preferred_aspect_ratio,
content_box_size
.map(|size| size.non_auto().map_or(Size::Initial, Size::Numeric)),
@@ -2775,7 +2774,7 @@ impl FlexItemBox {
)
.block
},
- IndependentFormattingContext::NonReplaced(non_replaced) => {
+ IndependentFormattingContextContents::NonReplaced(non_replaced) => {
// TODO: This is wrong if the item writing mode is different from the flex
// container's writing mode.
let inline_size = content_box_size
@@ -2792,7 +2791,7 @@ impl FlexItemBox {
} else {
let constraint_space = ConstraintSpace::new(
SizeConstraint::default(),
- non_replaced.style.writing_mode,
+ style.writing_mode,
non_replaced.preferred_aspect_ratio(),
);
non_replaced
@@ -2808,7 +2807,7 @@ impl FlexItemBox {
let item_as_containing_block = ContainingBlock {
inline_size,
block_size: AuOrAuto::Auto,
- style: &non_replaced.style,
+ style,
};
let content_block_size = || {
if let Some(cache) = &*self.block_content_size_cache.borrow() {
diff --git a/components/layout_2020/flow/inline/mod.rs b/components/layout_2020/flow/inline/mod.rs
index d48f765a55c..a23abcd5d89 100644
--- a/components/layout_2020/flow/inline/mod.rs
+++ b/components/layout_2020/flow/inline/mod.rs
@@ -111,13 +111,14 @@ use webrender_api::FontInstanceKey;
use xi_unicode::linebreak_property;
use super::float::{Clear, PlacementAmongFloats};
+use super::IndependentFormattingContextContents;
use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
use crate::flow::float::{FloatBox, SequentialLayoutState};
use crate::flow::{CollapsibleWithParentStartMargin, FlowLayout};
use crate::formatting_contexts::{
Baselines, IndependentFormattingContext, IndependentLayoutResult,
- NonReplacedFormattingContextContents,
+ IndependentNonReplacedContents,
};
use crate::fragment_tree::{
BoxFragment, CollapsedBlockMargins, CollapsedMargin, Fragment, FragmentFlags,
@@ -2034,13 +2035,11 @@ impl IndependentFormattingContext {
match self.style().clone_baseline_source() {
BaselineSource::First => baselines.first,
BaselineSource::Last => baselines.last,
- BaselineSource::Auto => {
- if let Self::NonReplaced(non_replaced) = self {
- if let NonReplacedFormattingContextContents::Flow(_) = non_replaced.contents {
- return baselines.last;
- }
- }
- baselines.first
+ BaselineSource::Auto => match &self.contents {
+ IndependentFormattingContextContents::NonReplaced(
+ IndependentNonReplacedContents::Flow(_),
+ ) => baselines.last,
+ _ => baselines.first,
},
}
}
diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs
index 46ccf221b41..4f76a39b6eb 100644
--- a/components/layout_2020/flow/mod.rs
+++ b/components/layout_2020/flow/mod.rs
@@ -27,8 +27,8 @@ use crate::flow::float::{
SequentialLayoutState,
};
use crate::formatting_contexts::{
- Baselines, IndependentFormattingContext, IndependentLayout, IndependentLayoutResult,
- NonReplacedFormattingContext,
+ Baselines, IndependentFormattingContext, IndependentFormattingContextContents,
+ IndependentLayout, IndependentLayoutResult, IndependentNonReplacedContents,
};
use crate::fragment_tree::{
BaseFragmentInfo, BoxFragment, CollapsedBlockMargins, CollapsedMargin, Fragment, FragmentFlags,
@@ -37,8 +37,9 @@ use crate::geom::{
AuOrAuto, LogicalRect, LogicalSides, LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSides,
Size, ToLogical, ToLogicalWithContainingBlock,
};
+use crate::layout_box_base::LayoutBoxBase;
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext, PositioningContextLength};
-use crate::replaced::ReplacedContent;
+use crate::replaced::ReplacedContents;
use crate::sizing::{self, ContentSizes, InlineContentSizesResult};
use crate::style_ext::{
Clamp, ComputedValuesExt, ContentBoxSizesAndPBMDeprecated, PaddingBorderMargin,
@@ -714,38 +715,20 @@ impl BlockLevelBox {
)
},
)),
- BlockLevelBox::Independent(independent) => match independent {
- IndependentFormattingContext::Replaced(replaced) => {
- Fragment::Box(positioning_context.layout_maybe_position_relative_fragment(
- layout_context,
- containing_block,
- &replaced.style,
- |_positioning_context| {
- layout_in_flow_replaced_block_level(
- containing_block,
- replaced.base_fragment_info,
- &replaced.style,
- &replaced.contents,
- sequential_layout_state,
- )
- },
- ))
- },
- IndependentFormattingContext::NonReplaced(non_replaced) => {
- Fragment::Box(positioning_context.layout_maybe_position_relative_fragment(
- layout_context,
- containing_block,
- &non_replaced.style,
- |positioning_context| {
- non_replaced.layout_in_flow_block_level(
- layout_context,
- positioning_context,
- containing_block,
- sequential_layout_state,
- )
- },
- ))
- },
+ BlockLevelBox::Independent(independent) => {
+ Fragment::Box(positioning_context.layout_maybe_position_relative_fragment(
+ layout_context,
+ containing_block,
+ independent.style(),
+ |positioning_context| {
+ independent.layout_in_flow_block_level(
+ layout_context,
+ positioning_context,
+ containing_block,
+ sequential_layout_state,
+ )
+ },
+ ))
},
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(box_) => {
// The static position of zero here is incorrect, however we do not know
@@ -1006,7 +989,7 @@ fn layout_in_flow_non_replaced_block_level_same_formatting_context(
.with_baselines(flow_layout.baselines)
}
-impl NonReplacedFormattingContext {
+impl IndependentNonReplacedContents {
/// Lay out a normal in flow non-replaced block that establishes an independent
/// formatting context in its containing formatting context.
///
@@ -1014,6 +997,7 @@ impl NonReplacedFormattingContext {
/// - <https://drafts.csswg.org/css2/visudet.html#normal-block>
pub(crate) fn layout_in_flow_block_level(
&self,
+ base: &LayoutBoxBase,
layout_context: &LayoutContext,
positioning_context: &mut PositioningContext,
containing_block: &ContainingBlock,
@@ -1021,6 +1005,7 @@ impl NonReplacedFormattingContext {
) -> BoxFragment {
if let Some(sequential_layout_state) = sequential_layout_state {
return self.layout_in_flow_block_level_sequentially(
+ base,
layout_context,
positioning_context,
containing_block,
@@ -1037,7 +1022,7 @@ impl NonReplacedFormattingContext {
depends_on_block_constraints,
} = solve_containing_block_padding_and_border_for_in_flow_box(
containing_block,
- &self.style,
+ &base.style,
);
let layout = self.layout(
@@ -1079,7 +1064,7 @@ impl NonReplacedFormattingContext {
let block_margins_collapsed_with_children = CollapsedBlockMargins::from_margin(&margin);
let containing_block_writing_mode = containing_block.style.writing_mode;
- let mut base_fragment_info = self.base_fragment_info;
+ let mut base_fragment_info = base.base_fragment_info;
if depends_on_block_constraints {
base_fragment_info.flags.insert(
FragmentFlags::SIZE_DEPENDS_ON_BLOCK_CONSTRAINTS_AND_CAN_BE_CHILD_OF_FLEX_ITEM,
@@ -1087,7 +1072,7 @@ impl NonReplacedFormattingContext {
}
BoxFragment::new(
base_fragment_info,
- self.style.clone(),
+ base.style.clone(),
layout.fragments,
content_rect.to_physical(Some(containing_block)),
pbm.padding.to_physical(containing_block_writing_mode),
@@ -1104,6 +1089,7 @@ impl NonReplacedFormattingContext {
/// layout concerns, such clearing and placing the content next to floats.
fn layout_in_flow_block_level_sequentially(
&self,
+ base: &LayoutBoxBase,
layout_context: &LayoutContext<'_>,
positioning_context: &mut PositioningContext,
containing_block: &ContainingBlock<'_>,
@@ -1116,7 +1102,7 @@ impl NonReplacedFormattingContext {
content_max_box_size,
pbm,
depends_on_block_constraints,
- } = self
+ } = base
.style
.content_box_sizes_and_padding_border_margin(&containing_block.into())
.into();
@@ -1147,6 +1133,7 @@ impl NonReplacedFormattingContext {
let clearance;
let mut content_size;
let mut layout;
+ let style = &base.style;
if let AuOrAuto::LengthPercentage(ref inline_size) = content_box_size.inline {
let inline_size = inline_size
.clamp_between_extremums(content_min_box_size.inline, content_max_box_size.inline);
@@ -1156,7 +1143,7 @@ impl NonReplacedFormattingContext {
&ContainingBlock {
inline_size,
block_size,
- style: &self.style,
+ style,
},
containing_block,
);
@@ -1188,17 +1175,14 @@ impl NonReplacedFormattingContext {
containing_block,
&pbm,
content_size + pbm.padding_border_sums,
- &self.style,
+ style,
);
} else {
// First compute the clear position required by the 'clear' property.
// The code below may then add extra clearance when the element can't fit
// next to floats not covered by 'clear'.
let clear_position = sequential_layout_state.calculate_clear_position(
- Clear::from_style_and_container_writing_mode(
- &self.style,
- containing_block_writing_mode,
- ),
+ Clear::from_style_and_container_writing_mode(style, containing_block_writing_mode),
&collapsed_margin_block_start,
);
let ceiling = clear_position.unwrap_or_else(|| {
@@ -1238,7 +1222,7 @@ impl NonReplacedFormattingContext {
&ContainingBlock {
inline_size: proposed_inline_size,
block_size,
- style: &self.style,
+ style,
},
containing_block,
);
@@ -1347,7 +1331,7 @@ impl NonReplacedFormattingContext {
size: content_size,
};
- let mut base_fragment_info = self.base_fragment_info;
+ let mut base_fragment_info = base.base_fragment_info;
if depends_on_block_constraints {
base_fragment_info.flags.insert(
FragmentFlags::SIZE_DEPENDS_ON_BLOCK_CONSTRAINTS_AND_CAN_BE_CHILD_OF_FLEX_ITEM,
@@ -1356,7 +1340,7 @@ impl NonReplacedFormattingContext {
BoxFragment::new(
base_fragment_info,
- self.style.clone(),
+ style.clone(),
layout.fragments,
content_rect.to_physical(Some(containing_block)),
pbm.padding.to_physical(containing_block_writing_mode),
@@ -1369,121 +1353,127 @@ impl NonReplacedFormattingContext {
}
}
-/// <https://drafts.csswg.org/css2/visudet.html#block-replaced-width>
-/// <https://drafts.csswg.org/css2/visudet.html#inline-replaced-width>
-/// <https://drafts.csswg.org/css2/visudet.html#inline-replaced-height>
-fn layout_in_flow_replaced_block_level(
- containing_block: &ContainingBlock,
- mut base_fragment_info: BaseFragmentInfo,
- style: &Arc<ComputedValues>,
- replaced: &ReplacedContent,
- mut sequential_layout_state: Option<&mut SequentialLayoutState>,
-) -> BoxFragment {
- let content_box_sizes_and_pbm =
- style.content_box_sizes_and_padding_border_margin(&containing_block.into());
- let pbm = &content_box_sizes_and_pbm.pbm;
- let content_size = replaced.used_size_as_if_inline_element(
- containing_block,
- style,
- &content_box_sizes_and_pbm,
- );
+impl ReplacedContents {
+ /// <https://drafts.csswg.org/css2/visudet.html#block-replaced-width>
+ /// <https://drafts.csswg.org/css2/visudet.html#inline-replaced-width>
+ /// <https://drafts.csswg.org/css2/visudet.html#inline-replaced-height>
+ fn layout_in_flow_block_level(
+ &self,
+ base: &LayoutBoxBase,
+ containing_block: &ContainingBlock,
+ mut sequential_layout_state: Option<&mut SequentialLayoutState>,
+ ) -> BoxFragment {
+ let content_box_sizes_and_pbm = base
+ .style
+ .content_box_sizes_and_padding_border_margin(&containing_block.into());
+ let pbm = &content_box_sizes_and_pbm.pbm;
+ let content_size = self.used_size_as_if_inline_element(
+ containing_block,
+ &base.style,
+ &content_box_sizes_and_pbm,
+ );
- let margin_inline_start;
- let margin_inline_end;
- let effective_margin_inline_start;
- let (margin_block_start, margin_block_end) = solve_block_margins_for_in_flow_block_level(pbm);
+ let margin_inline_start;
+ let margin_inline_end;
+ let effective_margin_inline_start;
+ let (margin_block_start, margin_block_end) =
+ solve_block_margins_for_in_flow_block_level(pbm);
- let containing_block_writing_mode = containing_block.style.writing_mode;
- let physical_content_size = content_size.to_physical_size(containing_block_writing_mode);
- let fragments = replaced.make_fragments(style, physical_content_size);
+ let containing_block_writing_mode = containing_block.style.writing_mode;
+ let physical_content_size = content_size.to_physical_size(containing_block_writing_mode);
+ let fragments = self.make_fragments(&base.style, physical_content_size);
- let clearance;
- if let Some(ref mut sequential_layout_state) = sequential_layout_state {
- // From https://drafts.csswg.org/css2/#floats:
- // "The border box of a table, a block-level replaced element, or an element in
- // the normal flow that establishes a new block formatting context (such as an
- // element with overflow other than visible) must not overlap the margin box of
- // any floats in the same block formatting context as the element itself. If
- // necessary, implementations should clear the said element by placing it below
- // any preceding floats, but may place it adjacent to such floats if there is
- // sufficient space. They may even make the border box of said element narrower
- // than defined by section 10.3.3. CSS 2 does not define when a UA may put said
- // element next to the float or by how much said element may become narrower."
- let collapsed_margin_block_start = CollapsedMargin::new(margin_block_start);
- let size = content_size + pbm.padding_border_sums;
- (
- clearance,
- (margin_inline_start, margin_inline_end),
- effective_margin_inline_start,
- ) = solve_clearance_and_inline_margins_avoiding_floats(
- sequential_layout_state,
- &collapsed_margin_block_start,
- containing_block,
- pbm,
- size,
- style,
- );
+ let clearance;
+ if let Some(ref mut sequential_layout_state) = sequential_layout_state {
+ // From https://drafts.csswg.org/css2/#floats:
+ // "The border box of a table, a block-level replaced element, or an element in
+ // the normal flow that establishes a new block formatting context (such as an
+ // element with overflow other than visible) must not overlap the margin box of
+ // any floats in the same block formatting context as the element itself. If
+ // necessary, implementations should clear the said element by placing it below
+ // any preceding floats, but may place it adjacent to such floats if there is
+ // sufficient space. They may even make the border box of said element narrower
+ // than defined by section 10.3.3. CSS 2 does not define when a UA may put said
+ // element next to the float or by how much said element may become narrower."
+ let collapsed_margin_block_start = CollapsedMargin::new(margin_block_start);
+ let size = content_size + pbm.padding_border_sums;
+ (
+ clearance,
+ (margin_inline_start, margin_inline_end),
+ effective_margin_inline_start,
+ ) = solve_clearance_and_inline_margins_avoiding_floats(
+ sequential_layout_state,
+ &collapsed_margin_block_start,
+ containing_block,
+ pbm,
+ size,
+ &base.style,
+ );
- // Clearance prevents margin collapse between this block and previous ones,
- // so in that case collapse margins before adjoining them below.
- if clearance.is_some() {
+ // Clearance prevents margin collapse between this block and previous ones,
+ // so in that case collapse margins before adjoining them below.
+ if clearance.is_some() {
+ sequential_layout_state.collapse_margins();
+ }
+ sequential_layout_state.adjoin_assign(&collapsed_margin_block_start);
+
+ // Margins can never collapse into replaced elements.
sequential_layout_state.collapse_margins();
- }
- sequential_layout_state.adjoin_assign(&collapsed_margin_block_start);
+ sequential_layout_state
+ .advance_block_position(size.block + clearance.unwrap_or_else(Au::zero));
+ sequential_layout_state.adjoin_assign(&CollapsedMargin::new(margin_block_end));
+ } else {
+ clearance = None;
+ (
+ (margin_inline_start, margin_inline_end),
+ effective_margin_inline_start,
+ ) = solve_inline_margins_for_in_flow_block_level(
+ containing_block,
+ pbm,
+ content_size.inline,
+ );
+ };
- // Margins can never collapse into replaced elements.
- sequential_layout_state.collapse_margins();
- sequential_layout_state
- .advance_block_position(size.block + clearance.unwrap_or_else(Au::zero));
- sequential_layout_state.adjoin_assign(&CollapsedMargin::new(margin_block_end));
- } else {
- clearance = None;
- (
- (margin_inline_start, margin_inline_end),
- effective_margin_inline_start,
- ) = solve_inline_margins_for_in_flow_block_level(
- containing_block,
- pbm,
- content_size.inline,
- );
- };
+ let margin = LogicalSides {
+ inline_start: margin_inline_start,
+ inline_end: margin_inline_end,
+ block_start: margin_block_start,
+ block_end: margin_block_end,
+ };
- let margin = LogicalSides {
- inline_start: margin_inline_start,
- inline_end: margin_inline_end,
- block_start: margin_block_start,
- block_end: margin_block_end,
- };
+ let start_corner = LogicalVec2 {
+ block: pbm.padding.block_start +
+ pbm.border.block_start +
+ clearance.unwrap_or_else(Au::zero),
+ inline: pbm.padding.inline_start +
+ pbm.border.inline_start +
+ effective_margin_inline_start,
+ };
+ let content_rect = LogicalRect {
+ start_corner,
+ size: content_size,
+ }
+ .to_physical(Some(containing_block));
- let start_corner = LogicalVec2 {
- block: pbm.padding.block_start +
- pbm.border.block_start +
- clearance.unwrap_or_else(Au::zero),
- inline: pbm.padding.inline_start + pbm.border.inline_start + effective_margin_inline_start,
- };
- let content_rect = LogicalRect {
- start_corner,
- size: content_size,
- }
- .to_physical(Some(containing_block));
+ let mut base_fragment_info = base.base_fragment_info;
+ if content_box_sizes_and_pbm.depends_on_block_constraints {
+ base_fragment_info.flags.insert(
+ FragmentFlags::SIZE_DEPENDS_ON_BLOCK_CONSTRAINTS_AND_CAN_BE_CHILD_OF_FLEX_ITEM,
+ );
+ }
- if content_box_sizes_and_pbm.depends_on_block_constraints {
- base_fragment_info
- .flags
- .insert(FragmentFlags::SIZE_DEPENDS_ON_BLOCK_CONSTRAINTS_AND_CAN_BE_CHILD_OF_FLEX_ITEM);
+ BoxFragment::new(
+ base_fragment_info,
+ base.style.clone(),
+ fragments,
+ 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,
+ CollapsedBlockMargins::from_margin(&margin),
+ )
}
-
- BoxFragment::new(
- base_fragment_info,
- style.clone(),
- fragments,
- 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,
- CollapsedBlockMargins::from_margin(&margin),
- )
}
struct ContainingBlockPaddingAndBorder<'a> {
@@ -2017,6 +2007,26 @@ fn block_size_is_zero_or_intrinsic(size: &StyleSize, containing_block: &Containi
}
impl IndependentFormattingContext {
+ pub(crate) fn layout_in_flow_block_level(
+ &self,
+ layout_context: &LayoutContext,
+ positioning_context: &mut PositioningContext,
+ containing_block: &ContainingBlock,
+ sequential_layout_state: Option<&mut SequentialLayoutState>,
+ ) -> BoxFragment {
+ match &self.contents {
+ IndependentFormattingContextContents::NonReplaced(contents) => contents
+ .layout_in_flow_block_level(
+ &self.base,
+ layout_context,
+ positioning_context,
+ containing_block,
+ sequential_layout_state,
+ ),
+ IndependentFormattingContextContents::Replaced(contents) => contents
+ .layout_in_flow_block_level(&self.base, containing_block, sequential_layout_state),
+ }
+ }
pub(crate) fn layout_float_or_atomic_inline(
&self,
layout_context: &LayoutContext,
@@ -2031,27 +2041,24 @@ impl IndependentFormattingContext {
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) => {
+ let (fragments, content_rect, baselines) = match &self.contents {
+ IndependentFormattingContextContents::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,
+ style,
&content_box_sizes_and_pbm,
)
.to_physical_size(container_writing_mode);
- let fragments = replaced
- .contents
- .make_fragments(&replaced.style, content_size);
+ let fragments = replaced.make_fragments(style, content_size);
let content_rect = PhysicalRect::new(PhysicalPoint::zero(), content_size);
(fragments, content_rect, None)
},
- IndependentFormattingContext::NonReplaced(non_replaced) => {
- let writing_mode = non_replaced.style.writing_mode;
+ IndependentFormattingContextContents::NonReplaced(non_replaced) => {
+ let writing_mode = self.style().writing_mode;
let available_inline_size =
(containing_block.inline_size - pbm_sums.inline_sum()).max(Au::zero());
let available_block_size = containing_block
@@ -2110,7 +2117,7 @@ impl IndependentFormattingContext {
let containing_block_for_children = ContainingBlock {
inline_size,
block_size: tentative_block_size.to_auto_or(),
- style: &non_replaced.style,
+ style: self.style(),
};
assert_eq!(
container_writing_mode.is_horizontal(),
diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs
index b1c62416ecc..f9828e2308a 100644
--- a/components/layout_2020/flow/root.rs
+++ b/components/layout_2020/flow/root.rs
@@ -28,7 +28,7 @@ use crate::formatting_contexts::IndependentFormattingContext;
use crate::fragment_tree::FragmentTree;
use crate::geom::{LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSize};
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext};
-use crate::replaced::ReplacedContent;
+use crate::replaced::ReplacedContents;
use crate::style_ext::{ComputedValuesExt, Display, DisplayGeneratingBox, DisplayInside};
use crate::taffy::{TaffyItemBox, TaffyItemBoxInner};
use crate::DefiniteContainingBlock;
@@ -222,7 +222,7 @@ impl BoxTree {
loop {
if let Some((primary_style, display_inside, update_point)) = update_point(dirty_node) {
- let contents = ReplacedContent::for_element(dirty_node, context)
+ let contents = ReplacedContents::for_element(dirty_node, context)
.map_or_else(|| NonReplacedContents::OfElement.into(), Contents::Replaced);
let info = NodeAndStyleInfo::new(dirty_node, Arc::clone(&primary_style));
let out_of_flow_absolutely_positioned_box = ArcRefCell::new(
@@ -290,7 +290,7 @@ fn construct_for_root_element<'dom>(
Display::GeneratingBox(display_generating_box) => display_generating_box.display_inside(),
};
- let contents = ReplacedContent::for_element(root_element, context)
+ let contents = ReplacedContents::for_element(root_element, context)
.map_or_else(|| NonReplacedContents::OfElement.into(), Contents::Replaced);
let root_box = if box_style.position.is_absolutely_positioned() {
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(ArcRefCell::new(
diff --git a/components/layout_2020/formatting_contexts.rs b/components/layout_2020/formatting_contexts.rs
index 8e22ef33122..d1bc21448a1 100644
--- a/components/layout_2020/formatting_contexts.rs
+++ b/components/layout_2020/formatting_contexts.rs
@@ -3,7 +3,6 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use app_units::Au;
-use atomic_refcell::AtomicRefCell;
use serde::Serialize;
use servo_arc::Arc;
use style::properties::ComputedValues;
@@ -17,46 +16,32 @@ use crate::flexbox::FlexContainer;
use crate::flow::BlockFormattingContext;
use crate::fragment_tree::{BaseFragmentInfo, BoxFragment, Fragment, FragmentFlags};
use crate::geom::LogicalSides;
+use crate::layout_box_base::LayoutBoxBase;
use crate::positioned::PositioningContext;
-use crate::replaced::ReplacedContent;
+use crate::replaced::ReplacedContents;
use crate::sizing::{self, InlineContentSizesResult};
use crate::style_ext::{AspectRatio, DisplayInside};
use crate::table::Table;
use crate::taffy::TaffyContainer;
-use crate::{
- ConstraintSpace, ContainingBlock, IndefiniteContainingBlock, LogicalVec2, SizeConstraint,
-};
+use crate::{ConstraintSpace, ContainingBlock, IndefiniteContainingBlock, LogicalVec2};
/// <https://drafts.csswg.org/css-display/#independent-formatting-context>
#[derive(Debug, Serialize)]
-pub(crate) enum IndependentFormattingContext {
- NonReplaced(NonReplacedFormattingContext),
- Replaced(ReplacedFormattingContext),
+pub(crate) struct IndependentFormattingContext {
+ pub base: LayoutBoxBase,
+ pub contents: IndependentFormattingContextContents,
}
#[derive(Debug, Serialize)]
-pub(crate) struct NonReplacedFormattingContext {
- pub base_fragment_info: BaseFragmentInfo,
- #[serde(skip_serializing)]
- pub style: Arc<ComputedValues>,
- /// If it was requested during construction
- #[serde(skip_serializing)]
- pub content_sizes_result: AtomicRefCell<Option<(SizeConstraint, InlineContentSizesResult)>>,
- pub contents: NonReplacedFormattingContextContents,
-}
-
-#[derive(Debug, Serialize)]
-pub(crate) struct ReplacedFormattingContext {
- pub base_fragment_info: BaseFragmentInfo,
- #[serde(skip_serializing)]
- pub style: Arc<ComputedValues>,
- pub contents: ReplacedContent,
+pub(crate) enum IndependentFormattingContextContents {
+ NonReplaced(IndependentNonReplacedContents),
+ Replaced(ReplacedContents),
}
// Private so that code outside of this module cannot match variants.
// It should got through methods instead.
#[derive(Debug, Serialize)]
-pub(crate) enum NonReplacedFormattingContextContents {
+pub(crate) enum IndependentNonReplacedContents {
Flow(BlockFormattingContext),
Flex(FlexContainer),
Grid(TaffyContainer),
@@ -115,24 +100,23 @@ impl IndependentFormattingContext {
contents: Contents,
propagated_text_decoration_line: TextDecorationLine,
) -> Self {
+ let mut base_fragment_info: BaseFragmentInfo = node_and_style_info.into();
+
match contents {
Contents::NonReplaced(non_replaced_contents) => {
- let mut base_fragment_info: BaseFragmentInfo = node_and_style_info.into();
let contents = match display_inside {
DisplayInside::Flow { is_list_item } |
DisplayInside::FlowRoot { is_list_item } => {
- NonReplacedFormattingContextContents::Flow(
- BlockFormattingContext::construct(
- context,
- node_and_style_info,
- non_replaced_contents,
- propagated_text_decoration_line,
- is_list_item,
- ),
- )
+ IndependentNonReplacedContents::Flow(BlockFormattingContext::construct(
+ context,
+ node_and_style_info,
+ non_replaced_contents,
+ propagated_text_decoration_line,
+ is_list_item,
+ ))
},
DisplayInside::Grid => {
- NonReplacedFormattingContextContents::Grid(TaffyContainer::construct(
+ IndependentNonReplacedContents::Grid(TaffyContainer::construct(
context,
node_and_style_info,
non_replaced_contents,
@@ -140,7 +124,7 @@ impl IndependentFormattingContext {
))
},
DisplayInside::Flex => {
- NonReplacedFormattingContextContents::Flex(FlexContainer::construct(
+ IndependentNonReplacedContents::Flex(FlexContainer::construct(
context,
node_and_style_info,
non_replaced_contents,
@@ -157,7 +141,7 @@ impl IndependentFormattingContext {
&node_and_style_info.style,
);
base_fragment_info.flags.insert(FragmentFlags::DO_NOT_PAINT);
- NonReplacedFormattingContextContents::Table(Table::construct(
+ IndependentNonReplacedContents::Table(Table::construct(
context,
node_and_style_info,
table_grid_style,
@@ -166,41 +150,36 @@ impl IndependentFormattingContext {
))
},
};
- Self::NonReplaced(NonReplacedFormattingContext {
- style: Arc::clone(&node_and_style_info.style),
- base_fragment_info,
- content_sizes_result: AtomicRefCell::default(),
- contents,
- })
+ Self {
+ base: LayoutBoxBase::new(base_fragment_info, node_and_style_info.style.clone()),
+ contents: IndependentFormattingContextContents::NonReplaced(contents),
+ }
},
Contents::Replaced(contents) => {
- let mut base_fragment_info: BaseFragmentInfo = node_and_style_info.into();
base_fragment_info.flags.insert(FragmentFlags::IS_REPLACED);
- Self::Replaced(ReplacedFormattingContext {
- base_fragment_info,
- style: Arc::clone(&node_and_style_info.style),
- contents,
- })
+ Self {
+ base: LayoutBoxBase::new(base_fragment_info, node_and_style_info.style.clone()),
+ contents: IndependentFormattingContextContents::Replaced(contents),
+ }
},
}
}
pub fn is_replaced(&self) -> bool {
- matches!(self, Self::Replaced(_))
+ matches!(
+ self.contents,
+ IndependentFormattingContextContents::Replaced(_)
+ )
}
+ #[inline]
pub fn style(&self) -> &Arc<ComputedValues> {
- match self {
- Self::NonReplaced(inner) => &inner.style,
- Self::Replaced(inner) => &inner.style,
- }
+ &self.base.style
}
+ #[inline]
pub fn base_fragment_info(&self) -> BaseFragmentInfo {
- match self {
- Self::NonReplaced(inner) => inner.base_fragment_info,
- Self::Replaced(inner) => inner.base_fragment_info,
- }
+ self.base.base_fragment_info
}
pub(crate) fn inline_content_sizes(
@@ -208,14 +187,15 @@ impl IndependentFormattingContext {
layout_context: &LayoutContext,
constraint_space: &ConstraintSpace,
) -> InlineContentSizesResult {
- match self {
- Self::NonReplaced(inner) => {
- inner.inline_content_sizes(layout_context, constraint_space)
- },
- Self::Replaced(inner) => inner
- .contents
- .inline_content_sizes(layout_context, constraint_space),
- }
+ self.base
+ .inline_content_sizes(constraint_space, || match &self.contents {
+ IndependentFormattingContextContents::NonReplaced(contents) => {
+ contents.inline_content_sizes(layout_context, constraint_space)
+ },
+ IndependentFormattingContextContents::Replaced(contents) => {
+ contents.inline_content_sizes(layout_context, constraint_space)
+ },
+ })
}
pub(crate) fn outer_inline_content_sizes(
@@ -225,40 +205,32 @@ impl IndependentFormattingContext {
auto_minimum: &LogicalVec2<Au>,
auto_block_size_stretches_to_containing_block: bool,
) -> InlineContentSizesResult {
- match self {
- Self::NonReplaced(non_replaced) => non_replaced.outer_inline_content_sizes(
- layout_context,
- containing_block,
- auto_minimum,
- auto_block_size_stretches_to_containing_block,
- ),
- Self::Replaced(replaced) => sizing::outer_inline(
- &replaced.style,
- containing_block,
- auto_minimum,
- auto_block_size_stretches_to_containing_block,
- |padding_border_sums| replaced.preferred_aspect_ratio(padding_border_sums),
- |constraint_space| {
- replaced
- .contents
- .inline_content_sizes(layout_context, constraint_space)
- },
- ),
- }
+ sizing::outer_inline(
+ self.style(),
+ containing_block,
+ auto_minimum,
+ auto_block_size_stretches_to_containing_block,
+ |padding_border_sums| self.preferred_aspect_ratio(padding_border_sums),
+ |constraint_space| self.inline_content_sizes(layout_context, constraint_space),
+ )
}
pub(crate) fn preferred_aspect_ratio(
&self,
padding_border_sums: &LogicalVec2<Au>,
) -> Option<AspectRatio> {
- match self {
- Self::NonReplaced(non_replaced) => non_replaced.preferred_aspect_ratio(),
- Self::Replaced(replaced) => replaced.preferred_aspect_ratio(padding_border_sums),
+ match &self.contents {
+ IndependentFormattingContextContents::NonReplaced(content) => {
+ content.preferred_aspect_ratio()
+ },
+ IndependentFormattingContextContents::Replaced(content) => {
+ content.preferred_aspect_ratio(self.style(), padding_border_sums)
+ },
}
}
}
-impl NonReplacedFormattingContext {
+impl IndependentNonReplacedContents {
pub fn layout(
&self,
layout_context: &LayoutContext,
@@ -266,25 +238,25 @@ impl NonReplacedFormattingContext {
containing_block_for_children: &ContainingBlock,
containing_block: &ContainingBlock,
) -> IndependentLayout {
- match &self.contents {
- NonReplacedFormattingContextContents::Flow(bfc) => bfc.layout(
+ match self {
+ IndependentNonReplacedContents::Flow(bfc) => bfc.layout(
layout_context,
positioning_context,
containing_block_for_children,
),
- NonReplacedFormattingContextContents::Flex(fc) => fc.layout(
+ IndependentNonReplacedContents::Flex(fc) => fc.layout(
layout_context,
positioning_context,
containing_block_for_children,
containing_block,
),
- NonReplacedFormattingContextContents::Grid(fc) => fc.layout(
+ IndependentNonReplacedContents::Grid(fc) => fc.layout(
layout_context,
positioning_context,
containing_block_for_children,
containing_block,
),
- NonReplacedFormattingContextContents::Table(table) => table.layout(
+ IndependentNonReplacedContents::Table(table) => table.layout(
layout_context,
positioning_context,
containing_block_for_children,
@@ -304,47 +276,6 @@ impl NonReplacedFormattingContext {
layout_context: &LayoutContext,
constraint_space: &ConstraintSpace,
) -> InlineContentSizesResult {
- let mut cache = self.content_sizes_result.borrow_mut();
- if let Some((previous_cb_block_size, result)) = *cache {
- if !result.depends_on_block_constraints ||
- previous_cb_block_size == constraint_space.block_size
- {
- return result;
- }
- // TODO: Should we keep multiple caches for various block sizes?
- }
-
- let result = self
- .contents
- .inline_content_sizes(layout_context, constraint_space);
- *cache = Some((constraint_space.block_size, result));
- result
- }
-
- pub(crate) fn outer_inline_content_sizes(
- &self,
- layout_context: &LayoutContext,
- containing_block: &IndefiniteContainingBlock,
- auto_minimum: &LogicalVec2<Au>,
- auto_block_size_stretches_to_containing_block: bool,
- ) -> InlineContentSizesResult {
- sizing::outer_inline(
- &self.style,
- containing_block,
- auto_minimum,
- auto_block_size_stretches_to_containing_block,
- |_| self.preferred_aspect_ratio(),
- |constraint_space| self.inline_content_sizes(layout_context, constraint_space),
- )
- }
-}
-
-impl NonReplacedFormattingContextContents {
- pub(crate) fn inline_content_sizes(
- &self,
- layout_context: &LayoutContext,
- constraint_space: &ConstraintSpace,
- ) -> InlineContentSizesResult {
match self {
Self::Flow(inner) => inner
.contents
@@ -355,13 +286,3 @@ impl NonReplacedFormattingContextContents {
}
}
}
-
-impl ReplacedFormattingContext {
- pub(crate) fn preferred_aspect_ratio(
- &self,
- padding_border_sums: &LogicalVec2<Au>,
- ) -> Option<AspectRatio> {
- self.contents
- .preferred_aspect_ratio(&self.style, padding_border_sums)
- }
-}
diff --git a/components/layout_2020/layout_box_base.rs b/components/layout_2020/layout_box_base.rs
new file mode 100644
index 00000000000..10a2d98d149
--- /dev/null
+++ b/components/layout_2020/layout_box_base.rs
@@ -0,0 +1,61 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use atomic_refcell::AtomicRefCell;
+use serde::Serialize;
+use servo_arc::Arc;
+use style::properties::ComputedValues;
+
+use crate::fragment_tree::BaseFragmentInfo;
+use crate::geom::SizeConstraint;
+use crate::sizing::InlineContentSizesResult;
+use crate::ConstraintSpace;
+
+/// A box tree node that handles containing information about style and the original DOM
+/// node or pseudo-element that it is based on. This also handles caching of layout values
+/// such as the inline content sizes to avoid recalculating these values during layout
+/// passes.
+///
+/// In the future, this will hold layout results to support incremental layout.
+#[derive(Debug, Serialize)]
+pub(crate) struct LayoutBoxBase {
+ pub base_fragment_info: BaseFragmentInfo,
+ #[serde(skip_serializing)]
+ pub style: Arc<ComputedValues>,
+ #[serde(skip_serializing)]
+ pub cached_inline_content_size:
+ AtomicRefCell<Option<(SizeConstraint, InlineContentSizesResult)>>,
+}
+
+impl LayoutBoxBase {
+ pub(crate) fn new(base_fragment_info: BaseFragmentInfo, style: Arc<ComputedValues>) -> Self {
+ Self {
+ base_fragment_info,
+ style,
+ cached_inline_content_size: AtomicRefCell::default(),
+ }
+ }
+
+ /// Get the inline content sizes of a box tree node that extends this [`LayoutBoxBase`], fetch
+ /// the result from a cache when possible.
+ pub(crate) fn inline_content_sizes(
+ &self,
+ constraint_space: &ConstraintSpace,
+ inline_content_sizes_fn: impl FnOnce() -> InlineContentSizesResult,
+ ) -> InlineContentSizesResult {
+ let mut cache = self.cached_inline_content_size.borrow_mut();
+ if let Some((previous_cb_block_size, result)) = *cache {
+ if !result.depends_on_block_constraints ||
+ previous_cb_block_size == constraint_space.block_size
+ {
+ return result;
+ }
+ // TODO: Should we keep multiple caches for various block sizes?
+ }
+
+ let result = inline_content_sizes_fn();
+ *cache = Some((constraint_space.block_size, result));
+ result
+ }
+}
diff --git a/components/layout_2020/lib.rs b/components/layout_2020/lib.rs
index 64e5e102887..3232a1aac44 100644
--- a/components/layout_2020/lib.rs
+++ b/components/layout_2020/lib.rs
@@ -14,6 +14,7 @@ pub mod flow;
mod formatting_contexts;
mod fragment_tree;
pub mod geom;
+mod layout_box_base;
mod taffy;
#[macro_use]
pub mod layout_debug;
diff --git a/components/layout_2020/lists.rs b/components/layout_2020/lists.rs
index b0e97ab02e3..ee8db260c8c 100644
--- a/components/layout_2020/lists.rs
+++ b/components/layout_2020/lists.rs
@@ -10,7 +10,7 @@ use style::values::computed::Image;
use crate::context::LayoutContext;
use crate::dom::NodeExt;
use crate::dom_traversal::{NodeAndStyleInfo, PseudoElementContentItem};
-use crate::replaced::ReplacedContent;
+use crate::replaced::ReplacedContents;
/// <https://drafts.csswg.org/css-lists/#content-property>
pub(crate) fn make_marker<'dom, Node>(
@@ -32,7 +32,7 @@ where
// https://drafts.csswg.org/css-lists/#marker-image
let marker_image = || match &style.list_style_image {
Image::Url(url) => Some(vec![
- PseudoElementContentItem::Replaced(ReplacedContent::from_image_url(
+ PseudoElementContentItem::Replaced(ReplacedContents::from_image_url(
node, context, url,
)?),
PseudoElementContentItem::Text(" ".into()),
diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs
index 1cf53ee8768..6fc0ddf66b5 100644
--- a/components/layout_2020/positioned.rs
+++ b/components/layout_2020/positioned.rs
@@ -20,7 +20,9 @@ use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
use crate::dom::NodeExt;
use crate::dom_traversal::{Contents, NodeAndStyleInfo};
-use crate::formatting_contexts::IndependentFormattingContext;
+use crate::formatting_contexts::{
+ IndependentFormattingContext, IndependentFormattingContextContents,
+};
use crate::fragment_tree::{
BoxFragment, CollapsedBlockMargins, Fragment, FragmentFlags, HoistedSharedFragment,
};
@@ -521,24 +523,22 @@ impl HoistedAbsolutelyPositionedBox {
flip_anchor: false,
};
- if let IndependentFormattingContext::Replaced(replaced) = context {
+ if let IndependentFormattingContextContents::Replaced(replaced) = &context.contents {
// https://drafts.csswg.org/css2/visudet.html#abs-replaced-width
// https://drafts.csswg.org/css2/visudet.html#abs-replaced-height
let inset_sums = LogicalVec2 {
inline: inline_axis_solver.inset_sum(),
block: block_axis_solver.inset_sum(),
};
- let used_size = replaced
- .contents
- .used_size_as_if_inline_element_from_content_box_sizes(
- containing_block,
- &style,
- replaced.preferred_aspect_ratio(&pbm.padding_border_sums),
- computed_size,
- computed_min_size,
- computed_max_size,
- pbm.padding_border_sums + pbm.margin.auto_is(Au::zero).sum() + inset_sums,
- );
+ let used_size = replaced.used_size_as_if_inline_element_from_content_box_sizes(
+ containing_block,
+ &style,
+ context.preferred_aspect_ratio(&pbm.padding_border_sums),
+ computed_size,
+ computed_min_size,
+ computed_max_size,
+ pbm.padding_border_sums + pbm.margin.auto_is(Au::zero).sum() + inset_sums,
+ );
inline_axis_solver.override_size(used_size.inline);
block_axis_solver.override_size(used_size.block);
}
@@ -561,20 +561,20 @@ impl HoistedAbsolutelyPositionedBox {
let mut new_fragment = {
let content_size: LogicalVec2<Au>;
let fragments;
- match context {
- IndependentFormattingContext::Replaced(replaced) => {
+ match &context.contents {
+ IndependentFormattingContextContents::Replaced(replaced) => {
// https://drafts.csswg.org/css2/visudet.html#abs-replaced-width
// https://drafts.csswg.org/css2/visudet.html#abs-replaced-height
content_size = LogicalVec2 {
inline: inline_axis.size.to_definite().unwrap(),
block: block_axis.size.to_definite().unwrap(),
};
- fragments = replaced.contents.make_fragments(
+ fragments = replaced.make_fragments(
&style,
content_size.to_physical_size(containing_block_writing_mode),
);
},
- IndependentFormattingContext::NonReplaced(non_replaced) => {
+ IndependentFormattingContextContents::NonReplaced(non_replaced) => {
// https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width
// https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-height
let inline_size = inline_axis.size.to_definite().unwrap();
diff --git a/components/layout_2020/replaced.rs b/components/layout_2020/replaced.rs
index c1e4236d052..bedfbf54ffe 100644
--- a/components/layout_2020/replaced.rs
+++ b/components/layout_2020/replaced.rs
@@ -34,7 +34,7 @@ use crate::style_ext::{AspectRatio, Clamp, ComputedValuesExt, ContentBoxSizesAnd
use crate::{ConstraintSpace, ContainingBlock, SizeConstraint};
#[derive(Debug, Serialize)]
-pub(crate) struct ReplacedContent {
+pub(crate) struct ReplacedContents {
pub kind: ReplacedContentKind,
natural_size: NaturalSizes,
base_fragment_info: BaseFragmentInfo,
@@ -140,7 +140,7 @@ pub(crate) enum ReplacedContentKind {
Video(Option<VideoInfo>),
}
-impl ReplacedContent {
+impl ReplacedContents {
pub fn for_element<'dom>(element: impl NodeExt<'dom>, context: &LayoutContext) -> Option<Self> {
if let Some(ref data_attribute_string) = element.as_typeless_object_with_data_attribute() {
if let Some(url) = try_to_parse_image_data_url(data_attribute_string) {
diff --git a/components/layout_2020/table/construct.rs b/components/layout_2020/table/construct.rs
index d57e315d3d8..8eb754d8df5 100644
--- a/components/layout_2020/table/construct.rs
+++ b/components/layout_2020/table/construct.rs
@@ -25,10 +25,11 @@ use crate::dom::{BoxSlot, NodeExt};
use crate::dom_traversal::{Contents, NodeAndStyleInfo, NonReplacedContents, TraversalHandler};
use crate::flow::{BlockContainerBuilder, BlockFormattingContext};
use crate::formatting_contexts::{
- IndependentFormattingContext, NonReplacedFormattingContext,
- NonReplacedFormattingContextContents,
+ IndependentFormattingContext, IndependentFormattingContextContents,
+ IndependentNonReplacedContents,
};
use crate::fragment_tree::BaseFragmentInfo;
+use crate::layout_box_base::LayoutBoxBase;
use crate::style_ext::{DisplayGeneratingBox, DisplayLayoutInternal};
/// A reference to a slot and its coordinates in the table
@@ -134,12 +135,12 @@ impl Table {
let mut table = table_builder.finish();
table.anonymous = true;
- IndependentFormattingContext::NonReplaced(NonReplacedFormattingContext {
- base_fragment_info: (&anonymous_info).into(),
- style: grid_and_wrapper_style,
- content_sizes_result: Default::default(),
- contents: NonReplacedFormattingContextContents::Table(table),
- })
+ IndependentFormattingContext {
+ base: LayoutBoxBase::new((&anonymous_info).into(), grid_and_wrapper_style),
+ contents: IndependentFormattingContextContents::NonReplaced(
+ IndependentNonReplacedContents::Table(table),
+ ),
+ }
}
/// Push a new slot into the last row of this table.
@@ -853,15 +854,13 @@ where
DisplayLayoutInternal::TableCaption => {
let contents = match contents.try_into() {
Ok(non_replaced_contents) => {
- NonReplacedFormattingContextContents::Flow(
- BlockFormattingContext::construct(
- self.context,
- info,
- non_replaced_contents,
- self.current_text_decoration_line,
- false, /* is_list_item */
- ),
- )
+ IndependentNonReplacedContents::Flow(BlockFormattingContext::construct(
+ self.context,
+ info,
+ non_replaced_contents,
+ self.current_text_decoration_line,
+ false, /* is_list_item */
+ ))
},
Err(_replaced) => {
unreachable!("Replaced should not have a LayoutInternal display type.");
@@ -869,11 +868,9 @@ where
};
let caption = TableCaption {
- context: ArcRefCell::new(NonReplacedFormattingContext {
- style: info.style.clone(),
- base_fragment_info: info.into(),
- content_sizes_result: Default::default(),
- contents,
+ context: ArcRefCell::new(IndependentFormattingContext {
+ base: LayoutBoxBase::new(info.into(), info.style.clone()),
+ contents: IndependentFormattingContextContents::NonReplaced(contents),
}),
};
diff --git a/components/layout_2020/table/layout.rs b/components/layout_2020/table/layout.rs
index 673beb604ae..ea7714207dd 100644
--- a/components/layout_2020/table/layout.rs
+++ b/components/layout_2020/table/layout.rs
@@ -1613,7 +1613,7 @@ impl<'a> TableLayout<'a> {
parent_positioning_context: &mut PositioningContext,
) -> BoxFragment {
let context = caption.context.borrow();
- let mut positioning_context = PositioningContext::new_for_style(&context.style);
+ let mut positioning_context = PositioningContext::new_for_style(context.style());
let containing_block = &ContainingBlock {
inline_size: self.table_width + table_pbm.padding_border_sums.inline,
block_size: AuOrAuto::Auto,
@@ -1711,7 +1711,7 @@ impl<'a> TableLayout<'a> {
table_layout
.fragments
.extend(self.table.captions.iter().filter_map(|caption| {
- if caption.context.borrow().style.clone_caption_side() != CaptionSide::Top {
+ if caption.context.borrow().style().clone_caption_side() != CaptionSide::Top {
return None;
}
@@ -1811,7 +1811,7 @@ impl<'a> TableLayout<'a> {
table_layout
.fragments
.extend(self.table.captions.iter().filter_map(|caption| {
- if caption.context.borrow().style.clone_caption_side() != CaptionSide::Bottom {
+ if caption.context.borrow().style().clone_caption_side() != CaptionSide::Bottom {
return None;
}
diff --git a/components/layout_2020/table/mod.rs b/components/layout_2020/table/mod.rs
index 1e29e605605..5a2c335875d 100644
--- a/components/layout_2020/table/mod.rs
+++ b/components/layout_2020/table/mod.rs
@@ -82,7 +82,7 @@ use style_traits::dom::OpaqueNode;
use super::flow::BlockFormattingContext;
use crate::cell::ArcRefCell;
use crate::flow::BlockContainer;
-use crate::formatting_contexts::NonReplacedFormattingContext;
+use crate::formatting_contexts::IndependentFormattingContext;
use crate::fragment_tree::BaseFragmentInfo;
pub type TableSize = Size2D<usize, UnknownUnit>;
@@ -320,5 +320,5 @@ impl TableTrackGroup {
#[derive(Debug, Serialize)]
pub struct TableCaption {
/// The contents of this cell, with its own layout.
- context: ArcRefCell<NonReplacedFormattingContext>,
+ context: ArcRefCell<IndependentFormattingContext>,
}
diff --git a/components/layout_2020/taffy/layout.rs b/components/layout_2020/taffy/layout.rs
index 33b1ce8a1ab..02c8568c091 100644
--- a/components/layout_2020/taffy/layout.rs
+++ b/components/layout_2020/taffy/layout.rs
@@ -15,7 +15,10 @@ use taffy::{AvailableSpace, MaybeMath, RequestedAxis, RunMode};
use super::{TaffyContainer, TaffyItemBox, TaffyItemBoxInner, TaffyStyloStyle};
use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
-use crate::formatting_contexts::{Baselines, IndependentFormattingContext, IndependentLayout};
+use crate::formatting_contexts::{
+ Baselines, IndependentFormattingContext, IndependentFormattingContextContents,
+ IndependentLayout,
+};
use crate::fragment_tree::{BoxFragment, CollapsedBlockMargins, Fragment};
use crate::geom::{
LogicalSides, LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSides, PhysicalSize, Size,
@@ -43,13 +46,12 @@ fn resolve_content_size(constraint: AvailableSpace, content_sizes: ContentSizes)
#[inline(always)]
fn with_independant_formatting_context<T>(
item: &mut TaffyItemBoxInner,
- cb: impl FnOnce(&mut IndependentFormattingContext) -> T,
+ cb: impl FnOnce(&IndependentFormattingContext) -> T,
) -> T {
match item {
TaffyItemBoxInner::InFlowBox(ref mut context) => cb(context),
TaffyItemBoxInner::OutOfFlowAbsolutelyPositionedBox(ref abspos_box) => {
- let mut abspos_box = AtomicRefCell::borrow_mut(abspos_box);
- cb(&mut abspos_box.context)
+ cb(&AtomicRefCell::borrow(abspos_box).context)
},
}
}
@@ -132,13 +134,14 @@ impl taffy::LayoutPartialTree for TaffyContainerContext<'_> {
with_independant_formatting_context(
&mut child.taffy_level_box,
|independent_context| -> taffy::LayoutOutput {
- match independent_context {
- IndependentFormattingContext::Replaced(replaced) => {
+ let style = independent_context.style();
+ match &independent_context.contents {
+ IndependentFormattingContextContents::Replaced(replaced) => {
// TODO: re-evaluate sizing constraint conversions in light of recent layout_2020 changes
let containing_block = &self.content_box_size_override;
// Adjust known_dimensions from border box to content box
- let pbm = replaced.style.padding_border_margin(containing_block);
+ let pbm = style.padding_border_margin(containing_block);
let pb_sum = pbm.padding_border_sums.map(|v| v.to_f32_px());
let content_box_known_dimensions = taffy::Size {
width: inputs
@@ -152,11 +155,11 @@ impl taffy::LayoutPartialTree for TaffyContainerContext<'_> {
};
let content_box_size = replaced
- .contents
.used_size_as_if_inline_element_from_content_box_sizes(
containing_block,
- &replaced.style,
- replaced.preferred_aspect_ratio(&pbm.padding_border_sums),
+ style,
+ independent_context
+ .preferred_aspect_ratio(&pbm.padding_border_sums),
LogicalVec2 {
inline: option_f32_to_size(content_box_known_dimensions.width),
block: option_f32_to_size(content_box_known_dimensions.height),
@@ -176,9 +179,8 @@ impl taffy::LayoutPartialTree for TaffyContainerContext<'_> {
// Create fragments if the RunMode if PerformLayout
// If the RunMode is ComputeSize then only the returned size will be used
if inputs.run_mode == RunMode::PerformLayout {
- child.child_fragments = replaced
- .contents
- .make_fragments(&replaced.style, content_box_size);
+ child.child_fragments =
+ replaced.make_fragments(style, content_box_size);
}
let computed_size = taffy::Size {
@@ -198,12 +200,12 @@ impl taffy::LayoutPartialTree for TaffyContainerContext<'_> {
}
},
- IndependentFormattingContext::NonReplaced(non_replaced) => {
+ IndependentFormattingContextContents::NonReplaced(non_replaced) => {
// TODO: re-evaluate sizing constraint conversions in light of recent layout_2020 changes
let containing_block = &self.content_box_size_override;
// Adjust known_dimensions from border box to content box
- let pbm = non_replaced.style.padding_border_margin(containing_block);
+ let pbm = style.padding_border_margin(containing_block);
let margin_sum = pbm.margin.auto_is(Au::zero).sum();
let content_box_inset =
(pbm.padding_border_sums + margin_sum).map(|v| v.to_f32_px());
@@ -256,7 +258,7 @@ impl taffy::LayoutPartialTree for TaffyContainerContext<'_> {
let content_box_size_override = ContainingBlock {
inline_size: Au::from_f32_px(inline_size),
block_size: maybe_block_size,
- style: &non_replaced.style,
+ style,
};
let layout = {