mirror of
https://github.com/servo/servo.git
synced 2025-06-08 00:23:30 +00:00
Compute content sizes lazily in layout 2020
This commit is contained in:
parent
ba5568a0a6
commit
235df94f2e
11 changed files with 176 additions and 247 deletions
|
@ -12,7 +12,6 @@ use crate::element_data::LayoutBox;
|
||||||
use crate::formatting_contexts::IndependentFormattingContext;
|
use crate::formatting_contexts::IndependentFormattingContext;
|
||||||
use crate::fragments::Tag;
|
use crate::fragments::Tag;
|
||||||
use crate::positioned::AbsolutelyPositionedBox;
|
use crate::positioned::AbsolutelyPositionedBox;
|
||||||
use crate::sizing::{BoxContentSizes, ContentSizes, ContentSizesRequest};
|
|
||||||
use crate::style_ext::DisplayGeneratingBox;
|
use crate::style_ext::DisplayGeneratingBox;
|
||||||
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
@ -23,9 +22,8 @@ impl FlexContainer {
|
||||||
context: &LayoutContext,
|
context: &LayoutContext,
|
||||||
info: &NodeAndStyleInfo<impl NodeExt<'dom>>,
|
info: &NodeAndStyleInfo<impl NodeExt<'dom>>,
|
||||||
contents: NonReplacedContents,
|
contents: NonReplacedContents,
|
||||||
content_sizes: ContentSizesRequest,
|
|
||||||
propagated_text_decoration_line: TextDecorationLine,
|
propagated_text_decoration_line: TextDecorationLine,
|
||||||
) -> (Self, BoxContentSizes) {
|
) -> Self {
|
||||||
let text_decoration_line =
|
let text_decoration_line =
|
||||||
propagated_text_decoration_line | info.style.clone_text_decoration_line();
|
propagated_text_decoration_line | info.style.clone_text_decoration_line();
|
||||||
let mut builder = FlexContainerBuilder {
|
let mut builder = FlexContainerBuilder {
|
||||||
|
@ -37,11 +35,7 @@ impl FlexContainer {
|
||||||
has_text_runs: false,
|
has_text_runs: false,
|
||||||
};
|
};
|
||||||
contents.traverse(context, info, &mut builder);
|
contents.traverse(context, info, &mut builder);
|
||||||
let content_sizes = content_sizes.compute(|| {
|
builder.finish()
|
||||||
// FIXME
|
|
||||||
ContentSizes::zero()
|
|
||||||
});
|
|
||||||
(builder.finish(), content_sizes)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,7 +146,6 @@ where
|
||||||
.map(|job| match job {
|
.map(|job| match job {
|
||||||
FlexLevelJob::TextRuns(runs) => ArcRefCell::new(FlexLevelBox::FlexItem(
|
FlexLevelJob::TextRuns(runs) => ArcRefCell::new(FlexLevelBox::FlexItem(
|
||||||
IndependentFormattingContext::construct_for_text_runs(
|
IndependentFormattingContext::construct_for_text_runs(
|
||||||
self.context,
|
|
||||||
&self
|
&self
|
||||||
.info
|
.info
|
||||||
.new_replacing_style(anonymous_style.clone().unwrap()),
|
.new_replacing_style(anonymous_style.clone().unwrap()),
|
||||||
|
@ -161,7 +154,6 @@ where
|
||||||
text: run.text.into(),
|
text: run.text.into(),
|
||||||
parent_style: run.info.style,
|
parent_style: run.info.style,
|
||||||
}),
|
}),
|
||||||
ContentSizesRequest::None, // FIXME: request sizes when we start using them
|
|
||||||
self.text_decoration_line,
|
self.text_decoration_line,
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
|
@ -191,7 +183,6 @@ where
|
||||||
&info,
|
&info,
|
||||||
display_inside,
|
display_inside,
|
||||||
contents,
|
contents,
|
||||||
ContentSizesRequest::None, // FIXME: request sizes when we start using them
|
|
||||||
self.text_decoration_line,
|
self.text_decoration_line,
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
use crate::cell::ArcRefCell;
|
use crate::cell::ArcRefCell;
|
||||||
use crate::formatting_contexts::IndependentFormattingContext;
|
use crate::formatting_contexts::IndependentFormattingContext;
|
||||||
use crate::positioned::AbsolutelyPositionedBox;
|
use crate::positioned::AbsolutelyPositionedBox;
|
||||||
|
use crate::sizing::ContentSizes;
|
||||||
|
|
||||||
mod construct;
|
mod construct;
|
||||||
mod layout;
|
mod layout;
|
||||||
|
@ -19,3 +20,9 @@ pub(crate) enum FlexLevelBox {
|
||||||
FlexItem(IndependentFormattingContext),
|
FlexItem(IndependentFormattingContext),
|
||||||
OutOfFlowAbsolutelyPositionedBox(ArcRefCell<AbsolutelyPositionedBox>),
|
OutOfFlowAbsolutelyPositionedBox(ArcRefCell<AbsolutelyPositionedBox>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FlexContainer {
|
||||||
|
pub fn inline_content_sizes(&self) -> ContentSizes {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -14,14 +14,12 @@ use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox};
|
||||||
use crate::formatting_contexts::IndependentFormattingContext;
|
use crate::formatting_contexts::IndependentFormattingContext;
|
||||||
use crate::fragments::Tag;
|
use crate::fragments::Tag;
|
||||||
use crate::positioned::AbsolutelyPositionedBox;
|
use crate::positioned::AbsolutelyPositionedBox;
|
||||||
use crate::sizing::{self, BoxContentSizes, ContentSizes, ContentSizesRequest};
|
use crate::style_ext::{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;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::convert::{TryFrom, TryInto};
|
use std::convert::{TryFrom, TryInto};
|
||||||
use style::logical_geometry::WritingMode;
|
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
use style::selector_parser::PseudoElement;
|
use style::selector_parser::PseudoElement;
|
||||||
use style::values::specified::text::TextDecorationLine;
|
use style::values::specified::text::TextDecorationLine;
|
||||||
|
@ -31,34 +29,24 @@ impl BlockFormattingContext {
|
||||||
context: &LayoutContext,
|
context: &LayoutContext,
|
||||||
info: &NodeAndStyleInfo<Node>,
|
info: &NodeAndStyleInfo<Node>,
|
||||||
contents: NonReplacedContents,
|
contents: NonReplacedContents,
|
||||||
content_sizes: ContentSizesRequest,
|
|
||||||
propagated_text_decoration_line: TextDecorationLine,
|
propagated_text_decoration_line: TextDecorationLine,
|
||||||
) -> (Self, BoxContentSizes)
|
) -> Self
|
||||||
where
|
where
|
||||||
Node: NodeExt<'dom>,
|
Node: NodeExt<'dom>,
|
||||||
{
|
{
|
||||||
let (contents, contains_floats, inline_content_sizes) = BlockContainer::construct(
|
let (contents, contains_floats) =
|
||||||
context,
|
BlockContainer::construct(context, info, contents, propagated_text_decoration_line);
|
||||||
info,
|
|
||||||
contents,
|
|
||||||
content_sizes,
|
|
||||||
propagated_text_decoration_line,
|
|
||||||
);
|
|
||||||
// FIXME: add contribution to `inline_content_sizes` of floats in this formatting context
|
|
||||||
// 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, inline_content_sizes)
|
bfc
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn construct_for_text_runs<'dom>(
|
pub fn construct_for_text_runs<'dom>(
|
||||||
context: &LayoutContext,
|
|
||||||
runs: impl Iterator<Item = TextRun>,
|
runs: impl Iterator<Item = TextRun>,
|
||||||
content_sizes: ContentSizesRequest,
|
|
||||||
text_decoration_line: TextDecorationLine,
|
text_decoration_line: TextDecorationLine,
|
||||||
) -> (Self, BoxContentSizes) {
|
) -> Self {
|
||||||
// FIXME: do white space collapsing
|
// FIXME: do white space collapsing
|
||||||
let inline_level_boxes = runs
|
let inline_level_boxes = runs
|
||||||
.map(|run| ArcRefCell::new(InlineLevelBox::TextRun(run)))
|
.map(|run| ArcRefCell::new(InlineLevelBox::TextRun(run)))
|
||||||
|
@ -68,18 +56,12 @@ impl BlockFormattingContext {
|
||||||
inline_level_boxes,
|
inline_level_boxes,
|
||||||
text_decoration_line,
|
text_decoration_line,
|
||||||
};
|
};
|
||||||
// FIXME: this is the wrong writing mode
|
|
||||||
// but we plan to remove eager content size computation.
|
|
||||||
let not_actually_containing_block_writing_mode = WritingMode::empty();
|
|
||||||
let content_sizes = content_sizes.compute(|| {
|
|
||||||
ifc.inline_content_sizes(context, not_actually_containing_block_writing_mode)
|
|
||||||
});
|
|
||||||
let contents = BlockContainer::InlineFormattingContext(ifc);
|
let contents = BlockContainer::InlineFormattingContext(ifc);
|
||||||
let bfc = Self {
|
let bfc = Self {
|
||||||
contents,
|
contents,
|
||||||
contains_floats: false,
|
contains_floats: false,
|
||||||
};
|
};
|
||||||
(bfc, content_sizes)
|
bfc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,9 +163,8 @@ impl BlockContainer {
|
||||||
context: &LayoutContext,
|
context: &LayoutContext,
|
||||||
info: &NodeAndStyleInfo<Node>,
|
info: &NodeAndStyleInfo<Node>,
|
||||||
contents: NonReplacedContents,
|
contents: NonReplacedContents,
|
||||||
content_sizes: ContentSizesRequest,
|
|
||||||
propagated_text_decoration_line: TextDecorationLine,
|
propagated_text_decoration_line: TextDecorationLine,
|
||||||
) -> (BlockContainer, ContainsFloats, BoxContentSizes)
|
) -> (BlockContainer, ContainsFloats)
|
||||||
where
|
where
|
||||||
Node: NodeExt<'dom>,
|
Node: NodeExt<'dom>,
|
||||||
{
|
{
|
||||||
|
@ -209,35 +190,22 @@ impl BlockContainer {
|
||||||
.is_empty()
|
.is_empty()
|
||||||
{
|
{
|
||||||
if builder.block_level_boxes.is_empty() {
|
if builder.block_level_boxes.is_empty() {
|
||||||
// FIXME: this is the wrong writing mode
|
|
||||||
// but we plan to remove eager content size computation.
|
|
||||||
let not_actually_containing_block_writing_mode = info.style.writing_mode;
|
|
||||||
let content_sizes = content_sizes.compute(|| {
|
|
||||||
builder
|
|
||||||
.ongoing_inline_formatting_context
|
|
||||||
.inline_content_sizes(context, not_actually_containing_block_writing_mode)
|
|
||||||
});
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
builder.end_ongoing_inline_formatting_context();
|
builder.end_ongoing_inline_formatting_context();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Accumulator {
|
struct Accumulator {
|
||||||
contains_floats: ContainsFloats,
|
contains_floats: ContainsFloats,
|
||||||
outer_content_sizes_of_children: ContentSizes,
|
|
||||||
}
|
}
|
||||||
let mut acc = Accumulator {
|
let mut acc = Accumulator {
|
||||||
contains_floats: builder.contains_floats,
|
contains_floats: builder.contains_floats,
|
||||||
outer_content_sizes_of_children: ContentSizes::zero(),
|
|
||||||
};
|
};
|
||||||
let mapfold = |acc: &mut Accumulator, creator: BlockLevelJob<'dom, _>| {
|
let mapfold = |acc: &mut Accumulator, creator: BlockLevelJob<'dom, _>| {
|
||||||
let (block_level_box, box_contains_floats) = creator.finish(
|
let (block_level_box, box_contains_floats) = creator.finish(context);
|
||||||
context,
|
|
||||||
content_sizes.if_requests_inline(|| &mut acc.outer_content_sizes_of_children),
|
|
||||||
);
|
|
||||||
acc.contains_floats |= box_contains_floats;
|
acc.contains_floats |= box_contains_floats;
|
||||||
block_level_box
|
block_level_box
|
||||||
};
|
};
|
||||||
|
@ -250,14 +218,9 @@ impl BlockContainer {
|
||||||
mapfold,
|
mapfold,
|
||||||
|| Accumulator {
|
|| Accumulator {
|
||||||
contains_floats: ContainsFloats::No,
|
contains_floats: ContainsFloats::No,
|
||||||
outer_content_sizes_of_children: ContentSizes::zero(),
|
|
||||||
},
|
},
|
||||||
|left, right| {
|
|left, right| {
|
||||||
left.contains_floats |= right.contains_floats;
|
left.contains_floats |= right.contains_floats;
|
||||||
if content_sizes.requests_inline() {
|
|
||||||
left.outer_content_sizes_of_children
|
|
||||||
.max_assign(&right.outer_content_sizes_of_children)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.collect()
|
.collect()
|
||||||
|
@ -270,12 +233,8 @@ impl BlockContainer {
|
||||||
};
|
};
|
||||||
let container = BlockContainer::BlockLevelBoxes(block_level_boxes);
|
let container = BlockContainer::BlockLevelBoxes(block_level_boxes);
|
||||||
|
|
||||||
let Accumulator {
|
let Accumulator { contains_floats } = acc;
|
||||||
contains_floats,
|
(container, contains_floats)
|
||||||
outer_content_sizes_of_children,
|
|
||||||
} = acc;
|
|
||||||
let content_sizes = content_sizes.compute(|| outer_content_sizes_of_children);
|
|
||||||
(container, contains_floats, content_sizes)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,7 +398,6 @@ where
|
||||||
display_inside: DisplayInside,
|
display_inside: DisplayInside,
|
||||||
contents: Contents,
|
contents: Contents,
|
||||||
) -> ArcRefCell<InlineLevelBox> {
|
) -> ArcRefCell<InlineLevelBox> {
|
||||||
let style = &info.style;
|
|
||||||
let box_ = if display_inside == DisplayInside::Flow && !contents.is_replaced() {
|
let box_ = if display_inside == DisplayInside::Flow && !contents.is_replaced() {
|
||||||
// We found un inline box.
|
// We found un inline box.
|
||||||
// Whatever happened before, all we need to do before recurring
|
// Whatever happened before, all we need to do before recurring
|
||||||
|
@ -464,14 +422,12 @@ where
|
||||||
inline_box.last_fragment = true;
|
inline_box.last_fragment = true;
|
||||||
ArcRefCell::new(InlineLevelBox::InlineBox(inline_box))
|
ArcRefCell::new(InlineLevelBox::InlineBox(inline_box))
|
||||||
} else {
|
} else {
|
||||||
let content_sizes = ContentSizesRequest::inline_if(!style.inline_size_is_length());
|
|
||||||
ArcRefCell::new(InlineLevelBox::Atomic(
|
ArcRefCell::new(InlineLevelBox::Atomic(
|
||||||
IndependentFormattingContext::construct(
|
IndependentFormattingContext::construct(
|
||||||
self.context,
|
self.context,
|
||||||
info,
|
info,
|
||||||
display_inside,
|
display_inside,
|
||||||
contents,
|
contents,
|
||||||
content_sizes,
|
|
||||||
// Text decorations are not propagated to atomic inline-level descendants.
|
// Text decorations are not propagated to atomic inline-level descendants.
|
||||||
TextDecorationLine::NONE,
|
TextDecorationLine::NONE,
|
||||||
),
|
),
|
||||||
|
@ -681,32 +637,11 @@ impl<'dom, Node> BlockLevelJob<'dom, Node>
|
||||||
where
|
where
|
||||||
Node: NodeExt<'dom>,
|
Node: NodeExt<'dom>,
|
||||||
{
|
{
|
||||||
fn finish(
|
fn finish(self, context: &LayoutContext) -> (ArcRefCell<BlockLevelBox>, ContainsFloats) {
|
||||||
self,
|
|
||||||
context: &LayoutContext,
|
|
||||||
max_assign_in_flow_outer_content_sizes_to: Option<&mut ContentSizes>,
|
|
||||||
) -> (ArcRefCell<BlockLevelBox>, ContainsFloats) {
|
|
||||||
let info = &self.info;
|
let info = &self.info;
|
||||||
// FIXME: this is the wrong writing mode
|
|
||||||
// but we plan to remove eager content size computation.
|
|
||||||
let not_actually_containing_block_writing_mode = info.style.writing_mode;
|
|
||||||
let (block_level_box, contains_floats) = match self.kind {
|
let (block_level_box, contains_floats) = match self.kind {
|
||||||
BlockLevelCreator::SameFormattingContextBlock(contents) => {
|
BlockLevelCreator::SameFormattingContextBlock(contents) => {
|
||||||
let (contents, contains_floats, box_content_sizes) = contents.finish(
|
let (contents, contains_floats) = contents.finish(context, info);
|
||||||
context,
|
|
||||||
info,
|
|
||||||
ContentSizesRequest::inline_if(
|
|
||||||
max_assign_in_flow_outer_content_sizes_to.is_some() &&
|
|
||||||
!info.style.inline_size_is_length(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
if let Some(to) = max_assign_in_flow_outer_content_sizes_to {
|
|
||||||
to.max_assign(&sizing::outer_inline(
|
|
||||||
&info.style,
|
|
||||||
not_actually_containing_block_writing_mode,
|
|
||||||
|| box_content_sizes.expect_inline().clone(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
let block_level_box = ArcRefCell::new(BlockLevelBox::SameFormattingContextBlock {
|
let block_level_box = ArcRefCell::new(BlockLevelBox::SameFormattingContextBlock {
|
||||||
tag: Tag::from_node_and_style_info(info),
|
tag: Tag::from_node_and_style_info(info),
|
||||||
contents,
|
contents,
|
||||||
|
@ -719,25 +654,13 @@ where
|
||||||
contents,
|
contents,
|
||||||
propagated_text_decoration_line,
|
propagated_text_decoration_line,
|
||||||
} => {
|
} => {
|
||||||
let content_sizes = ContentSizesRequest::inline_if(
|
|
||||||
max_assign_in_flow_outer_content_sizes_to.is_some() &&
|
|
||||||
!info.style.inline_size_is_length(),
|
|
||||||
);
|
|
||||||
let context = IndependentFormattingContext::construct(
|
let context = IndependentFormattingContext::construct(
|
||||||
context,
|
context,
|
||||||
info,
|
info,
|
||||||
display_inside,
|
display_inside,
|
||||||
contents,
|
contents,
|
||||||
content_sizes,
|
|
||||||
propagated_text_decoration_line,
|
propagated_text_decoration_line,
|
||||||
);
|
);
|
||||||
if let Some(to) = max_assign_in_flow_outer_content_sizes_to {
|
|
||||||
to.max_assign(&sizing::outer_inline(
|
|
||||||
&context.style(),
|
|
||||||
not_actually_containing_block_writing_mode,
|
|
||||||
|| context.content_sizes(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
(
|
(
|
||||||
ArcRefCell::new(BlockLevelBox::Independent(context)),
|
ArcRefCell::new(BlockLevelBox::Independent(context)),
|
||||||
ContainsFloats::No,
|
ContainsFloats::No,
|
||||||
|
@ -775,35 +698,21 @@ impl IntermediateBlockContainer {
|
||||||
self,
|
self,
|
||||||
context: &LayoutContext,
|
context: &LayoutContext,
|
||||||
info: &NodeAndStyleInfo<Node>,
|
info: &NodeAndStyleInfo<Node>,
|
||||||
content_sizes: ContentSizesRequest,
|
) -> (BlockContainer, ContainsFloats)
|
||||||
) -> (BlockContainer, ContainsFloats, BoxContentSizes)
|
|
||||||
where
|
where
|
||||||
Node: NodeExt<'dom>,
|
Node: NodeExt<'dom>,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
IntermediateBlockContainer::Deferred(contents, propagated_text_decoration_line) => {
|
IntermediateBlockContainer::Deferred(contents, propagated_text_decoration_line) => {
|
||||||
BlockContainer::construct(
|
BlockContainer::construct(context, info, contents, propagated_text_decoration_line)
|
||||||
context,
|
|
||||||
info,
|
|
||||||
contents,
|
|
||||||
content_sizes,
|
|
||||||
propagated_text_decoration_line,
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
IntermediateBlockContainer::InlineFormattingContext(ifc) => {
|
IntermediateBlockContainer::InlineFormattingContext(ifc) => {
|
||||||
// FIXME: this is the wrong writing mode
|
|
||||||
// but we plan to remove eager content size computation.
|
|
||||||
let not_actually_containing_block_writing_mode = info.style.writing_mode;
|
|
||||||
let content_sizes = content_sizes.compute(|| {
|
|
||||||
ifc.inline_content_sizes(context, not_actually_containing_block_writing_mode)
|
|
||||||
});
|
|
||||||
// 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,
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,7 @@
|
||||||
use crate::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::dom_traversal::{Contents, NodeAndStyleInfo, NodeExt};
|
use crate::dom_traversal::{Contents, NodeAndStyleInfo, NodeExt};
|
||||||
use crate::formatting_contexts::IndependentFormattingContext;
|
use crate::formatting_contexts::IndependentFormattingContext;
|
||||||
use crate::sizing::ContentSizesRequest;
|
use crate::style_ext::DisplayInside;
|
||||||
use crate::style_ext::{ComputedValuesExt, DisplayInside};
|
|
||||||
use style::values::specified::text::TextDecorationLine;
|
use style::values::specified::text::TextDecorationLine;
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
|
@ -32,14 +31,12 @@ impl FloatBox {
|
||||||
display_inside: DisplayInside,
|
display_inside: DisplayInside,
|
||||||
contents: Contents,
|
contents: Contents,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let content_sizes = ContentSizesRequest::inline_if(!info.style.inline_size_is_length());
|
|
||||||
Self {
|
Self {
|
||||||
contents: IndependentFormattingContext::construct(
|
contents: IndependentFormattingContext::construct(
|
||||||
context,
|
context,
|
||||||
info,
|
info,
|
||||||
display_inside,
|
display_inside,
|
||||||
contents,
|
contents,
|
||||||
content_sizes,
|
|
||||||
// Text decorations are not propagated to any out-of-flow descendants
|
// Text decorations are not propagated to any out-of-flow descendants
|
||||||
TextDecorationLine::NONE,
|
TextDecorationLine::NONE,
|
||||||
),
|
),
|
||||||
|
|
|
@ -16,7 +16,7 @@ use crate::positioned::{
|
||||||
relative_adjustement, AbsolutelyPositionedBox, HoistedAbsolutelyPositionedBox,
|
relative_adjustement, AbsolutelyPositionedBox, HoistedAbsolutelyPositionedBox,
|
||||||
PositioningContext,
|
PositioningContext,
|
||||||
};
|
};
|
||||||
use crate::sizing::{self, ContentSizes};
|
use crate::sizing::ContentSizes;
|
||||||
use crate::style_ext::{ComputedValuesExt, Display, DisplayGeneratingBox, DisplayOutside};
|
use crate::style_ext::{ComputedValuesExt, Display, DisplayGeneratingBox, DisplayOutside};
|
||||||
use crate::ContainingBlock;
|
use crate::ContainingBlock;
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
|
@ -200,10 +200,9 @@ impl InlineFormattingContext {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
InlineLevelBox::Atomic(atomic) => {
|
InlineLevelBox::Atomic(atomic) => {
|
||||||
let (outer, pc) = sizing::outer_inline_and_percentages(
|
let (outer, pc) = atomic.outer_inline_and_percentages(
|
||||||
&atomic.style(),
|
self.layout_context,
|
||||||
self.containing_block_writing_mode,
|
self.containing_block_writing_mode,
|
||||||
|| atomic.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;
|
||||||
|
@ -595,7 +594,9 @@ fn layout_atomic(
|
||||||
// https://drafts.csswg.org/css2/visudet.html#inlineblock-width
|
// https://drafts.csswg.org/css2/visudet.html#inlineblock-width
|
||||||
let tentative_inline_size = box_size.inline.auto_is(|| {
|
let tentative_inline_size = box_size.inline.auto_is(|| {
|
||||||
let available_size = ifc.containing_block.inline_size - pbm_sums.inline_sum();
|
let available_size = ifc.containing_block.inline_size - pbm_sums.inline_sum();
|
||||||
non_replaced.content_sizes.shrink_to_fit(available_size)
|
non_replaced
|
||||||
|
.inline_content_sizes(layout_context)
|
||||||
|
.shrink_to_fit(available_size)
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://drafts.csswg.org/css2/visudet.html#min-max-widths
|
// https://drafts.csswg.org/css2/visudet.html#min-max-widths
|
||||||
|
|
|
@ -18,11 +18,13 @@ use crate::fragments::{
|
||||||
use crate::geom::flow_relative::{Rect, Sides, Vec2};
|
use crate::geom::flow_relative::{Rect, Sides, Vec2};
|
||||||
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext};
|
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext};
|
||||||
use crate::replaced::ReplacedContent;
|
use crate::replaced::ReplacedContent;
|
||||||
|
use crate::sizing::{self, ContentSizes};
|
||||||
use crate::style_ext::{ComputedValuesExt, PaddingBorderMargin};
|
use crate::style_ext::{ComputedValuesExt, PaddingBorderMargin};
|
||||||
use crate::ContainingBlock;
|
use crate::ContainingBlock;
|
||||||
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
||||||
use rayon_croissant::ParallelIteratorExt;
|
use rayon_croissant::ParallelIteratorExt;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
|
use style::logical_geometry::WritingMode;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
use style::values::computed::{Length, LengthOrAuto};
|
use style::values::computed::{Length, LengthOrAuto};
|
||||||
use style::Zero;
|
use style::Zero;
|
||||||
|
@ -132,6 +134,29 @@ impl BlockContainer {
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn inline_content_sizes(
|
||||||
|
&self,
|
||||||
|
layout_context: &LayoutContext,
|
||||||
|
containing_block_writing_mode: WritingMode,
|
||||||
|
) -> ContentSizes {
|
||||||
|
match &self {
|
||||||
|
Self::BlockLevelBoxes(boxes) => {
|
||||||
|
let mut content_sizes = ContentSizes::zero();
|
||||||
|
for box_ in boxes {
|
||||||
|
content_sizes.max_assign(
|
||||||
|
&box_
|
||||||
|
.borrow_mut()
|
||||||
|
.inline_content_sizes(layout_context, containing_block_writing_mode),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
content_sizes
|
||||||
|
},
|
||||||
|
Self::InlineFormattingContext(context) => {
|
||||||
|
context.inline_content_sizes(layout_context, containing_block_writing_mode)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout_block_level_children(
|
fn layout_block_level_children(
|
||||||
|
@ -350,6 +375,28 @@ impl BlockLevelBox {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn inline_content_sizes(
|
||||||
|
&mut self,
|
||||||
|
layout_context: &LayoutContext,
|
||||||
|
containing_block_writing_mode: WritingMode,
|
||||||
|
) -> ContentSizes {
|
||||||
|
match self {
|
||||||
|
Self::SameFormattingContextBlock {
|
||||||
|
style, contents, ..
|
||||||
|
} => sizing::outer_inline(style, containing_block_writing_mode, || {
|
||||||
|
contents.inline_content_sizes(layout_context, style.writing_mode)
|
||||||
|
}),
|
||||||
|
Self::Independent(independent) => {
|
||||||
|
independent.outer_inline(layout_context, containing_block_writing_mode)
|
||||||
|
},
|
||||||
|
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(_) => ContentSizes::zero(),
|
||||||
|
BlockLevelBox::OutOfFlowFloatBox(_box_) => {
|
||||||
|
// TODO: Actually implement that.
|
||||||
|
ContentSizes::zero()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum NonReplacedContents<'a> {
|
enum NonReplacedContents<'a> {
|
||||||
|
|
|
@ -22,7 +22,6 @@ use crate::geom::{PhysicalPoint, PhysicalRect, PhysicalSize};
|
||||||
use crate::positioned::AbsolutelyPositionedBox;
|
use crate::positioned::AbsolutelyPositionedBox;
|
||||||
use crate::positioned::PositioningContext;
|
use crate::positioned::PositioningContext;
|
||||||
use crate::replaced::ReplacedContent;
|
use crate::replaced::ReplacedContent;
|
||||||
use crate::sizing::ContentSizesRequest;
|
|
||||||
use crate::style_ext::ComputedValuesExt;
|
use crate::style_ext::ComputedValuesExt;
|
||||||
use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside};
|
use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside};
|
||||||
use crate::wrapper::GetStyleAndLayoutData;
|
use crate::wrapper::GetStyleAndLayoutData;
|
||||||
|
@ -291,7 +290,6 @@ fn construct_for_root_element<'dom>(
|
||||||
&info,
|
&info,
|
||||||
display_inside,
|
display_inside,
|
||||||
contents,
|
contents,
|
||||||
ContentSizesRequest::None,
|
|
||||||
propagated_text_decoration_line,
|
propagated_text_decoration_line,
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,13 +9,14 @@ use crate::flow::BlockFormattingContext;
|
||||||
use crate::fragments::{Fragment, Tag};
|
use crate::fragments::{Fragment, Tag};
|
||||||
use crate::positioned::PositioningContext;
|
use crate::positioned::PositioningContext;
|
||||||
use crate::replaced::ReplacedContent;
|
use crate::replaced::ReplacedContent;
|
||||||
use crate::sizing::{BoxContentSizes, ContentSizes, ContentSizesRequest};
|
use crate::sizing::{self, 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;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
use style::logical_geometry::WritingMode;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
use style::values::computed::Length;
|
use style::values::computed::{Length, Percentage};
|
||||||
use style::values::specified::text::TextDecorationLine;
|
use style::values::specified::text::TextDecorationLine;
|
||||||
|
|
||||||
/// https://drafts.csswg.org/css-display/#independent-formatting-context
|
/// https://drafts.csswg.org/css-display/#independent-formatting-context
|
||||||
|
@ -31,7 +32,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: BoxContentSizes,
|
pub content_sizes: Option<ContentSizes>,
|
||||||
pub contents: NonReplacedFormattingContextContents,
|
pub contents: NonReplacedFormattingContextContents,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,42 +66,37 @@ impl IndependentFormattingContext {
|
||||||
info: &NodeAndStyleInfo<impl NodeExt<'dom>>,
|
info: &NodeAndStyleInfo<impl NodeExt<'dom>>,
|
||||||
display_inside: DisplayInside,
|
display_inside: DisplayInside,
|
||||||
contents: Contents,
|
contents: Contents,
|
||||||
content_sizes: ContentSizesRequest,
|
|
||||||
propagated_text_decoration_line: TextDecorationLine,
|
propagated_text_decoration_line: TextDecorationLine,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
match contents.try_into() {
|
match contents.try_into() {
|
||||||
Ok(non_replaced) => match display_inside {
|
Ok(non_replaced) => {
|
||||||
|
let contents = match display_inside {
|
||||||
DisplayInside::Flow | DisplayInside::FlowRoot => {
|
DisplayInside::Flow | DisplayInside::FlowRoot => {
|
||||||
let (bfc, content_sizes) = BlockFormattingContext::construct(
|
NonReplacedFormattingContextContents::Flow(
|
||||||
|
BlockFormattingContext::construct(
|
||||||
context,
|
context,
|
||||||
info,
|
info,
|
||||||
non_replaced,
|
non_replaced,
|
||||||
content_sizes,
|
|
||||||
propagated_text_decoration_line,
|
propagated_text_decoration_line,
|
||||||
);
|
),
|
||||||
Self::NonReplaced(NonReplacedFormattingContext {
|
)
|
||||||
tag: Tag::from_node_and_style_info(info),
|
|
||||||
style: Arc::clone(&info.style),
|
|
||||||
content_sizes,
|
|
||||||
contents: NonReplacedFormattingContextContents::Flow(bfc),
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
DisplayInside::Flex => {
|
DisplayInside::Flex => {
|
||||||
let (fc, content_sizes) = FlexContainer::construct(
|
NonReplacedFormattingContextContents::Flex(FlexContainer::construct(
|
||||||
context,
|
context,
|
||||||
info,
|
info,
|
||||||
non_replaced,
|
non_replaced,
|
||||||
content_sizes,
|
|
||||||
propagated_text_decoration_line,
|
propagated_text_decoration_line,
|
||||||
);
|
))
|
||||||
|
},
|
||||||
|
};
|
||||||
Self::NonReplaced(NonReplacedFormattingContext {
|
Self::NonReplaced(NonReplacedFormattingContext {
|
||||||
tag: Tag::from_node_and_style_info(info),
|
tag: Tag::from_node_and_style_info(info),
|
||||||
style: Arc::clone(&info.style),
|
style: Arc::clone(&info.style),
|
||||||
content_sizes,
|
content_sizes: None,
|
||||||
contents: NonReplacedFormattingContextContents::Flex(fc),
|
contents,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
|
||||||
Err(contents) => Self::Replaced(ReplacedFormattingContext {
|
Err(contents) => Self::Replaced(ReplacedFormattingContext {
|
||||||
tag: Tag::from_node_and_style_info(info),
|
tag: Tag::from_node_and_style_info(info),
|
||||||
style: Arc::clone(&info.style),
|
style: Arc::clone(&info.style),
|
||||||
|
@ -110,22 +106,16 @@ impl IndependentFormattingContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn construct_for_text_runs<'dom>(
|
pub fn construct_for_text_runs<'dom>(
|
||||||
context: &LayoutContext,
|
|
||||||
info: &NodeAndStyleInfo<impl NodeExt<'dom>>,
|
info: &NodeAndStyleInfo<impl NodeExt<'dom>>,
|
||||||
runs: impl Iterator<Item = crate::flow::inline::TextRun>,
|
runs: impl Iterator<Item = crate::flow::inline::TextRun>,
|
||||||
content_sizes: ContentSizesRequest,
|
|
||||||
propagated_text_decoration_line: TextDecorationLine,
|
propagated_text_decoration_line: TextDecorationLine,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let (bfc, content_sizes) = BlockFormattingContext::construct_for_text_runs(
|
let bfc =
|
||||||
context,
|
BlockFormattingContext::construct_for_text_runs(runs, propagated_text_decoration_line);
|
||||||
runs,
|
|
||||||
content_sizes,
|
|
||||||
propagated_text_decoration_line,
|
|
||||||
);
|
|
||||||
Self::NonReplaced(NonReplacedFormattingContext {
|
Self::NonReplaced(NonReplacedFormattingContext {
|
||||||
tag: Tag::from_node_and_style_info(info),
|
tag: Tag::from_node_and_style_info(info),
|
||||||
style: Arc::clone(&info.style),
|
style: Arc::clone(&info.style),
|
||||||
content_sizes,
|
content_sizes: None,
|
||||||
contents: NonReplacedFormattingContextContents::Flow(bfc),
|
contents: NonReplacedFormattingContextContents::Flow(bfc),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -144,10 +134,40 @@ impl IndependentFormattingContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn content_sizes(&self) -> ContentSizes {
|
pub fn outer_inline(
|
||||||
|
&mut self,
|
||||||
|
layout_context: &LayoutContext,
|
||||||
|
containing_block_writing_mode: WritingMode,
|
||||||
|
) -> ContentSizes {
|
||||||
|
let (mut outer, percentages) =
|
||||||
|
self.outer_inline_and_percentages(layout_context, containing_block_writing_mode);
|
||||||
|
outer.adjust_for_pbm_percentages(percentages);
|
||||||
|
outer
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn outer_inline_and_percentages(
|
||||||
|
&mut self,
|
||||||
|
layout_context: &LayoutContext,
|
||||||
|
containing_block_writing_mode: WritingMode,
|
||||||
|
) -> (ContentSizes, Percentage) {
|
||||||
match self {
|
match self {
|
||||||
Self::NonReplaced(inner) => inner.content_sizes.expect_inline().clone(),
|
Self::NonReplaced(non_replaced) => {
|
||||||
Self::Replaced(inner) => inner.contents.inline_content_sizes(&inner.style),
|
let style = &non_replaced.style;
|
||||||
|
let content_sizes = &mut non_replaced.content_sizes;
|
||||||
|
let contents = &non_replaced.contents;
|
||||||
|
sizing::outer_inline_and_percentages(&style, containing_block_writing_mode, || {
|
||||||
|
content_sizes
|
||||||
|
.get_or_insert_with(|| {
|
||||||
|
contents.inline_content_sizes(layout_context, style.writing_mode)
|
||||||
|
})
|
||||||
|
.clone()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
Self::Replaced(replaced) => sizing::outer_inline_and_percentages(
|
||||||
|
&replaced.style,
|
||||||
|
containing_block_writing_mode,
|
||||||
|
|| replaced.contents.inline_content_sizes(&replaced.style),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,4 +195,27 @@ impl NonReplacedFormattingContext {
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn inline_content_sizes(&mut self, layout_context: &LayoutContext) -> ContentSizes {
|
||||||
|
let writing_mode = self.style.writing_mode;
|
||||||
|
let contents = &self.contents;
|
||||||
|
self.content_sizes
|
||||||
|
.get_or_insert_with(|| contents.inline_content_sizes(layout_context, writing_mode))
|
||||||
|
.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NonReplacedFormattingContextContents {
|
||||||
|
pub fn inline_content_sizes(
|
||||||
|
&self,
|
||||||
|
layout_context: &LayoutContext,
|
||||||
|
containing_block_writing_mode: WritingMode,
|
||||||
|
) -> ContentSizes {
|
||||||
|
match self {
|
||||||
|
Self::Flow(inner) => inner
|
||||||
|
.contents
|
||||||
|
.inline_content_sizes(layout_context, containing_block_writing_mode),
|
||||||
|
Self::Flex(inner) => inner.inline_content_sizes(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ use crate::formatting_contexts::IndependentFormattingContext;
|
||||||
use crate::fragments::{BoxFragment, CollapsedBlockMargins, Fragment};
|
use crate::fragments::{BoxFragment, CollapsedBlockMargins, Fragment};
|
||||||
use crate::geom::flow_relative::{Rect, Sides, Vec2};
|
use crate::geom::flow_relative::{Rect, Sides, Vec2};
|
||||||
use crate::geom::{LengthOrAuto, LengthPercentageOrAuto};
|
use crate::geom::{LengthOrAuto, LengthPercentageOrAuto};
|
||||||
use crate::sizing::ContentSizesRequest;
|
|
||||||
use crate::style_ext::{ComputedValuesExt, DisplayInside};
|
use crate::style_ext::{ComputedValuesExt, DisplayInside};
|
||||||
use crate::{ContainingBlock, DefiniteContainingBlock};
|
use crate::{ContainingBlock, DefiniteContainingBlock};
|
||||||
use rayon::iter::{IntoParallelRefMutIterator, ParallelExtend};
|
use rayon::iter::{IntoParallelRefMutIterator, ParallelExtend};
|
||||||
|
@ -74,22 +73,12 @@ impl AbsolutelyPositionedBox {
|
||||||
display_inside: DisplayInside,
|
display_inside: DisplayInside,
|
||||||
contents: Contents,
|
contents: Contents,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// "Shrink-to-fit" in https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width
|
|
||||||
let content_sizes = ContentSizesRequest::inline_if(
|
|
||||||
// If inline-size is non-auto, that value is used without shrink-to-fit
|
|
||||||
!node_info.style.inline_size_is_length() &&
|
|
||||||
// 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
|
|
||||||
// in the constraint equation.
|
|
||||||
!node_info.style.inline_box_offsets_are_both_non_auto(),
|
|
||||||
);
|
|
||||||
Self {
|
Self {
|
||||||
context: IndependentFormattingContext::construct(
|
context: IndependentFormattingContext::construct(
|
||||||
context,
|
context,
|
||||||
node_info,
|
node_info,
|
||||||
display_inside,
|
display_inside,
|
||||||
contents,
|
contents,
|
||||||
content_sizes,
|
|
||||||
// Text decorations are not propagated to any out-of-flow descendants.
|
// Text decorations are not propagated to any out-of-flow descendants.
|
||||||
TextDecorationLine::NONE,
|
TextDecorationLine::NONE,
|
||||||
),
|
),
|
||||||
|
@ -472,7 +461,9 @@ impl HoistedAbsolutelyPositionedBox {
|
||||||
};
|
};
|
||||||
let available_size =
|
let available_size =
|
||||||
cbis - anchor - pbm.padding_border_sums.inline - margin.inline_sum();
|
cbis - anchor - pbm.padding_border_sums.inline - margin.inline_sum();
|
||||||
non_replaced.content_sizes.shrink_to_fit(available_size)
|
non_replaced
|
||||||
|
.inline_content_sizes(layout_context)
|
||||||
|
.shrink_to_fit(available_size)
|
||||||
});
|
});
|
||||||
|
|
||||||
let containing_block_for_children = ContainingBlock {
|
let containing_block_for_children = ContainingBlock {
|
||||||
|
|
|
@ -11,44 +11,6 @@ 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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn compute(self, compute_inline: impl FnOnce() -> ContentSizes) -> BoxContentSizes {
|
|
||||||
match self {
|
|
||||||
Self::Inline => BoxContentSizes::Inline(compute_inline()),
|
|
||||||
Self::None => BoxContentSizes::NoneWereRequested,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize)]
|
#[derive(Clone, Debug, Serialize)]
|
||||||
pub(crate) struct ContentSizes {
|
pub(crate) struct ContentSizes {
|
||||||
pub min_content: Length,
|
pub min_content: Length,
|
||||||
|
@ -90,27 +52,10 @@ impl ContentSizes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Optional min/max-content for storage in the box tree
|
impl ContentSizes {
|
||||||
#[derive(Debug, Serialize)]
|
|
||||||
pub(crate) enum BoxContentSizes {
|
|
||||||
NoneWereRequested, // … during box construction
|
|
||||||
Inline(ContentSizes),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BoxContentSizes {
|
|
||||||
pub fn expect_inline(&self) -> &ContentSizes {
|
|
||||||
match self {
|
|
||||||
Self::NoneWereRequested => panic!("Accessing content size that was not requested"),
|
|
||||||
Self::Inline(s) => s,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// https://drafts.csswg.org/css2/visudet.html#shrink-to-fit-float
|
/// https://drafts.csswg.org/css2/visudet.html#shrink-to-fit-float
|
||||||
pub(crate) fn shrink_to_fit(&self, available_size: Length) -> Length {
|
pub fn shrink_to_fit(&self, available_size: Length) -> Length {
|
||||||
let inline = self.expect_inline();
|
available_size.max(self.min_content).min(self.max_content)
|
||||||
available_size
|
|
||||||
.max(inline.min_content)
|
|
||||||
.min(inline.max_content)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ where
|
||||||
{
|
{
|
||||||
/// Resolves `auto` values by calling `f`.
|
/// Resolves `auto` values by calling `f`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn auto_is(&self, f: impl Fn() -> LengthPercentage) -> LengthPercentage {
|
pub fn auto_is(&self, f: impl FnOnce() -> LengthPercentage) -> LengthPercentage {
|
||||||
match self {
|
match self {
|
||||||
LengthPercentageOrAuto::LengthPercentage(length) => length.clone(),
|
LengthPercentageOrAuto::LengthPercentage(length) => length.clone(),
|
||||||
LengthPercentageOrAuto::Auto => f(),
|
LengthPercentageOrAuto::Auto => f(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue