Finish plumbing intrinsic min/max-content through box construction

This commit is contained in:
Simon Sapin 2019-12-03 02:19:48 +01:00
parent da36fcddb0
commit c056e5b6b0
5 changed files with 80 additions and 39 deletions

View file

@ -192,8 +192,7 @@ impl<Node> Contents<Node> {
/// Returns true iff the `try_from` impl below would return `Err(_)` /// Returns true iff the `try_from` impl below would return `Err(_)`
pub fn is_replaced(&self) -> bool { pub fn is_replaced(&self) -> bool {
match self { match self {
Contents::OfElement(_) | Contents::OfElement(_) | Contents::OfPseudoElement(_) => false,
Contents::OfPseudoElement(_) => false,
Contents::Replaced(_) => true, Contents::Replaced(_) => true,
} }
} }

View file

@ -24,14 +24,17 @@ impl BlockFormattingContext {
context: &LayoutContext, context: &LayoutContext,
style: &Arc<ComputedValues>, style: &Arc<ComputedValues>,
contents: NonReplacedContents<impl NodeExt<'dom>>, contents: NonReplacedContents<impl NodeExt<'dom>>,
) -> Self { request_content_sizes: bool,
let (contents, contains_floats) = BlockContainer::construct(context, style, contents); ) -> (Self, Option<ContentSizes>) {
let (contents, contains_floats, content_sizes) =
BlockContainer::construct(context, style, contents, request_content_sizes);
// FIXME: add contribution to `content_sizes` of floats in this formatting context // FIXME: add contribution to `content_sizes` of floats in this formatting context
// https://dbaron.org/css/intrinsic/#intrinsic // https://dbaron.org/css/intrinsic/#intrinsic
Self { let bfc = Self {
contents, contents,
contains_floats: contains_floats == ContainsFloats::Yes, contains_floats: contains_floats == ContainsFloats::Yes,
} };
(bfc, content_sizes)
} }
} }
@ -130,9 +133,8 @@ 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, request_content_sizes: bool,
) -> (BlockContainer, ContainsFloats) { ) -> (BlockContainer, ContainsFloats, Option<ContentSizes>) {
let request_content_sizes = false; // FIXME
let mut builder = BlockContainerBuilder { let mut builder = BlockContainerBuilder {
context, context,
block_container_style, block_container_style,
@ -153,10 +155,19 @@ 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 {
Some(
builder
.ongoing_inline_formatting_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); return (container, builder.contains_floats, content_sizes);
} }
builder.end_ongoing_inline_formatting_context(); builder.end_ongoing_inline_formatting_context();
} }
@ -204,7 +215,12 @@ impl BlockContainer {
}, },
); );
let container = BlockContainer::BlockLevelBoxes(iter.collect()); let container = BlockContainer::BlockLevelBoxes(iter.collect());
(container, target.contains_floats) let content_sizes = if request_content_sizes {
Some(target.outer_content_sizes_of_children)
} else {
None
};
(container, target.contains_floats, content_sizes)
} }
} }
@ -367,7 +383,9 @@ where
}); });
// `unwrap` doesnt panic here because `is_replaced` returned `false`. // `unwrap` doesnt panic here because `is_replaced` returned `false`.
NonReplacedContents::try_from(contents).unwrap().traverse(&style, self.context, self); NonReplacedContents::try_from(contents)
.unwrap()
.traverse(&style, self.context, self);
let mut inline_box = self let mut inline_box = self
.ongoing_inline_boxes_stack .ongoing_inline_boxes_stack
@ -575,13 +593,12 @@ where
) -> (Arc<BlockLevelBox>, ContainsFloats) { ) -> (Arc<BlockLevelBox>, ContainsFloats) {
match self { match self {
IntermediateBlockLevelBox::SameFormattingContextBlock { style, contents } => { IntermediateBlockLevelBox::SameFormattingContextBlock { style, contents } => {
let request_content_sizes = let request_content_sizes = max_assign_in_flow_outer_content_sizes_to.is_some() &&
max_assign_in_flow_outer_content_sizes_to.is_some() &&
style.inline_size_is_auto(); style.inline_size_is_auto();
let (contents, contains_floats) = contents.finish(context, &style, request_content_sizes); let (contents, contains_floats, content_sizes) =
contents.finish(context, &style, request_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 {
let get_content_size = || todo!(); to.max_assign(&outer_inline_content_sizes(&style, &content_sizes))
to.max_assign(&outer_inline_content_sizes(&style, get_content_size()))
} }
let block_level_box = let block_level_box =
Arc::new(BlockLevelBox::SameFormattingContextBlock { contents, style }); Arc::new(BlockLevelBox::SameFormattingContextBlock { contents, style });
@ -592,8 +609,7 @@ where
display_inside, display_inside,
contents, contents,
} => { } => {
let request_content_sizes = let request_content_sizes = max_assign_in_flow_outer_content_sizes_to.is_some() &&
max_assign_in_flow_outer_content_sizes_to.is_some() &&
style.inline_size_is_auto(); style.inline_size_is_auto();
let contents = IndependentFormattingContext::construct( let contents = IndependentFormattingContext::construct(
context, context,
@ -603,8 +619,10 @@ where
request_content_sizes, request_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 {
let get_content_size = || todo!(); to.max_assign(&outer_inline_content_sizes(
to.max_assign(&outer_inline_content_sizes(&contents.style, get_content_size())) &contents.style,
&contents.inline_content_sizes,
))
} }
( (
Arc::new(BlockLevelBox::Independent(contents)), Arc::new(BlockLevelBox::Independent(contents)),
@ -643,19 +661,25 @@ where
self, self,
context: &LayoutContext, context: &LayoutContext,
style: &Arc<ComputedValues>, style: &Arc<ComputedValues>,
_request_content_sizes: bool, request_content_sizes: bool,
) -> (BlockContainer, ContainsFloats) { ) -> (BlockContainer, ContainsFloats, Option<ContentSizes>) {
match self { match self {
IntermediateBlockContainer::Deferred { contents } => { IntermediateBlockContainer::Deferred { contents } => {
BlockContainer::construct(context, style, contents) BlockContainer::construct(context, style, contents, request_content_sizes)
}, },
IntermediateBlockContainer::InlineFormattingContext(ifc) => { IntermediateBlockContainer::InlineFormattingContext(ifc) => {
let content_sizes = if request_content_sizes {
Some(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,
) )
}, },
} }

View file

@ -84,8 +84,7 @@ impl InlineFormattingContext {
// This works on an already-constructed `InlineFormattingContext`, // This works on an already-constructed `InlineFormattingContext`,
// Which would have to change if/when // Which would have to change if/when
// `BlockContainer::construct` parallelize their construction. // `BlockContainer::construct` parallelize their construction.
#[allow(unused)] pub(super) fn inline_content_sizes(&self, layout_context: &LayoutContext) -> ContentSizes {
pub(super) fn content_sizes(&self, layout_context: &LayoutContext) -> ContentSizes {
struct Computation { struct Computation {
paragraph: ContentSizes, paragraph: ContentSizes,
current_line: ContentSizes, current_line: ContentSizes,
@ -147,12 +146,10 @@ impl InlineFormattingContext {
} }
}, },
InlineLevelBox::Atomic(atomic) => { InlineLevelBox::Atomic(atomic) => {
let inner = || {
// &atomic.inline_content_sizes
todo!()
};
let (outer, pc) = outer_inline_content_sizes_and_percentages( let (outer, pc) = outer_inline_content_sizes_and_percentages(
&atomic.style, inner()); &atomic.style,
&atomic.inline_content_sizes,
);
self.current_line.min_content += outer.min_content; self.current_line.min_content += outer.min_content;
self.current_line.max_content += outer.max_content; self.current_line.max_content += outer.max_content;
self.current_line_percentages += pc; self.current_line_percentages += pc;

View file

@ -8,6 +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::style_ext::DisplayInside; use crate::style_ext::DisplayInside;
use crate::ContainingBlock; use crate::ContainingBlock;
use servo_arc::Arc; use servo_arc::Arc;
@ -19,6 +20,10 @@ use style::values::computed::Length;
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct IndependentFormattingContext { pub(crate) struct IndependentFormattingContext {
pub style: Arc<ComputedValues>, pub style: Arc<ComputedValues>,
/// If it was requested during construction
pub inline_content_sizes: Option<ContentSizes>,
contents: IndependentFormattingContextContents, contents: IndependentFormattingContextContents,
} }
@ -50,18 +55,31 @@ 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, // Ignored for replaced content request_content_sizes: bool,
) -> Self { ) -> Self {
use self::IndependentFormattingContextContents as Contents; use self::IndependentFormattingContextContents as Contents;
let contents = 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 => Contents::Flow( DisplayInside::Flow | DisplayInside::FlowRoot => {
BlockFormattingContext::construct(context, &style, non_replaced), let (bfc, content_sizes) = BlockFormattingContext::construct(
), context,
&style,
non_replaced,
request_content_sizes,
);
(Contents::Flow(bfc), content_sizes)
},
},
Err(replaced) => {
let content_sizes = None; // Unused by layout code
(Contents::Replaced(replaced), content_sizes)
}, },
Err(replaced) => Contents::Replaced(replaced),
}; };
Self { style, contents } Self {
style,
contents,
inline_content_sizes,
}
} }
pub fn as_replaced(&self) -> Result<&ReplacedContent, NonReplacedIFC> { pub fn as_replaced(&self) -> Result<&ReplacedContent, NonReplacedIFC> {

View file

@ -65,7 +65,10 @@ pub(crate) fn outer_inline_content_sizes_and_percentages(
let specified = specified.map(|lp| lp.as_length()); let specified = specified.map(|lp| lp.as_length());
// The (inner) min/max-content are only used for 'auto' // The (inner) min/max-content are only used for 'auto'
let mut outer = match specified.non_auto().flatten() { let mut outer = match specified.non_auto().flatten() {
None => inner_content_sizes.as_ref().expect("Accessing content size that was not requested").clone(), None => inner_content_sizes
.as_ref()
.expect("Accessing content size that was not requested")
.clone(),
Some(length) => ContentSizes { Some(length) => ContentSizes {
min_content: length, min_content: length,
max_content: length, max_content: length,