Replace boolean parameters by a new ContentSizesRequest enum

This commit is contained in:
Simon Sapin 2019-12-04 15:10:11 +01:00
parent 6763e7e4ae
commit 38e8fd1e99
6 changed files with 92 additions and 62 deletions

View file

@ -10,7 +10,7 @@ use crate::flow::inline::{InlineBox, InlineFormattingContext, InlineLevelBox, Te
use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox}; use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox};
use crate::formatting_contexts::IndependentFormattingContext; use crate::formatting_contexts::IndependentFormattingContext;
use crate::positioned::AbsolutelyPositionedBox; use crate::positioned::AbsolutelyPositionedBox;
use crate::sizing::{outer_inline_content_sizes, ContentSizes}; use crate::sizing::{outer_inline_content_sizes, ContentSizes, ContentSizesRequest};
use crate::style_ext::{ComputedValuesExt, DisplayGeneratingBox, DisplayInside, DisplayOutside}; use crate::style_ext::{ComputedValuesExt, DisplayGeneratingBox, DisplayInside, DisplayOutside};
use rayon::iter::{IntoParallelIterator, ParallelIterator}; use rayon::iter::{IntoParallelIterator, ParallelIterator};
use rayon_croissant::ParallelIteratorExt; use rayon_croissant::ParallelIteratorExt;
@ -24,17 +24,17 @@ impl BlockFormattingContext {
context: &LayoutContext, context: &LayoutContext,
style: &Arc<ComputedValues>, style: &Arc<ComputedValues>,
contents: NonReplacedContents<impl NodeExt<'dom>>, contents: NonReplacedContents<impl NodeExt<'dom>>,
request_content_sizes: bool, content_sizes: ContentSizesRequest,
) -> (Self, Option<ContentSizes>) { ) -> (Self, Option<ContentSizes>) {
let (contents, contains_floats, content_sizes) = let (contents, contains_floats, inline_content_sizes) =
BlockContainer::construct(context, style, contents, request_content_sizes); BlockContainer::construct(context, style, contents, content_sizes);
// FIXME: add contribution to `content_sizes` of floats in this formatting context // FIXME: add contribution to `inline_content_sizes` of floats in this formatting context
// https://dbaron.org/css/intrinsic/#intrinsic // https://dbaron.org/css/intrinsic/#intrinsic
let bfc = Self { let bfc = Self {
contents, contents,
contains_floats: contains_floats == ContainsFloats::Yes, contains_floats: contains_floats == ContainsFloats::Yes,
}; };
(bfc, content_sizes) (bfc, inline_content_sizes)
} }
} }
@ -133,7 +133,7 @@ impl BlockContainer {
context: &LayoutContext, context: &LayoutContext,
block_container_style: &Arc<ComputedValues>, block_container_style: &Arc<ComputedValues>,
contents: NonReplacedContents<impl NodeExt<'dom>>, contents: NonReplacedContents<impl NodeExt<'dom>>,
request_content_sizes: bool, content_sizes: ContentSizesRequest,
) -> (BlockContainer, ContainsFloats, Option<ContentSizes>) { ) -> (BlockContainer, ContainsFloats, Option<ContentSizes>) {
let mut builder = BlockContainerBuilder { let mut builder = BlockContainerBuilder {
context, context,
@ -155,19 +155,15 @@ impl BlockContainer {
.is_empty() .is_empty()
{ {
if builder.block_level_boxes.is_empty() { if builder.block_level_boxes.is_empty() {
let content_sizes = if request_content_sizes { let inline_content_sizes = content_sizes.if_requests_inline(|| {
Some( builder
builder .ongoing_inline_formatting_context
.ongoing_inline_formatting_context .inline_content_sizes(context)
.inline_content_sizes(context), });
)
} else {
None
};
let container = BlockContainer::InlineFormattingContext( let container = BlockContainer::InlineFormattingContext(
builder.ongoing_inline_formatting_context, builder.ongoing_inline_formatting_context,
); );
return (container, builder.contains_floats, content_sizes); return (container, builder.contains_floats, inline_content_sizes);
} }
builder.end_ongoing_inline_formatting_context(); builder.end_ongoing_inline_formatting_context();
} }
@ -195,11 +191,8 @@ impl BlockContainer {
|target, (intermediate, box_slot): (Intermediate<_>, BoxSlot<'_>)| { |target, (intermediate, box_slot): (Intermediate<_>, BoxSlot<'_>)| {
let (block_level_box, box_contains_floats) = intermediate.finish( let (block_level_box, box_contains_floats) = intermediate.finish(
context, context,
if request_content_sizes { content_sizes
Some(&mut target.outer_content_sizes_of_children) .if_requests_inline(|| &mut target.outer_content_sizes_of_children),
} else {
None
},
); );
target.contains_floats |= box_contains_floats; target.contains_floats |= box_contains_floats;
box_slot.set(LayoutBox::BlockLevel(block_level_box.clone())); box_slot.set(LayoutBox::BlockLevel(block_level_box.clone()));
@ -207,19 +200,21 @@ impl BlockContainer {
}, },
|left, right| { |left, right| {
left.contains_floats |= right.contains_floats; left.contains_floats |= right.contains_floats;
if request_content_sizes { if content_sizes.requests_inline() {
left.outer_content_sizes_of_children left.outer_content_sizes_of_children
.max_assign(&right.outer_content_sizes_of_children) .max_assign(&right.outer_content_sizes_of_children)
} }
}, },
); );
let container = BlockContainer::BlockLevelBoxes(iter.collect()); let container = BlockContainer::BlockLevelBoxes(iter.collect());
let content_sizes = if request_content_sizes {
Some(target.outer_content_sizes_of_children) let Target {
} else { contains_floats,
None outer_content_sizes_of_children,
}; } = target;
(container, target.contains_floats, content_sizes) let inline_content_sizes =
content_sizes.if_requests_inline(|| outer_content_sizes_of_children);
(container, contains_floats, inline_content_sizes)
} }
} }
@ -393,14 +388,13 @@ where
inline_box.last_fragment = true; inline_box.last_fragment = true;
Arc::new(InlineLevelBox::InlineBox(inline_box)) Arc::new(InlineLevelBox::InlineBox(inline_box))
} else { } else {
let request_content_sizes = style.inline_size_is_auto();
Arc::new(InlineLevelBox::Atomic( Arc::new(InlineLevelBox::Atomic(
IndependentFormattingContext::construct( IndependentFormattingContext::construct(
self.context, self.context,
style.clone(), style.clone(),
display_inside, display_inside,
contents, contents,
request_content_sizes, ContentSizesRequest::inline_if(style.inline_size_is_auto()),
), ),
)) ))
}; };
@ -592,12 +586,16 @@ where
) -> (Arc<BlockLevelBox>, ContainsFloats) { ) -> (Arc<BlockLevelBox>, ContainsFloats) {
match self { match self {
IntermediateBlockLevelBox::SameFormattingContextBlock { style, contents } => { IntermediateBlockLevelBox::SameFormattingContextBlock { style, contents } => {
let request_content_sizes = max_assign_in_flow_outer_content_sizes_to.is_some() && let (contents, contains_floats, inline_content_sizes) = contents.finish(
style.inline_size_is_auto(); context,
let (contents, contains_floats, content_sizes) = &style,
contents.finish(context, &style, request_content_sizes); ContentSizesRequest::inline_if(
max_assign_in_flow_outer_content_sizes_to.is_some() &&
style.inline_size_is_auto(),
),
);
if let Some(to) = max_assign_in_flow_outer_content_sizes_to { if let Some(to) = max_assign_in_flow_outer_content_sizes_to {
to.max_assign(&outer_inline_content_sizes(&style, &content_sizes)) to.max_assign(&outer_inline_content_sizes(&style, &inline_content_sizes))
} }
let block_level_box = let block_level_box =
Arc::new(BlockLevelBox::SameFormattingContextBlock { contents, style }); Arc::new(BlockLevelBox::SameFormattingContextBlock { contents, style });
@ -608,14 +606,16 @@ where
display_inside, display_inside,
contents, contents,
} => { } => {
let request_content_sizes = max_assign_in_flow_outer_content_sizes_to.is_some() && let content_sizes = ContentSizesRequest::inline_if(
style.inline_size_is_auto(); max_assign_in_flow_outer_content_sizes_to.is_some() &&
style.inline_size_is_auto(),
);
let contents = IndependentFormattingContext::construct( let contents = IndependentFormattingContext::construct(
context, context,
style, style,
display_inside, display_inside,
contents, contents,
request_content_sizes, content_sizes,
); );
if let Some(to) = max_assign_in_flow_outer_content_sizes_to { if let Some(to) = max_assign_in_flow_outer_content_sizes_to {
to.max_assign(&outer_inline_content_sizes( to.max_assign(&outer_inline_content_sizes(
@ -660,25 +660,22 @@ where
self, self,
context: &LayoutContext, context: &LayoutContext,
style: &Arc<ComputedValues>, style: &Arc<ComputedValues>,
request_content_sizes: bool, content_sizes: ContentSizesRequest,
) -> (BlockContainer, ContainsFloats, Option<ContentSizes>) { ) -> (BlockContainer, ContainsFloats, Option<ContentSizes>) {
match self { match self {
IntermediateBlockContainer::Deferred { contents } => { IntermediateBlockContainer::Deferred { contents } => {
BlockContainer::construct(context, style, contents, request_content_sizes) BlockContainer::construct(context, style, contents, content_sizes)
}, },
IntermediateBlockContainer::InlineFormattingContext(ifc) => { IntermediateBlockContainer::InlineFormattingContext(ifc) => {
let content_sizes = if request_content_sizes { let inline_content_sizes =
Some(ifc.inline_content_sizes(context)) content_sizes.if_requests_inline(|| ifc.inline_content_sizes(context));
} else {
None
};
// If that inline formatting context contained any float, those // If that inline formatting context contained any float, those
// were already taken into account during the first phase of // were already taken into account during the first phase of
// box construction. // box construction.
( (
BlockContainer::InlineFormattingContext(ifc), BlockContainer::InlineFormattingContext(ifc),
ContainsFloats::No, ContainsFloats::No,
content_sizes, inline_content_sizes,
) )
}, },
} }

View file

@ -5,6 +5,7 @@
use crate::context::LayoutContext; use crate::context::LayoutContext;
use crate::dom_traversal::{Contents, NodeExt}; use crate::dom_traversal::{Contents, NodeExt};
use crate::formatting_contexts::IndependentFormattingContext; use crate::formatting_contexts::IndependentFormattingContext;
use crate::sizing::ContentSizesRequest;
use crate::style_ext::{ComputedValuesExt, DisplayInside}; use crate::style_ext::{ComputedValuesExt, DisplayInside};
use servo_arc::Arc; use servo_arc::Arc;
use style::properties::ComputedValues; use style::properties::ComputedValues;
@ -32,14 +33,14 @@ impl FloatBox {
display_inside: DisplayInside, display_inside: DisplayInside,
contents: Contents<impl NodeExt<'dom>>, contents: Contents<impl NodeExt<'dom>>,
) -> Self { ) -> Self {
let request_content_sizes = style.inline_size_is_auto(); let content_sizes = ContentSizesRequest::inline_if(style.inline_size_is_auto());
Self { Self {
contents: IndependentFormattingContext::construct( contents: IndependentFormattingContext::construct(
context, context,
style, style,
display_inside, display_inside,
contents, contents,
request_content_sizes, content_sizes,
), ),
} }
} }

View file

@ -14,6 +14,7 @@ use crate::geom;
use crate::geom::flow_relative::Vec2; use crate::geom::flow_relative::Vec2;
use crate::positioned::AbsolutelyPositionedBox; use crate::positioned::AbsolutelyPositionedBox;
use crate::replaced::ReplacedContent; use crate::replaced::ReplacedContent;
use crate::sizing::ContentSizesRequest;
use crate::style_ext::{Direction, Display, DisplayGeneratingBox, DisplayInside, WritingMode}; use crate::style_ext::{Direction, Display, DisplayGeneratingBox, DisplayInside, WritingMode};
use crate::{ContainingBlock, DefiniteContainingBlock}; use crate::{ContainingBlock, DefiniteContainingBlock};
use rayon::iter::{IntoParallelRefIterator, ParallelExtend, ParallelIterator}; use rayon::iter::{IntoParallelRefIterator, ParallelExtend, ParallelIterator};
@ -83,7 +84,7 @@ fn construct_for_root_element<'dom>(
style, style,
display_inside, display_inside,
contents, contents,
/* request_content_sizes */ false, ContentSizesRequest::None,
), ),
))], ))],
) )

