mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Avoid recomputing inline_content_sizes() when not needed (#33806)
The result of `inline_content_sizes()` may depend on the block size of the containing block, so we were always recomputing in case we got a different block size. However, if no content has a vertical percentage or stretches vertically, then we don't need to recompute: the result will be the same anyways. Signed-off-by: Oriol Brufau <obrufau@igalia.com> Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
821bed1d11
commit
b9ed45942d
12 changed files with 257 additions and 139 deletions
|
@ -171,7 +171,7 @@ where
|
||||||
let non_replaced = NonReplacedFormattingContext {
|
let non_replaced = NonReplacedFormattingContext {
|
||||||
base_fragment_info: info.into(),
|
base_fragment_info: info.into(),
|
||||||
style: info.style.clone(),
|
style: info.style.clone(),
|
||||||
content_sizes: None,
|
content_sizes_result: None,
|
||||||
contents: NonReplacedFormattingContextContents::Flow(
|
contents: NonReplacedFormattingContextContents::Flow(
|
||||||
block_formatting_context,
|
block_formatting_context,
|
||||||
),
|
),
|
||||||
|
|
|
@ -31,7 +31,7 @@ use crate::geom::{AuOrAuto, LogicalRect, LogicalSides, LogicalVec2};
|
||||||
use crate::positioned::{
|
use crate::positioned::{
|
||||||
relative_adjustement, AbsolutelyPositionedBox, PositioningContext, PositioningContextLength,
|
relative_adjustement, AbsolutelyPositionedBox, PositioningContext, PositioningContextLength,
|
||||||
};
|
};
|
||||||
use crate::sizing::{ContentSizes, IntrinsicSizingMode};
|
use crate::sizing::{ContentSizes, InlineContentSizesResult, IntrinsicSizingMode};
|
||||||
use crate::style_ext::{Clamp, ComputedValuesExt, PaddingBorderMargin};
|
use crate::style_ext::{Clamp, ComputedValuesExt, PaddingBorderMargin};
|
||||||
use crate::{ContainingBlock, IndefiniteContainingBlock};
|
use crate::{ContainingBlock, IndefiniteContainingBlock};
|
||||||
|
|
||||||
|
@ -336,6 +336,7 @@ struct FlexItemBoxInlineContentSizesInfo {
|
||||||
min_flex_factors: DesiredFlexFractionAndGrowOrShrinkFactor,
|
min_flex_factors: DesiredFlexFractionAndGrowOrShrinkFactor,
|
||||||
max_flex_factors: DesiredFlexFractionAndGrowOrShrinkFactor,
|
max_flex_factors: DesiredFlexFractionAndGrowOrShrinkFactor,
|
||||||
min_content_main_size_for_multiline_container: Au,
|
min_content_main_size_for_multiline_container: Au,
|
||||||
|
depends_on_block_constraints: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FlexContainer {
|
impl FlexContainer {
|
||||||
|
@ -348,7 +349,7 @@ impl FlexContainer {
|
||||||
&mut self,
|
&mut self,
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
containing_block_for_children: &IndefiniteContainingBlock,
|
containing_block_for_children: &IndefiniteContainingBlock,
|
||||||
) -> ContentSizes {
|
) -> InlineContentSizesResult {
|
||||||
match self.config.flex_axis {
|
match self.config.flex_axis {
|
||||||
FlexAxis::Row => {
|
FlexAxis::Row => {
|
||||||
self.main_content_sizes(layout_context, containing_block_for_children, || {
|
self.main_content_sizes(layout_context, containing_block_for_children, || {
|
||||||
|
@ -367,14 +368,15 @@ impl FlexContainer {
|
||||||
&mut self,
|
&mut self,
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
containing_block_for_children: &IndefiniteContainingBlock,
|
containing_block_for_children: &IndefiniteContainingBlock,
|
||||||
) -> ContentSizes {
|
) -> InlineContentSizesResult {
|
||||||
// <https://drafts.csswg.org/css-flexbox/#intrinsic-cross-sizes>
|
// <https://drafts.csswg.org/css-flexbox/#intrinsic-cross-sizes>
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
self.config.flex_axis,
|
self.config.flex_axis,
|
||||||
FlexAxis::Column,
|
FlexAxis::Column,
|
||||||
"The cross axis should be the inline one"
|
"The cross axis should be the inline one"
|
||||||
);
|
);
|
||||||
let mut content_sizes = ContentSizes::zero();
|
let mut sizes = ContentSizes::zero();
|
||||||
|
let mut depends_on_block_constraints = false;
|
||||||
for kid in self.children.iter() {
|
for kid in self.children.iter() {
|
||||||
let kid = &mut *kid.borrow_mut();
|
let kid = &mut *kid.borrow_mut();
|
||||||
match kid {
|
match kid {
|
||||||
|
@ -383,17 +385,22 @@ impl FlexContainer {
|
||||||
// columns, and sum the column sizes and gaps.
|
// columns, and sum the column sizes and gaps.
|
||||||
// TODO: Use the proper automatic minimum size.
|
// TODO: Use the proper automatic minimum size.
|
||||||
let ifc = &mut item.independent_formatting_context;
|
let ifc = &mut item.independent_formatting_context;
|
||||||
content_sizes.max_assign(ifc.outer_inline_content_sizes(
|
let result = ifc.outer_inline_content_sizes(
|
||||||
layout_context,
|
layout_context,
|
||||||
containing_block_for_children,
|
containing_block_for_children,
|
||||||
&LogicalVec2::zero(),
|
&LogicalVec2::zero(),
|
||||||
false, /* auto_block_size_stretches_to_containing_block */
|
false, /* auto_block_size_stretches_to_containing_block */
|
||||||
));
|
);
|
||||||
|
sizes.max_assign(result.sizes);
|
||||||
|
depends_on_block_constraints |= result.depends_on_block_constraints;
|
||||||
},
|
},
|
||||||
FlexLevelBox::OutOfFlowAbsolutelyPositionedBox(_) => {},
|
FlexLevelBox::OutOfFlowAbsolutelyPositionedBox(_) => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
content_sizes
|
InlineContentSizesResult {
|
||||||
|
sizes,
|
||||||
|
depends_on_block_constraints,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main_content_sizes<'a>(
|
fn main_content_sizes<'a>(
|
||||||
|
@ -401,7 +408,7 @@ impl FlexContainer {
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
containing_block_for_children: &IndefiniteContainingBlock,
|
containing_block_for_children: &IndefiniteContainingBlock,
|
||||||
flex_context_getter: impl Fn() -> &'a FlexContext<'a>,
|
flex_context_getter: impl Fn() -> &'a FlexContext<'a>,
|
||||||
) -> ContentSizes {
|
) -> InlineContentSizesResult {
|
||||||
// - TODO: calculate intrinsic cross sizes when container is a column
|
// - TODO: calculate intrinsic cross sizes when container is a column
|
||||||
// (and check for ‘writing-mode’?)
|
// (and check for ‘writing-mode’?)
|
||||||
// - TODO: Collapsed flex items need to be skipped for intrinsic size calculation.
|
// - TODO: Collapsed flex items need to be skipped for intrinsic size calculation.
|
||||||
|
@ -483,6 +490,7 @@ impl FlexContainer {
|
||||||
} else {
|
} else {
|
||||||
Au::zero()
|
Au::zero()
|
||||||
};
|
};
|
||||||
|
let mut container_depends_on_block_constraints = false;
|
||||||
|
|
||||||
for FlexItemBoxInlineContentSizesInfo {
|
for FlexItemBoxInlineContentSizesInfo {
|
||||||
outer_flex_base_size,
|
outer_flex_base_size,
|
||||||
|
@ -492,6 +500,7 @@ impl FlexContainer {
|
||||||
min_flex_factors,
|
min_flex_factors,
|
||||||
max_flex_factors,
|
max_flex_factors,
|
||||||
min_content_main_size_for_multiline_container,
|
min_content_main_size_for_multiline_container,
|
||||||
|
depends_on_block_constraints,
|
||||||
} in item_infos.iter()
|
} in item_infos.iter()
|
||||||
{
|
{
|
||||||
// > 4. Add each item’s flex base size to the product of its flex grow factor (scaled flex shrink
|
// > 4. Add each item’s flex base size to the product of its flex grow factor (scaled flex shrink
|
||||||
|
@ -528,11 +537,16 @@ impl FlexContainer {
|
||||||
container_min_content_size
|
container_min_content_size
|
||||||
.max_assign(*min_content_main_size_for_multiline_container);
|
.max_assign(*min_content_main_size_for_multiline_container);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
container_depends_on_block_constraints |= depends_on_block_constraints;
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentSizes {
|
InlineContentSizesResult {
|
||||||
min_content: container_min_content_size,
|
sizes: ContentSizes {
|
||||||
max_content: container_max_content_size,
|
min_content: container_min_content_size,
|
||||||
|
max_content: container_max_content_size,
|
||||||
|
},
|
||||||
|
depends_on_block_constraints: container_depends_on_block_constraints,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -573,6 +587,7 @@ impl FlexContainer {
|
||||||
FlexAxis::Row => containing_block.inline_size,
|
FlexAxis::Row => containing_block.inline_size,
|
||||||
FlexAxis::Column => containing_block.block_size.auto_is(|| {
|
FlexAxis::Column => containing_block.block_size.auto_is(|| {
|
||||||
self.main_content_sizes(layout_context, &containing_block.into(), || &flex_context)
|
self.main_content_sizes(layout_context, &containing_block.into(), || &flex_context)
|
||||||
|
.sizes
|
||||||
.max_content
|
.max_content
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
@ -1023,7 +1038,7 @@ impl<'a> FlexItem<'a> {
|
||||||
flex_context.config.flex_axis,
|
flex_context.config.flex_axis,
|
||||||
);
|
);
|
||||||
|
|
||||||
let (content_box_size, min_size, max_size, pbm) = box_
|
let (content_box_size, min_size, max_size, pbm, _) = box_
|
||||||
.style()
|
.style()
|
||||||
.content_box_sizes_and_padding_border_margin_deprecated(&containing_block.into());
|
.content_box_sizes_and_padding_border_margin_deprecated(&containing_block.into());
|
||||||
|
|
||||||
|
@ -1735,6 +1750,7 @@ impl FlexItem<'_> {
|
||||||
&containing_block_for_children,
|
&containing_block_for_children,
|
||||||
&containing_block.into(),
|
&containing_block.into(),
|
||||||
)
|
)
|
||||||
|
.sizes
|
||||||
.map(|size| {
|
.map(|size| {
|
||||||
size.clamp_between_extremums(
|
size.clamp_between_extremums(
|
||||||
self.content_min_size.cross,
|
self.content_min_size.cross,
|
||||||
|
@ -2008,7 +2024,7 @@ impl FlexItemBox {
|
||||||
let cross_axis_is_item_block_axis =
|
let cross_axis_is_item_block_axis =
|
||||||
cross_axis_is_item_block_axis(container_is_horizontal, item_is_horizontal, flex_axis);
|
cross_axis_is_item_block_axis(container_is_horizontal, item_is_horizontal, flex_axis);
|
||||||
|
|
||||||
let (content_box_size, content_min_size, content_max_size, pbm) =
|
let (content_box_size, content_min_size, content_max_size, pbm, _) =
|
||||||
style.content_box_sizes_and_padding_border_margin_deprecated(containing_block);
|
style.content_box_sizes_and_padding_border_margin_deprecated(containing_block);
|
||||||
let padding = main_start_cross_start.sides_to_flex_relative(pbm.padding);
|
let padding = main_start_cross_start.sides_to_flex_relative(pbm.padding);
|
||||||
let border = main_start_cross_start.sides_to_flex_relative(pbm.border);
|
let border = main_start_cross_start.sides_to_flex_relative(pbm.border);
|
||||||
|
@ -2069,17 +2085,23 @@ impl FlexItemBox {
|
||||||
|
|
||||||
// Compute the min-content and max-content contributions of the item.
|
// Compute the min-content and max-content contributions of the item.
|
||||||
// <https://drafts.csswg.org/css-flexbox/#intrinsic-item-contributions>
|
// <https://drafts.csswg.org/css-flexbox/#intrinsic-item-contributions>
|
||||||
let content_contribution_sizes = match flex_axis {
|
let (content_contribution_sizes, depends_on_block_constraints) = match flex_axis {
|
||||||
FlexAxis::Row => self
|
FlexAxis::Row => {
|
||||||
.independent_formatting_context
|
let InlineContentSizesResult {
|
||||||
.outer_inline_content_sizes(
|
sizes,
|
||||||
layout_context,
|
depends_on_block_constraints,
|
||||||
containing_block,
|
} = self
|
||||||
&content_min_size_no_auto,
|
.independent_formatting_context
|
||||||
item_with_auto_cross_size_stretches_to_container_size,
|
.outer_inline_content_sizes(
|
||||||
),
|
layout_context,
|
||||||
FlexAxis::Column => self
|
containing_block,
|
||||||
.layout_for_block_content_size(
|
&content_min_size_no_auto,
|
||||||
|
item_with_auto_cross_size_stretches_to_container_size,
|
||||||
|
);
|
||||||
|
(sizes, depends_on_block_constraints)
|
||||||
|
},
|
||||||
|
FlexAxis::Column => {
|
||||||
|
let size = self.layout_for_block_content_size(
|
||||||
flex_context_getter(),
|
flex_context_getter(),
|
||||||
&pbm,
|
&pbm,
|
||||||
content_box_size,
|
content_box_size,
|
||||||
|
@ -2087,8 +2109,9 @@ impl FlexItemBox {
|
||||||
content_max_size,
|
content_max_size,
|
||||||
item_with_auto_cross_size_stretches_to_container_size,
|
item_with_auto_cross_size_stretches_to_container_size,
|
||||||
IntrinsicSizingMode::Contribution,
|
IntrinsicSizingMode::Contribution,
|
||||||
)
|
);
|
||||||
.into(),
|
(size.into(), true)
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let content_box_size = flex_axis.vec2_to_flex_relative(content_box_size);
|
let content_box_size = flex_axis.vec2_to_flex_relative(content_box_size);
|
||||||
|
@ -2155,6 +2178,7 @@ impl FlexItemBox {
|
||||||
min_flex_factors,
|
min_flex_factors,
|
||||||
max_flex_factors,
|
max_flex_factors,
|
||||||
min_content_main_size_for_multiline_container,
|
min_content_main_size_for_multiline_container,
|
||||||
|
depends_on_block_constraints,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2282,6 +2306,7 @@ impl FlexItemBox {
|
||||||
&containing_block_for_children,
|
&containing_block_for_children,
|
||||||
containing_block,
|
containing_block,
|
||||||
)
|
)
|
||||||
|
.sizes
|
||||||
.min_content
|
.min_content
|
||||||
} else {
|
} else {
|
||||||
block_content_size_callback(self)
|
block_content_size_callback(self)
|
||||||
|
@ -2444,6 +2469,7 @@ impl FlexItemBox {
|
||||||
&containing_block_for_children,
|
&containing_block_for_children,
|
||||||
containing_block,
|
containing_block,
|
||||||
)
|
)
|
||||||
|
.sizes
|
||||||
.max_content;
|
.max_content;
|
||||||
if let Some(ratio) = ratio {
|
if let Some(ratio) = ratio {
|
||||||
max_content.clamp_between_extremums(
|
max_content.clamp_between_extremums(
|
||||||
|
@ -2522,11 +2548,12 @@ impl FlexItemBox {
|
||||||
let style = non_replaced.style.clone();
|
let style = non_replaced.style.clone();
|
||||||
let containing_block_for_children =
|
let containing_block_for_children =
|
||||||
IndefiniteContainingBlock::new_for_style(&style);
|
IndefiniteContainingBlock::new_for_style(&style);
|
||||||
let inline_content_sizes = non_replaced.inline_content_sizes(
|
non_replaced
|
||||||
flex_context.layout_context,
|
.inline_content_sizes(
|
||||||
&containing_block_for_children,
|
flex_context.layout_context,
|
||||||
);
|
&containing_block_for_children,
|
||||||
inline_content_sizes
|
)
|
||||||
|
.sizes
|
||||||
.shrink_to_fit(containing_block_inline_size_minus_pbm)
|
.shrink_to_fit(containing_block_inline_size_minus_pbm)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -126,7 +126,7 @@ use crate::fragment_tree::{
|
||||||
};
|
};
|
||||||
use crate::geom::{LogicalRect, LogicalVec2, 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, InlineContentSizesResult};
|
||||||
use crate::style_ext::{ComputedValuesExt, PaddingBorderMargin};
|
use crate::style_ext::{ComputedValuesExt, PaddingBorderMargin};
|
||||||
use crate::{ContainingBlock, IndefiniteContainingBlock};
|
use crate::{ContainingBlock, IndefiniteContainingBlock};
|
||||||
|
|
||||||
|
@ -1565,7 +1565,7 @@ impl InlineFormattingContext {
|
||||||
&self,
|
&self,
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
containing_block_for_children: &IndefiniteContainingBlock,
|
containing_block_for_children: &IndefiniteContainingBlock,
|
||||||
) -> ContentSizes {
|
) -> InlineContentSizesResult {
|
||||||
ContentSizesComputation::compute(self, layout_context, containing_block_for_children)
|
ContentSizesComputation::compute(self, layout_context, containing_block_for_children)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2184,16 +2184,23 @@ struct ContentSizesComputation<'layout_data> {
|
||||||
/// Stack of ending padding, margin, and border to add to the length
|
/// Stack of ending padding, margin, and border to add to the length
|
||||||
/// when an inline box finishes.
|
/// when an inline box finishes.
|
||||||
ending_inline_pbm_stack: Vec<Au>,
|
ending_inline_pbm_stack: Vec<Au>,
|
||||||
|
depends_on_block_constraints: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'layout_data> ContentSizesComputation<'layout_data> {
|
impl<'layout_data> ContentSizesComputation<'layout_data> {
|
||||||
fn traverse(mut self, inline_formatting_context: &InlineFormattingContext) -> ContentSizes {
|
fn traverse(
|
||||||
|
mut self,
|
||||||
|
inline_formatting_context: &InlineFormattingContext,
|
||||||
|
) -> InlineContentSizesResult {
|
||||||
for inline_item in inline_formatting_context.inline_items.iter() {
|
for inline_item in inline_formatting_context.inline_items.iter() {
|
||||||
self.process_item(&mut inline_item.borrow_mut(), inline_formatting_context);
|
self.process_item(&mut inline_item.borrow_mut(), inline_formatting_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.forced_line_break();
|
self.forced_line_break();
|
||||||
self.paragraph
|
InlineContentSizesResult {
|
||||||
|
sizes: self.paragraph,
|
||||||
|
depends_on_block_constraints: self.depends_on_block_constraints,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_item(
|
fn process_item(
|
||||||
|
@ -2299,12 +2306,16 @@ impl<'layout_data> ContentSizesComputation<'layout_data> {
|
||||||
self.line_break_opportunity();
|
self.line_break_opportunity();
|
||||||
}
|
}
|
||||||
|
|
||||||
let outer = atomic.outer_inline_content_sizes(
|
let InlineContentSizesResult {
|
||||||
|
sizes: outer,
|
||||||
|
depends_on_block_constraints,
|
||||||
|
} = atomic.outer_inline_content_sizes(
|
||||||
self.layout_context,
|
self.layout_context,
|
||||||
self.containing_block,
|
self.containing_block,
|
||||||
&LogicalVec2::zero(),
|
&LogicalVec2::zero(),
|
||||||
false, /* auto_block_size_stretches_to_containing_block */
|
false, /* auto_block_size_stretches_to_containing_block */
|
||||||
);
|
);
|
||||||
|
self.depends_on_block_constraints |= depends_on_block_constraints;
|
||||||
|
|
||||||
if !inline_formatting_context
|
if !inline_formatting_context
|
||||||
.next_character_prevents_soft_wrap_opportunity(*offset_in_text)
|
.next_character_prevents_soft_wrap_opportunity(*offset_in_text)
|
||||||
|
@ -2356,7 +2367,7 @@ impl<'layout_data> ContentSizesComputation<'layout_data> {
|
||||||
inline_formatting_context: &InlineFormattingContext,
|
inline_formatting_context: &InlineFormattingContext,
|
||||||
layout_context: &'layout_data LayoutContext,
|
layout_context: &'layout_data LayoutContext,
|
||||||
containing_block: &'layout_data IndefiniteContainingBlock,
|
containing_block: &'layout_data IndefiniteContainingBlock,
|
||||||
) -> ContentSizes {
|
) -> InlineContentSizesResult {
|
||||||
Self {
|
Self {
|
||||||
layout_context,
|
layout_context,
|
||||||
containing_block,
|
containing_block,
|
||||||
|
@ -2366,6 +2377,7 @@ impl<'layout_data> ContentSizesComputation<'layout_data> {
|
||||||
had_content_yet_for_min_content: false,
|
had_content_yet_for_min_content: false,
|
||||||
had_content_yet_for_max_content: false,
|
had_content_yet_for_max_content: false,
|
||||||
ending_inline_pbm_stack: Vec::new(),
|
ending_inline_pbm_stack: Vec::new(),
|
||||||
|
depends_on_block_constraints: false,
|
||||||
}
|
}
|
||||||
.traverse(inline_formatting_context)
|
.traverse(inline_formatting_context)
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ use crate::geom::{
|
||||||
};
|
};
|
||||||
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext, PositioningContextLength};
|
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext, PositioningContextLength};
|
||||||
use crate::replaced::ReplacedContent;
|
use crate::replaced::ReplacedContent;
|
||||||
use crate::sizing::{self, ContentSizes};
|
use crate::sizing::{self, ContentSizes, InlineContentSizesResult};
|
||||||
use crate::style_ext::{Clamp, ComputedValuesExt, PaddingBorderMargin};
|
use crate::style_ext::{Clamp, ComputedValuesExt, PaddingBorderMargin};
|
||||||
use crate::{ContainingBlock, IndefiniteContainingBlock};
|
use crate::{ContainingBlock, IndefiniteContainingBlock};
|
||||||
|
|
||||||
|
@ -234,7 +234,7 @@ impl OutsideMarker {
|
||||||
&IndefiniteContainingBlock::new_for_style(&self.marker_style),
|
&IndefiniteContainingBlock::new_for_style(&self.marker_style),
|
||||||
);
|
);
|
||||||
let containing_block_for_children = ContainingBlock {
|
let containing_block_for_children = ContainingBlock {
|
||||||
inline_size: content_sizes.max_content,
|
inline_size: content_sizes.sizes.max_content,
|
||||||
block_size: AuOrAuto::auto(),
|
block_size: AuOrAuto::auto(),
|
||||||
style: &self.marker_style,
|
style: &self.marker_style,
|
||||||
};
|
};
|
||||||
|
@ -361,28 +361,29 @@ fn calculate_inline_content_size_for_block_level_boxes(
|
||||||
boxes: &[ArcRefCell<BlockLevelBox>],
|
boxes: &[ArcRefCell<BlockLevelBox>],
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
containing_block: &IndefiniteContainingBlock,
|
containing_block: &IndefiniteContainingBlock,
|
||||||
) -> ContentSizes {
|
) -> InlineContentSizesResult {
|
||||||
let get_box_info = |box_: &ArcRefCell<BlockLevelBox>| {
|
let get_box_info = |box_: &ArcRefCell<BlockLevelBox>| {
|
||||||
match &mut *box_.borrow_mut() {
|
match &mut *box_.borrow_mut() {
|
||||||
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(_) |
|
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(_) |
|
||||||
BlockLevelBox::OutsideMarker { .. } => None,
|
BlockLevelBox::OutsideMarker { .. } => None,
|
||||||
BlockLevelBox::OutOfFlowFloatBox(ref mut float_box) => {
|
BlockLevelBox::OutOfFlowFloatBox(ref mut float_box) => {
|
||||||
let size = float_box
|
let inline_content_sizes_result = float_box.contents.outer_inline_content_sizes(
|
||||||
.contents
|
layout_context,
|
||||||
.outer_inline_content_sizes(
|
containing_block,
|
||||||
layout_context,
|
&LogicalVec2::zero(),
|
||||||
containing_block,
|
false, /* auto_block_size_stretches_to_containing_block */
|
||||||
&LogicalVec2::zero(),
|
);
|
||||||
false, /* auto_block_size_stretches_to_containing_block */
|
|
||||||
)
|
|
||||||
.max(ContentSizes::zero());
|
|
||||||
let style_box = &float_box.contents.style().get_box();
|
let style_box = &float_box.contents.style().get_box();
|
||||||
Some((size, style_box.float, style_box.clear))
|
Some((
|
||||||
|
inline_content_sizes_result,
|
||||||
|
style_box.float,
|
||||||
|
style_box.clear,
|
||||||
|
))
|
||||||
},
|
},
|
||||||
BlockLevelBox::SameFormattingContextBlock {
|
BlockLevelBox::SameFormattingContextBlock {
|
||||||
style, contents, ..
|
style, contents, ..
|
||||||
} => {
|
} => {
|
||||||
let size = sizing::outer_inline(
|
let inline_content_sizes_result = sizing::outer_inline(
|
||||||
style,
|
style,
|
||||||
containing_block,
|
containing_block,
|
||||||
&LogicalVec2::zero(),
|
&LogicalVec2::zero(),
|
||||||
|
@ -390,30 +391,34 @@ fn calculate_inline_content_size_for_block_level_boxes(
|
||||||
|containing_block_for_children| {
|
|containing_block_for_children| {
|
||||||
contents.inline_content_sizes(layout_context, containing_block_for_children)
|
contents.inline_content_sizes(layout_context, containing_block_for_children)
|
||||||
},
|
},
|
||||||
)
|
);
|
||||||
.max(ContentSizes::zero());
|
|
||||||
// A block in the same BFC can overlap floats, it's not moved next to them,
|
// A block in the same BFC can overlap floats, it's not moved next to them,
|
||||||
// so we shouldn't add its size to the size of the floats.
|
// so we shouldn't add its size to the size of the floats.
|
||||||
// Instead, we treat it like an independent block with 'clear: both'.
|
// Instead, we treat it like an independent block with 'clear: both'.
|
||||||
Some((size, Float::None, Clear::Both))
|
Some((inline_content_sizes_result, Float::None, Clear::Both))
|
||||||
},
|
},
|
||||||
BlockLevelBox::Independent(ref mut independent) => {
|
BlockLevelBox::Independent(ref mut independent) => {
|
||||||
let size = independent
|
let inline_content_sizes_result = independent.outer_inline_content_sizes(
|
||||||
.outer_inline_content_sizes(
|
layout_context,
|
||||||
layout_context,
|
containing_block,
|
||||||
containing_block,
|
&LogicalVec2::zero(),
|
||||||
&LogicalVec2::zero(),
|
false, /* auto_block_size_stretches_to_containing_block */
|
||||||
false, /* auto_block_size_stretches_to_containing_block */
|
);
|
||||||
)
|
Some((
|
||||||
.max(ContentSizes::zero());
|
inline_content_sizes_result,
|
||||||
Some((size, Float::None, independent.style().get_box().clear))
|
Float::None,
|
||||||
|
independent.style().get_box().clear,
|
||||||
|
))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// When iterating the block-level boxes to compute the inline content sizes,
|
/// When iterating the block-level boxes to compute the inline content sizes,
|
||||||
/// this struct contains the data accumulated up to the current box.
|
/// this struct contains the data accumulated up to the current box.
|
||||||
|
#[derive(Default)]
|
||||||
struct AccumulatedData {
|
struct AccumulatedData {
|
||||||
|
/// Whether the inline size depends on the block one.
|
||||||
|
depends_on_block_constraints: bool,
|
||||||
/// The maximum size seen so far, not including trailing uncleared floats.
|
/// The maximum size seen so far, not including trailing uncleared floats.
|
||||||
max_size: ContentSizes,
|
max_size: ContentSizes,
|
||||||
/// The size of the trailing uncleared floats with 'float: left'.
|
/// The size of the trailing uncleared floats with 'float: left'.
|
||||||
|
@ -447,37 +452,44 @@ fn calculate_inline_content_size_for_block_level_boxes(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let accumulate = |mut data: AccumulatedData, (size, float, clear)| {
|
let accumulate =
|
||||||
data.clear_floats(clear);
|
|mut data: AccumulatedData,
|
||||||
match float {
|
(inline_content_sizes_result, float, clear): (InlineContentSizesResult, _, _)| {
|
||||||
Float::Left => data.left_floats = data.left_floats.union(&size),
|
let size = inline_content_sizes_result.sizes.max(ContentSizes::zero());
|
||||||
Float::Right => data.right_floats = data.right_floats.union(&size),
|
let depends_on_block_constraints =
|
||||||
Float::None => {
|
inline_content_sizes_result.depends_on_block_constraints;
|
||||||
data.max_size = data
|
data.depends_on_block_constraints |= depends_on_block_constraints;
|
||||||
.max_size
|
data.clear_floats(clear);
|
||||||
.max(data.left_floats.union(&data.right_floats).union(&size));
|
match float {
|
||||||
data.left_floats = ContentSizes::zero();
|
Float::Left => data.left_floats = data.left_floats.union(&size),
|
||||||
data.right_floats = ContentSizes::zero();
|
Float::Right => data.right_floats = data.right_floats.union(&size),
|
||||||
},
|
Float::None => {
|
||||||
}
|
data.max_size = data
|
||||||
data
|
.max_size
|
||||||
};
|
.max(data.left_floats.union(&data.right_floats).union(&size));
|
||||||
let zero = AccumulatedData {
|
data.left_floats = ContentSizes::zero();
|
||||||
max_size: ContentSizes::zero(),
|
data.right_floats = ContentSizes::zero();
|
||||||
left_floats: ContentSizes::zero(),
|
},
|
||||||
right_floats: ContentSizes::zero(),
|
}
|
||||||
};
|
data
|
||||||
|
};
|
||||||
let data = if layout_context.use_rayon {
|
let data = if layout_context.use_rayon {
|
||||||
boxes
|
boxes
|
||||||
.par_iter()
|
.par_iter()
|
||||||
.filter_map(get_box_info)
|
.filter_map(get_box_info)
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.fold(zero, accumulate)
|
.fold(AccumulatedData::default(), accumulate)
|
||||||
} else {
|
} else {
|
||||||
boxes.iter().filter_map(get_box_info).fold(zero, accumulate)
|
boxes
|
||||||
|
.iter()
|
||||||
|
.filter_map(get_box_info)
|
||||||
|
.fold(AccumulatedData::default(), accumulate)
|
||||||
};
|
};
|
||||||
data.max_size_including_uncleared_floats()
|
InlineContentSizesResult {
|
||||||
|
depends_on_block_constraints: data.depends_on_block_constraints,
|
||||||
|
sizes: data.max_size_including_uncleared_floats(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BlockContainer {
|
impl BlockContainer {
|
||||||
|
@ -512,7 +524,7 @@ impl BlockContainer {
|
||||||
&self,
|
&self,
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
containing_block_for_children: &IndefiniteContainingBlock,
|
containing_block_for_children: &IndefiniteContainingBlock,
|
||||||
) -> ContentSizes {
|
) -> InlineContentSizesResult {
|
||||||
match &self {
|
match &self {
|
||||||
Self::BlockLevelBoxes(boxes) => calculate_inline_content_size_for_block_level_boxes(
|
Self::BlockLevelBoxes(boxes) => calculate_inline_content_size_for_block_level_boxes(
|
||||||
boxes,
|
boxes,
|
||||||
|
@ -1984,6 +1996,7 @@ impl IndependentFormattingContext {
|
||||||
);
|
);
|
||||||
non_replaced
|
non_replaced
|
||||||
.inline_content_sizes(layout_context, &containing_block_for_children)
|
.inline_content_sizes(layout_context, &containing_block_for_children)
|
||||||
|
.sizes
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://drafts.csswg.org/css2/visudet.html#float-width
|
// https://drafts.csswg.org/css2/visudet.html#float-width
|
||||||
|
|
|
@ -18,7 +18,7 @@ use crate::fragment_tree::{BaseFragmentInfo, BoxFragment, Fragment, FragmentFlag
|
||||||
use crate::geom::LogicalSides;
|
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, InlineContentSizesResult};
|
||||||
use crate::style_ext::{AspectRatio, DisplayInside};
|
use crate::style_ext::{AspectRatio, DisplayInside};
|
||||||
use crate::table::Table;
|
use crate::table::Table;
|
||||||
use crate::{AuOrAuto, ContainingBlock, IndefiniteContainingBlock, LogicalVec2};
|
use crate::{AuOrAuto, ContainingBlock, IndefiniteContainingBlock, LogicalVec2};
|
||||||
|
@ -36,7 +36,7 @@ pub(crate) struct NonReplacedFormattingContext {
|
||||||
#[serde(skip_serializing)]
|
#[serde(skip_serializing)]
|
||||||
pub style: Arc<ComputedValues>,
|
pub style: Arc<ComputedValues>,
|
||||||
/// If it was requested during construction
|
/// If it was requested during construction
|
||||||
pub content_sizes: Option<(AuOrAuto, ContentSizes)>,
|
pub content_sizes_result: Option<(AuOrAuto, InlineContentSizesResult)>,
|
||||||
pub contents: NonReplacedFormattingContextContents,
|
pub contents: NonReplacedFormattingContextContents,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ impl IndependentFormattingContext {
|
||||||
Self::NonReplaced(NonReplacedFormattingContext {
|
Self::NonReplaced(NonReplacedFormattingContext {
|
||||||
style: Arc::clone(&node_and_style_info.style),
|
style: Arc::clone(&node_and_style_info.style),
|
||||||
base_fragment_info,
|
base_fragment_info,
|
||||||
content_sizes: None,
|
content_sizes_result: None,
|
||||||
contents,
|
contents,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -187,7 +187,7 @@ impl IndependentFormattingContext {
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
containing_block_for_children: &IndefiniteContainingBlock,
|
containing_block_for_children: &IndefiniteContainingBlock,
|
||||||
containing_block: &IndefiniteContainingBlock,
|
containing_block: &IndefiniteContainingBlock,
|
||||||
) -> ContentSizes {
|
) -> InlineContentSizesResult {
|
||||||
match self {
|
match self {
|
||||||
Self::NonReplaced(inner) => {
|
Self::NonReplaced(inner) => {
|
||||||
inner.inline_content_sizes(layout_context, containing_block_for_children)
|
inner.inline_content_sizes(layout_context, containing_block_for_children)
|
||||||
|
@ -206,7 +206,7 @@ impl IndependentFormattingContext {
|
||||||
containing_block: &IndefiniteContainingBlock,
|
containing_block: &IndefiniteContainingBlock,
|
||||||
auto_minimum: &LogicalVec2<Au>,
|
auto_minimum: &LogicalVec2<Au>,
|
||||||
auto_block_size_stretches_to_containing_block: bool,
|
auto_block_size_stretches_to_containing_block: bool,
|
||||||
) -> ContentSizes {
|
) -> InlineContentSizesResult {
|
||||||
match self {
|
match self {
|
||||||
Self::NonReplaced(non_replaced) => non_replaced.outer_inline_content_sizes(
|
Self::NonReplaced(non_replaced) => non_replaced.outer_inline_content_sizes(
|
||||||
layout_context,
|
layout_context,
|
||||||
|
@ -274,20 +274,22 @@ impl NonReplacedFormattingContext {
|
||||||
&mut self,
|
&mut self,
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
containing_block_for_children: &IndefiniteContainingBlock,
|
containing_block_for_children: &IndefiniteContainingBlock,
|
||||||
) -> ContentSizes {
|
) -> InlineContentSizesResult {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
containing_block_for_children.size.inline,
|
containing_block_for_children.size.inline,
|
||||||
AuOrAuto::Auto,
|
AuOrAuto::Auto,
|
||||||
"inline_content_sizes() got non-auto containing block inline-size",
|
"inline_content_sizes() got non-auto containing block inline-size",
|
||||||
);
|
);
|
||||||
if let Some((previous_cb_block_size, result)) = self.content_sizes {
|
if let Some((previous_cb_block_size, result)) = self.content_sizes_result {
|
||||||
if previous_cb_block_size == containing_block_for_children.size.block {
|
if !result.depends_on_block_constraints ||
|
||||||
|
previous_cb_block_size == containing_block_for_children.size.block
|
||||||
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
// TODO: Should we keep multiple caches for various block sizes?
|
// TODO: Should we keep multiple caches for various block sizes?
|
||||||
}
|
}
|
||||||
|
|
||||||
self.content_sizes
|
self.content_sizes_result
|
||||||
.insert((
|
.insert((
|
||||||
containing_block_for_children.size.block,
|
containing_block_for_children.size.block,
|
||||||
self.contents
|
self.contents
|
||||||
|
@ -302,7 +304,7 @@ impl NonReplacedFormattingContext {
|
||||||
containing_block: &IndefiniteContainingBlock,
|
containing_block: &IndefiniteContainingBlock,
|
||||||
auto_minimum: &LogicalVec2<Au>,
|
auto_minimum: &LogicalVec2<Au>,
|
||||||
auto_block_size_stretches_to_containing_block: bool,
|
auto_block_size_stretches_to_containing_block: bool,
|
||||||
) -> ContentSizes {
|
) -> InlineContentSizesResult {
|
||||||
sizing::outer_inline(
|
sizing::outer_inline(
|
||||||
&self.style.clone(),
|
&self.style.clone(),
|
||||||
containing_block,
|
containing_block,
|
||||||
|
@ -320,7 +322,7 @@ impl NonReplacedFormattingContextContents {
|
||||||
&mut self,
|
&mut self,
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
containing_block_for_children: &IndefiniteContainingBlock,
|
containing_block_for_children: &IndefiniteContainingBlock,
|
||||||
) -> ContentSizes {
|
) -> InlineContentSizesResult {
|
||||||
match self {
|
match self {
|
||||||
Self::Flow(inner) => inner
|
Self::Flow(inner) => inner
|
||||||
.contents
|
.contents
|
||||||
|
|
|
@ -65,7 +65,7 @@ impl<'a> IndefiniteContainingBlock<'a> {
|
||||||
style: &'a ComputedValues,
|
style: &'a ComputedValues,
|
||||||
auto_minimum: &LogicalVec2<Au>,
|
auto_minimum: &LogicalVec2<Au>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let (content_box_size, content_min_size, content_max_size, _) =
|
let (content_box_size, content_min_size, content_max_size, _, _) =
|
||||||
style.content_box_sizes_and_padding_border_margin_deprecated(self);
|
style.content_box_sizes_and_padding_border_margin_deprecated(self);
|
||||||
let block_size = content_box_size.block.map(|v| {
|
let block_size = content_box_size.block.map(|v| {
|
||||||
v.clamp_between_extremums(
|
v.clamp_between_extremums(
|
||||||
|
|
|
@ -587,6 +587,7 @@ impl HoistedAbsolutelyPositionedBox {
|
||||||
);
|
);
|
||||||
non_replaced
|
non_replaced
|
||||||
.inline_content_sizes(layout_context, &containing_block_for_children)
|
.inline_content_sizes(layout_context, &containing_block_for_children)
|
||||||
|
.sizes
|
||||||
.shrink_to_fit(available_size)
|
.shrink_to_fit(available_size)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ use crate::context::LayoutContext;
|
||||||
use crate::dom::NodeExt;
|
use crate::dom::NodeExt;
|
||||||
use crate::fragment_tree::{BaseFragmentInfo, Fragment, IFrameFragment, ImageFragment};
|
use crate::fragment_tree::{BaseFragmentInfo, Fragment, IFrameFragment, ImageFragment};
|
||||||
use crate::geom::{LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSize};
|
use crate::geom::{LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSize};
|
||||||
use crate::sizing::ContentSizes;
|
use crate::sizing::InlineContentSizesResult;
|
||||||
use crate::style_ext::{AspectRatio, Clamp, ComputedValuesExt, PaddingBorderMargin};
|
use crate::style_ext::{AspectRatio, Clamp, ComputedValuesExt, PaddingBorderMargin};
|
||||||
use crate::{AuOrAuto, ContainingBlock, IndefiniteContainingBlock};
|
use crate::{AuOrAuto, ContainingBlock, IndefiniteContainingBlock};
|
||||||
|
|
||||||
|
@ -263,21 +263,27 @@ impl ReplacedContent {
|
||||||
_: &LayoutContext,
|
_: &LayoutContext,
|
||||||
containing_block_for_children: &IndefiniteContainingBlock,
|
containing_block_for_children: &IndefiniteContainingBlock,
|
||||||
preferred_aspect_ratio: Option<AspectRatio>,
|
preferred_aspect_ratio: Option<AspectRatio>,
|
||||||
) -> ContentSizes {
|
) -> InlineContentSizesResult {
|
||||||
// FIXME: min/max-content of replaced elements is not defined in
|
// FIXME: min/max-content of replaced elements is not defined in
|
||||||
// https://dbaron.org/css/intrinsic/
|
// https://dbaron.org/css/intrinsic/
|
||||||
// This seems sensible?
|
// This seems sensible?
|
||||||
let block_size = containing_block_for_children.size.block;
|
let block_size = containing_block_for_children.size.block;
|
||||||
let inline_size = match (block_size, preferred_aspect_ratio) {
|
match (block_size, preferred_aspect_ratio) {
|
||||||
(AuOrAuto::LengthPercentage(block_size), Some(ratio)) => {
|
(AuOrAuto::LengthPercentage(block_size), Some(ratio)) => InlineContentSizesResult {
|
||||||
ratio.compute_dependent_size(Direction::Inline, block_size)
|
sizes: ratio
|
||||||
|
.compute_dependent_size(Direction::Inline, block_size)
|
||||||
|
.into(),
|
||||||
|
depends_on_block_constraints: true,
|
||||||
},
|
},
|
||||||
_ => self
|
_ => InlineContentSizesResult {
|
||||||
.flow_relative_intrinsic_size(containing_block_for_children.style)
|
sizes: self
|
||||||
.inline
|
.flow_relative_intrinsic_size(containing_block_for_children.style)
|
||||||
.unwrap_or_else(Au::zero),
|
.inline
|
||||||
};
|
.unwrap_or_else(Au::zero)
|
||||||
inline_size.into()
|
.into(),
|
||||||
|
depends_on_block_constraints: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_fragments(
|
pub fn make_fragments(
|
||||||
|
|
|
@ -118,10 +118,15 @@ pub(crate) fn outer_inline(
|
||||||
containing_block: &IndefiniteContainingBlock,
|
containing_block: &IndefiniteContainingBlock,
|
||||||
auto_minimum: &LogicalVec2<Au>,
|
auto_minimum: &LogicalVec2<Au>,
|
||||||
auto_block_size_stretches_to_containing_block: bool,
|
auto_block_size_stretches_to_containing_block: bool,
|
||||||
get_content_size: impl FnOnce(&IndefiniteContainingBlock) -> ContentSizes,
|
get_content_size: impl FnOnce(&IndefiniteContainingBlock) -> InlineContentSizesResult,
|
||||||
) -> ContentSizes {
|
) -> InlineContentSizesResult {
|
||||||
let (content_box_size, content_min_size, content_max_size, pbm) =
|
let (
|
||||||
style.content_box_sizes_and_padding_border_margin_deprecated(containing_block);
|
content_box_size,
|
||||||
|
content_min_size,
|
||||||
|
content_max_size,
|
||||||
|
pbm,
|
||||||
|
mut depends_on_block_constraints,
|
||||||
|
) = style.content_box_sizes_and_padding_border_margin_deprecated(containing_block);
|
||||||
let content_min_size = LogicalVec2 {
|
let content_min_size = LogicalVec2 {
|
||||||
inline: content_min_size.inline.auto_is(|| auto_minimum.inline),
|
inline: content_min_size.inline.auto_is(|| auto_minimum.inline),
|
||||||
block: content_min_size.block.auto_is(|| auto_minimum.block),
|
block: content_min_size.block.auto_is(|| auto_minimum.block),
|
||||||
|
@ -132,11 +137,15 @@ pub(crate) fn outer_inline(
|
||||||
v.clamp_between_extremums(content_min_size.inline, content_max_size.inline) + pbm_inline_sum
|
v.clamp_between_extremums(content_min_size.inline, content_max_size.inline) + pbm_inline_sum
|
||||||
};
|
};
|
||||||
match content_box_size.inline {
|
match content_box_size.inline {
|
||||||
AuOrAuto::LengthPercentage(inline_size) => adjust(inline_size).into(),
|
AuOrAuto::LengthPercentage(inline_size) => InlineContentSizesResult {
|
||||||
|
sizes: adjust(inline_size).into(),
|
||||||
|
depends_on_block_constraints: false,
|
||||||
|
},
|
||||||
AuOrAuto::Auto => {
|
AuOrAuto::Auto => {
|
||||||
let block_size = if content_box_size.block.is_auto() &&
|
let block_size = if content_box_size.block.is_auto() &&
|
||||||
auto_block_size_stretches_to_containing_block
|
auto_block_size_stretches_to_containing_block
|
||||||
{
|
{
|
||||||
|
depends_on_block_constraints = true;
|
||||||
let outer_block_size = containing_block.size.block;
|
let outer_block_size = containing_block.size.block;
|
||||||
outer_block_size.map(|v| v - pbm.padding_border_sums.block - margin.block_sum())
|
outer_block_size.map(|v| v - pbm.padding_border_sums.block - margin.block_sum())
|
||||||
} else {
|
} else {
|
||||||
|
@ -145,7 +154,18 @@ pub(crate) fn outer_inline(
|
||||||
.map(|v| v.clamp_between_extremums(content_min_size.block, content_max_size.block));
|
.map(|v| v.clamp_between_extremums(content_min_size.block, content_max_size.block));
|
||||||
let containing_block_for_children =
|
let containing_block_for_children =
|
||||||
IndefiniteContainingBlock::new_for_style_and_block_size(style, block_size);
|
IndefiniteContainingBlock::new_for_style_and_block_size(style, block_size);
|
||||||
get_content_size(&containing_block_for_children).map(adjust)
|
let content_result = get_content_size(&containing_block_for_children);
|
||||||
|
InlineContentSizesResult {
|
||||||
|
sizes: content_result.sizes.map(adjust),
|
||||||
|
depends_on_block_constraints: content_result.depends_on_block_constraints &&
|
||||||
|
depends_on_block_constraints,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize)]
|
||||||
|
pub(crate) struct InlineContentSizesResult {
|
||||||
|
pub sizes: ContentSizes,
|
||||||
|
pub depends_on_block_constraints: bool,
|
||||||
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ use crate::dom_traversal::Contents;
|
||||||
use crate::fragment_tree::FragmentFlags;
|
use crate::fragment_tree::FragmentFlags;
|
||||||
use crate::geom::{
|
use crate::geom::{
|
||||||
AuOrAuto, LengthPercentageOrAuto, LogicalSides, LogicalVec2, PhysicalSides, PhysicalSize,
|
AuOrAuto, LengthPercentageOrAuto, LogicalSides, LogicalVec2, PhysicalSides, PhysicalSize,
|
||||||
PhysicalVec, Size,
|
PhysicalVec, Size, SizeKeyword,
|
||||||
};
|
};
|
||||||
use crate::{ContainingBlock, IndefiniteContainingBlock};
|
use crate::{ContainingBlock, IndefiniteContainingBlock};
|
||||||
|
|
||||||
|
@ -249,6 +249,7 @@ pub(crate) trait ComputedValuesExt {
|
||||||
LogicalVec2<Size<Au>>,
|
LogicalVec2<Size<Au>>,
|
||||||
LogicalVec2<Size<Au>>,
|
LogicalVec2<Size<Au>>,
|
||||||
PaddingBorderMargin,
|
PaddingBorderMargin,
|
||||||
|
bool, /* depends_on_block_constraints */
|
||||||
);
|
);
|
||||||
fn content_box_sizes_and_padding_border_margin_deprecated(
|
fn content_box_sizes_and_padding_border_margin_deprecated(
|
||||||
&self,
|
&self,
|
||||||
|
@ -258,6 +259,7 @@ pub(crate) trait ComputedValuesExt {
|
||||||
LogicalVec2<AuOrAuto>,
|
LogicalVec2<AuOrAuto>,
|
||||||
LogicalVec2<Option<Au>>,
|
LogicalVec2<Option<Au>>,
|
||||||
PaddingBorderMargin,
|
PaddingBorderMargin,
|
||||||
|
bool, /* depends_on_block_constraints */
|
||||||
);
|
);
|
||||||
fn padding_border_margin(&self, containing_block: &ContainingBlock) -> PaddingBorderMargin;
|
fn padding_border_margin(&self, containing_block: &ContainingBlock) -> PaddingBorderMargin;
|
||||||
fn padding_border_margin_for_intrinsic_size(
|
fn padding_border_margin_for_intrinsic_size(
|
||||||
|
@ -499,6 +501,7 @@ impl ComputedValuesExt for ComputedValues {
|
||||||
LogicalVec2<Size<Au>>,
|
LogicalVec2<Size<Au>>,
|
||||||
LogicalVec2<Size<Au>>,
|
LogicalVec2<Size<Au>>,
|
||||||
PaddingBorderMargin,
|
PaddingBorderMargin,
|
||||||
|
bool, /* depends_on_block_constraints */
|
||||||
) {
|
) {
|
||||||
// <https://drafts.csswg.org/css-sizing-3/#cyclic-percentage-contribution>
|
// <https://drafts.csswg.org/css-sizing-3/#cyclic-percentage-contribution>
|
||||||
// If max size properties or preferred size properties are set to a value containing
|
// If max size properties or preferred size properties are set to a value containing
|
||||||
|
@ -513,25 +516,45 @@ impl ComputedValuesExt for ComputedValues {
|
||||||
writing_mode,
|
writing_mode,
|
||||||
containing_block.size.inline.auto_is(Au::zero),
|
containing_block.size.inline.auto_is(Au::zero),
|
||||||
);
|
);
|
||||||
let box_size = self
|
let box_size = self.box_size(writing_mode);
|
||||||
.box_size(writing_mode)
|
let min_size = self.min_box_size(writing_mode);
|
||||||
.maybe_percentages_relative_to_basis(&containing_block_size);
|
let max_size = self.max_box_size(writing_mode);
|
||||||
|
let depends_on_block_constraints = |size: &Size<LengthPercentage>| {
|
||||||
|
match size {
|
||||||
|
// fit-content is like clamp(min-content, stretch, max-content), but currently
|
||||||
|
// min-content and max-content have the same behavior in the block axis,
|
||||||
|
// so there is no dependency on block constraints.
|
||||||
|
// TODO: for flex and grid layout, min-content and max-content should be different.
|
||||||
|
// TODO: We are assuming that Size::Initial doesn't stretch. However, it may actually
|
||||||
|
// stretch flex and grid items depending on the CSS Align properties, in that case
|
||||||
|
// the caller needs to take care of it.
|
||||||
|
Size::Keyword(SizeKeyword::Stretch) => true,
|
||||||
|
Size::Numeric(length_percentage) => length_percentage.has_percentage(),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let depends_on_block_constraints = depends_on_block_constraints(&box_size.block) ||
|
||||||
|
depends_on_block_constraints(&min_size.block) ||
|
||||||
|
depends_on_block_constraints(&max_size.block);
|
||||||
|
let box_size = box_size.maybe_percentages_relative_to_basis(&containing_block_size);
|
||||||
let content_box_size = self
|
let content_box_size = self
|
||||||
.content_box_size_for_box_size(box_size, &pbm)
|
.content_box_size_for_box_size(box_size, &pbm)
|
||||||
.map(|v| v.map(Au::from));
|
.map(|v| v.map(Au::from));
|
||||||
let min_size = self
|
let min_size = min_size.percentages_relative_to_basis(&containing_block_size_auto_is_zero);
|
||||||
.min_box_size(writing_mode)
|
|
||||||
.percentages_relative_to_basis(&containing_block_size_auto_is_zero);
|
|
||||||
let content_min_size = self
|
let content_min_size = self
|
||||||
.content_min_box_size_for_min_size(min_size, &pbm)
|
.content_min_box_size_for_min_size(min_size, &pbm)
|
||||||
.map(|v| v.map(Au::from));
|
.map(|v| v.map(Au::from));
|
||||||
let max_size = self
|
let max_size = max_size.maybe_percentages_relative_to_basis(&containing_block_size);
|
||||||
.max_box_size(writing_mode)
|
|
||||||
.maybe_percentages_relative_to_basis(&containing_block_size);
|
|
||||||
let content_max_size = self
|
let content_max_size = self
|
||||||
.content_max_box_size_for_max_size(max_size, &pbm)
|
.content_max_box_size_for_max_size(max_size, &pbm)
|
||||||
.map(|v| v.map(Au::from));
|
.map(|v| v.map(Au::from));
|
||||||
(content_box_size, content_min_size, content_max_size, pbm)
|
(
|
||||||
|
content_box_size,
|
||||||
|
content_min_size,
|
||||||
|
content_max_size,
|
||||||
|
pbm,
|
||||||
|
depends_on_block_constraints,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn content_box_sizes_and_padding_border_margin_deprecated(
|
fn content_box_sizes_and_padding_border_margin_deprecated(
|
||||||
|
@ -542,14 +565,21 @@ impl ComputedValuesExt for ComputedValues {
|
||||||
LogicalVec2<AuOrAuto>,
|
LogicalVec2<AuOrAuto>,
|
||||||
LogicalVec2<Option<Au>>,
|
LogicalVec2<Option<Au>>,
|
||||||
PaddingBorderMargin,
|
PaddingBorderMargin,
|
||||||
|
bool, /* depends_on_block_constraints */
|
||||||
) {
|
) {
|
||||||
let (content_box_size, content_min_size, content_max_size, pbm) =
|
let (
|
||||||
self.content_box_sizes_and_padding_border_margin(containing_block);
|
content_box_size,
|
||||||
|
content_min_size,
|
||||||
|
content_max_size,
|
||||||
|
pbm,
|
||||||
|
depends_on_block_constraints,
|
||||||
|
) = self.content_box_sizes_and_padding_border_margin(containing_block);
|
||||||
(
|
(
|
||||||
content_box_size.map(Size::to_auto_or),
|
content_box_size.map(Size::to_auto_or),
|
||||||
content_min_size.map(Size::to_auto_or),
|
content_min_size.map(Size::to_auto_or),
|
||||||
content_max_size.map(Size::to_numeric),
|
content_max_size.map(Size::to_numeric),
|
||||||
pbm,
|
pbm,
|
||||||
|
depends_on_block_constraints,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -137,7 +137,7 @@ impl Table {
|
||||||
IndependentFormattingContext::NonReplaced(NonReplacedFormattingContext {
|
IndependentFormattingContext::NonReplaced(NonReplacedFormattingContext {
|
||||||
base_fragment_info: (&anonymous_info).into(),
|
base_fragment_info: (&anonymous_info).into(),
|
||||||
style: grid_and_wrapper_style,
|
style: grid_and_wrapper_style,
|
||||||
content_sizes: None,
|
content_sizes_result: None,
|
||||||
contents: NonReplacedFormattingContextContents::Table(table),
|
contents: NonReplacedFormattingContextContents::Table(table),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -858,7 +858,7 @@ where
|
||||||
context: ArcRefCell::new(NonReplacedFormattingContext {
|
context: ArcRefCell::new(NonReplacedFormattingContext {
|
||||||
style: info.style.clone(),
|
style: info.style.clone(),
|
||||||
base_fragment_info: info.into(),
|
base_fragment_info: info.into(),
|
||||||
content_sizes: None,
|
content_sizes_result: None,
|
||||||
contents,
|
contents,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
|
@ -38,7 +38,7 @@ use crate::geom::{
|
||||||
Size, SizeKeyword, ToLogical, ToLogicalWithContainingBlock,
|
Size, SizeKeyword, ToLogical, ToLogicalWithContainingBlock,
|
||||||
};
|
};
|
||||||
use crate::positioned::{relative_adjustement, PositioningContext, PositioningContextLength};
|
use crate::positioned::{relative_adjustement, PositioningContext, PositioningContextLength};
|
||||||
use crate::sizing::ContentSizes;
|
use crate::sizing::{ContentSizes, InlineContentSizesResult};
|
||||||
use crate::style_ext::{Clamp, ComputedValuesExt, PaddingBorderMargin};
|
use crate::style_ext::{Clamp, ComputedValuesExt, PaddingBorderMargin};
|
||||||
use crate::table::TableSlotCoordinates;
|
use crate::table::TableSlotCoordinates;
|
||||||
use crate::{ContainingBlock, IndefiniteContainingBlock};
|
use crate::{ContainingBlock, IndefiniteContainingBlock};
|
||||||
|
@ -298,10 +298,13 @@ impl<'a> TableLayout<'a> {
|
||||||
let mut inline_content_sizes = if is_in_fixed_mode {
|
let mut inline_content_sizes = if is_in_fixed_mode {
|
||||||
ContentSizes::zero()
|
ContentSizes::zero()
|
||||||
} else {
|
} else {
|
||||||
cell.contents.contents.inline_content_sizes(
|
cell.contents
|
||||||
layout_context,
|
.contents
|
||||||
&IndefiniteContainingBlock::new_for_style(&cell.style),
|
.inline_content_sizes(
|
||||||
)
|
layout_context,
|
||||||
|
&IndefiniteContainingBlock::new_for_style(&cell.style),
|
||||||
|
)
|
||||||
|
.sizes
|
||||||
};
|
};
|
||||||
inline_content_sizes.min_content += padding_border_sums.inline;
|
inline_content_sizes.min_content += padding_border_sums.inline;
|
||||||
inline_content_sizes.max_content += padding_border_sums.inline;
|
inline_content_sizes.max_content += padding_border_sums.inline;
|
||||||
|
@ -784,6 +787,7 @@ impl<'a> TableLayout<'a> {
|
||||||
&LogicalVec2::zero(),
|
&LogicalVec2::zero(),
|
||||||
false, /* auto_block_size_stretches_to_containing_block */
|
false, /* auto_block_size_stretches_to_containing_block */
|
||||||
)
|
)
|
||||||
|
.sizes
|
||||||
.min_content
|
.min_content
|
||||||
})
|
})
|
||||||
.max()
|
.max()
|
||||||
|
@ -2611,7 +2615,7 @@ impl Table {
|
||||||
&mut self,
|
&mut self,
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
containing_block_for_children: &IndefiniteContainingBlock,
|
containing_block_for_children: &IndefiniteContainingBlock,
|
||||||
) -> ContentSizes {
|
) -> InlineContentSizesResult {
|
||||||
let writing_mode = containing_block_for_children.style.writing_mode;
|
let writing_mode = containing_block_for_children.style.writing_mode;
|
||||||
let mut layout = TableLayout::new(self);
|
let mut layout = TableLayout::new(self);
|
||||||
let mut table_content_sizes = layout.compute_grid_min_max(layout_context, writing_mode);
|
let mut table_content_sizes = layout.compute_grid_min_max(layout_context, writing_mode);
|
||||||
|
@ -2638,7 +2642,10 @@ impl Table {
|
||||||
.max_assign(caption_minimum_inline_size);
|
.max_assign(caption_minimum_inline_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
table_content_sizes
|
InlineContentSizesResult {
|
||||||
|
sizes: table_content_sizes,
|
||||||
|
depends_on_block_constraints: false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_column_measure_for_column_at_index(
|
fn get_column_measure_for_column_at_index(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue