Add content sizes computation for block containers

This commit is contained in:
Simon Sapin 2019-12-03 02:03:51 +01:00
parent 78bfa45eab
commit 303b36f17b
3 changed files with 73 additions and 29 deletions

View file

@ -10,6 +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::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;
@ -25,6 +26,8 @@ impl BlockFormattingContext {
contents: NonReplacedContents<impl NodeExt<'dom>>, contents: NonReplacedContents<impl NodeExt<'dom>>,
) -> Self { ) -> Self {
let (contents, contains_floats) = BlockContainer::construct(context, style, contents); let (contents, contains_floats) = BlockContainer::construct(context, style, contents);
// FIXME: add contribution to `content_sizes` of floats in this formatting context
// https://dbaron.org/css/intrinsic/#intrinsic
Self { Self {
contents, contents,
contains_floats: contains_floats == ContainsFloats::Yes, contains_floats: contains_floats == ContainsFloats::Yes,
@ -127,16 +130,17 @@ 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>>,
//intrinsic_sizes_requested: bool, //request_content_sizes: bool,
) -> (BlockContainer, ContainsFloats) { ) -> (BlockContainer, ContainsFloats) {
let request_content_sizes = false; // FIXME
let mut builder = BlockContainerBuilder { let mut builder = BlockContainerBuilder {
context, context,
block_container_style, block_container_style,
block_level_boxes: Default::default(), block_level_boxes: Vec::new(),
ongoing_inline_formatting_context: Default::default(), ongoing_inline_formatting_context: InlineFormattingContext::default(),
ongoing_inline_boxes_stack: Default::default(), ongoing_inline_boxes_stack: Vec::new(),
anonymous_style: Default::default(), anonymous_style: None,
contains_floats: Default::default(), contains_floats: ContainsFloats::No,
}; };
contents.traverse(block_container_style, context, &mut builder); contents.traverse(block_container_style, context, &mut builder);
@ -158,25 +162,46 @@ impl BlockContainer {
} }
type Intermediate<Node> = IntermediateBlockLevelBox<Node>; type Intermediate<Node> = IntermediateBlockLevelBox<Node>;
#[derive(Default)]
struct Target { struct Target {
contains_floats: ContainsFloats, contains_floats: ContainsFloats,
outer_content_sizes_of_children: ContentSizes,
}
impl Default for Target {
fn default() -> Self {
Self {
contains_floats: ContainsFloats::No,
outer_content_sizes_of_children: ContentSizes::zero(),
}
}
} }
let mut target = Target { let mut target = Target {
contains_floats: builder.contains_floats, contains_floats: builder.contains_floats,
outer_content_sizes_of_children: ContentSizes::zero(),
}; };
let request_content_sizes = false; // FIXME let request_childrens_outer_content_sizes = request_content_sizes;
let iter = builder.block_level_boxes.into_par_iter(); let iter = builder.block_level_boxes.into_par_iter();
let iter = iter.mapfold_reduce_into( let iter = iter.mapfold_reduce_into(
&mut target, &mut target,
|target, (intermediate, box_slot): (Intermediate<_>, BoxSlot<'_>)| { |target, (intermediate, box_slot): (Intermediate<_>, BoxSlot<'_>)| {
let (block_level_box, box_contains_floats) = let (block_level_box, box_contains_floats) = intermediate.finish(
intermediate.finish(context, request_content_sizes); context,
if request_childrens_outer_content_sizes {
Some(&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()));
block_level_box block_level_box
}, },
|left, right| left.contains_floats |= right.contains_floats, |left, right| {
left.contains_floats |= right.contains_floats;
if request_content_sizes {
left.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());
(container, target.contains_floats) (container, target.contains_floats)
@ -548,11 +573,18 @@ where
fn finish( fn finish(
self, self,
context: &LayoutContext, context: &LayoutContext,
parent_requests_outer_content_sizes: bool, max_assign_in_flow_outer_content_sizes_to: Option<&mut ContentSizes>,
) -> (Arc<BlockLevelBox>, ContainsFloats) { ) -> (Arc<BlockLevelBox>, ContainsFloats) {
match self { match self {
IntermediateBlockLevelBox::SameFormattingContextBlock { style, contents } => { IntermediateBlockLevelBox::SameFormattingContextBlock { style, contents } => {
let (contents, contains_floats) = contents.finish(context, &style); let request_content_sizes =
max_assign_in_flow_outer_content_sizes_to.is_some() &&
style.inline_size_is_auto();
let (contents, contains_floats) = contents.finish(context, &style, request_content_sizes);
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, get_content_size()))
}
let block_level_box = let block_level_box =
Arc::new(BlockLevelBox::SameFormattingContextBlock { contents, style }); Arc::new(BlockLevelBox::SameFormattingContextBlock { contents, style });
(block_level_box, contains_floats) (block_level_box, contains_floats)
@ -563,7 +595,8 @@ where
contents, contents,
} => { } => {
let request_content_sizes = let request_content_sizes =
parent_requests_outer_content_sizes && 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,
@ -571,6 +604,10 @@ where
contents, contents,
request_content_sizes, request_content_sizes,
); );
if let Some(to) = max_assign_in_flow_outer_content_sizes_to {
let get_content_size = || todo!();
to.max_assign(&outer_inline_content_sizes(&contents.style, get_content_size()))
}
( (
Arc::new(BlockLevelBox::Independent(contents)), Arc::new(BlockLevelBox::Independent(contents)),
ContainsFloats::No, ContainsFloats::No,
@ -608,6 +645,7 @@ where
self, self,
context: &LayoutContext, context: &LayoutContext,
style: &Arc<ComputedValues>, style: &Arc<ComputedValues>,
_request_content_sizes: bool,
) -> (BlockContainer, ContainsFloats) { ) -> (BlockContainer, ContainsFloats) {
match self { match self {
IntermediateBlockContainer::Deferred { contents } => { IntermediateBlockContainer::Deferred { contents } => {
@ -639,9 +677,3 @@ impl std::ops::BitOrAssign for ContainsFloats {
} }
} }
} }
impl Default for ContainsFloats {
fn default() -> Self {
ContainsFloats::No
}
}

View file

@ -10,7 +10,7 @@ use crate::fragments::CollapsedBlockMargins;
use crate::fragments::{AnonymousFragment, BoxFragment, Fragment, TextFragment}; use crate::fragments::{AnonymousFragment, BoxFragment, Fragment, TextFragment};
use crate::geom::flow_relative::{Rect, Sides, Vec2}; use crate::geom::flow_relative::{Rect, Sides, Vec2};
use crate::positioned::{AbsolutelyPositionedBox, AbsolutelyPositionedFragment}; use crate::positioned::{AbsolutelyPositionedBox, AbsolutelyPositionedFragment};
use crate::sizing::{outer_inline_content_sizes, ContentSizes}; use crate::sizing::{outer_inline_content_sizes_and_percentages, ContentSizes};
use crate::style_ext::{ComputedValuesExt, Display, DisplayGeneratingBox, DisplayOutside}; use crate::style_ext::{ComputedValuesExt, Display, DisplayGeneratingBox, DisplayOutside};
use crate::{relative_adjustement, ContainingBlock}; use crate::{relative_adjustement, ContainingBlock};
use app_units::Au; use app_units::Au;
@ -148,14 +148,11 @@ impl InlineFormattingContext {
}, },
InlineLevelBox::Atomic(atomic) => { InlineLevelBox::Atomic(atomic) => {
let inner = || { let inner = || {
// atomic // &atomic.inline_content_sizes
// .inline_content_sizes
// .as_ref()
// .expect("Accessing content size that was not requested")
// .clone()
todo!() todo!()
}; };
let (outer, pc) = outer_inline_content_sizes(&atomic.style, &inner); let (outer, pc) = outer_inline_content_sizes_and_percentages(
&atomic.style, inner());
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

@ -24,6 +24,11 @@ impl ContentSizes {
} }
} }
pub fn max_assign(&mut self, other: &Self) {
self.min_content.max_assign(other.min_content);
self.max_content.max_assign(other.max_content);
}
/// Relevant to outer intrinsic inline sizes, for percentages from padding and margin. /// Relevant to outer intrinsic inline sizes, for percentages from padding and margin.
pub fn adjust_for_pbm_percentages(&mut self, percentages: Percentage) { pub fn adjust_for_pbm_percentages(&mut self, percentages: Percentage) {
// " Note that this may yield an infinite result, but undefined results // " Note that this may yield an infinite result, but undefined results
@ -41,7 +46,17 @@ impl ContentSizes {
/// https://dbaron.org/css/intrinsic/#outer-intrinsic /// https://dbaron.org/css/intrinsic/#outer-intrinsic
pub(crate) fn outer_inline_content_sizes( pub(crate) fn outer_inline_content_sizes(
style: &ComputedValues, style: &ComputedValues,
get_inner_intrinsic_sizes: &dyn Fn() -> ContentSizes, inner_content_sizes: &Option<ContentSizes>,
) -> ContentSizes {
let (mut outer, percentages) =
outer_inline_content_sizes_and_percentages(style, inner_content_sizes);
outer.adjust_for_pbm_percentages(percentages);
outer
}
pub(crate) fn outer_inline_content_sizes_and_percentages(
style: &ComputedValues,
inner_content_sizes: &Option<ContentSizes>,
) -> (ContentSizes, Percentage) { ) -> (ContentSizes, Percentage) {
// FIXME: account for 'min-width', 'max-width', 'box-sizing' // FIXME: account for 'min-width', 'max-width', 'box-sizing'
@ -50,7 +65,7 @@ pub(crate) fn outer_inline_content_sizes(
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 => get_inner_intrinsic_sizes(), 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,