View file

@ -8,7 +8,7 @@ use crate::flow::BlockFormattingContext;
use crate::fragments::Fragment; use crate::fragments::Fragment;
use crate::positioned::AbsolutelyPositionedFragment; use crate::positioned::AbsolutelyPositionedFragment;
use crate::replaced::ReplacedContent; use crate::replaced::ReplacedContent;
use crate::sizing::ContentSizes; use crate::sizing::{ContentSizes, ContentSizesRequest};
use crate::style_ext::DisplayInside; use crate::style_ext::DisplayInside;
use crate::ContainingBlock; use crate::ContainingBlock;
use servo_arc::Arc; use servo_arc::Arc;
@ -55,24 +55,24 @@ impl IndependentFormattingContext {
style: Arc<ComputedValues>, style: Arc<ComputedValues>,
display_inside: DisplayInside, display_inside: DisplayInside,
contents: Contents<impl NodeExt<'dom>>, contents: Contents<impl NodeExt<'dom>>,
request_content_sizes: bool, content_sizes: ContentSizesRequest,
) -> Self { ) -> Self {
use self::IndependentFormattingContextContents as Contents; use self::IndependentFormattingContextContents as Contents;
let (contents, inline_content_sizes) = match contents.try_into() { let (contents, inline_content_sizes) = match contents.try_into() {
Ok(non_replaced) => match display_inside { Ok(non_replaced) => match display_inside {
DisplayInside::Flow | DisplayInside::FlowRoot => { DisplayInside::Flow | DisplayInside::FlowRoot => {
let (bfc, content_sizes) = BlockFormattingContext::construct( let (bfc, inline_content_sizes) = BlockFormattingContext::construct(
context, context,
&style, &style,
non_replaced, non_replaced,
request_content_sizes, content_sizes,
); );
(Contents::Flow(bfc), content_sizes) (Contents::Flow(bfc), inline_content_sizes)
}, },
}, },
Err(replaced) => { Err(replaced) => {
let content_sizes = None; // Unused by layout code let inline_content_sizes = None; // Unused by layout code
(Contents::Replaced(replaced), content_sizes) (Contents::Replaced(replaced), inline_content_sizes)
}, },
}; };
Self { Self {

View file

@ -7,7 +7,7 @@ use crate::dom_traversal::{Contents, NodeExt};
use crate::formatting_contexts::IndependentFormattingContext; use crate::formatting_contexts::IndependentFormattingContext;
use crate::fragments::{AnonymousFragment, BoxFragment, CollapsedBlockMargins, Fragment}; use crate::fragments::{AnonymousFragment, BoxFragment, CollapsedBlockMargins, Fragment};
use crate::geom::flow_relative::{Rect, Sides, Vec2}; use crate::geom::flow_relative::{Rect, Sides, Vec2};
use crate::sizing::shrink_to_fit; use crate::sizing::{shrink_to_fit, ContentSizesRequest};
use crate::style_ext::{ComputedValuesExt, Direction, DisplayInside, WritingMode}; use crate::style_ext::{ComputedValuesExt, Direction, DisplayInside, WritingMode};
use crate::{ContainingBlock, DefiniteContainingBlock}; use crate::{ContainingBlock, DefiniteContainingBlock};
use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
@ -53,21 +53,21 @@ impl AbsolutelyPositionedBox {
contents: Contents<impl NodeExt<'dom>>, contents: Contents<impl NodeExt<'dom>>,
) -> Self { ) -> Self {
// "Shrink-to-fit" in https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width // "Shrink-to-fit" in https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width
let request_content_sizes = { let content_sizes = ContentSizesRequest::inline_if(
// If inline-size is non-auto, that value is used without shrink-to-fit // If inline-size is non-auto, that value is used without shrink-to-fit
style.inline_size_is_auto() && style.inline_size_is_auto() &&
// If it is, then the only case where shrink-to-fit is *not* used is // If it is, then the only case where shrink-to-fit is *not* used is
// if both offsets are non-auto, leaving inline-size as the only variable // if both offsets are non-auto, leaving inline-size as the only variable
// in the constraint equation. // in the constraint equation.
!style.inline_box_offsets_are_both_non_auto() !style.inline_box_offsets_are_both_non_auto(),
}; );
Self { Self {
contents: IndependentFormattingContext::construct( contents: IndependentFormattingContext::construct(
context, context,
style, style,
display_inside, display_inside,
contents, contents,
request_content_sizes, content_sizes,
), ),
} }
} }

View file

@ -9,6 +9,37 @@ use style::properties::ComputedValues;
use style::values::computed::{Length, LengthPercentage, Percentage}; use style::values::computed::{Length, LengthPercentage, Percentage};
use style::Zero; use style::Zero;
/// Which min/max-content values should be computed during box construction
#[derive(Clone, Copy, Debug)]
pub(crate) enum ContentSizesRequest {
Inline,
None,
}
impl ContentSizesRequest {
pub fn inline_if(condition: bool) -> Self {
if condition {
Self::Inline
} else {
Self::None
}
}
pub fn requests_inline(self) -> bool {
match self {
Self::Inline => true,
Self::None => false,
}
}
pub fn if_requests_inline<T>(self, f: impl FnOnce() -> T) -> Option<T> {
match self {
Self::Inline => Some(f()),
Self::None => None,
}
}
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub(crate) struct ContentSizes { pub(crate) struct ContentSizes {
pub min_content: Length, pub min_content: Length,