mirror of
https://github.com/servo/servo.git
synced 2025-07-25 00:00:20 +01:00
Use a new BoxContentSizes
enum instead of Option<ContentSizes>
This commit is contained in:
parent
38e8fd1e99
commit
dd9dfc66e3
5 changed files with 103 additions and 96 deletions
|
@ -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, ContentSizesRequest};
|
use crate::sizing::{BoxContentSizes, 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;
|
||||||
|
@ -25,7 +25,7 @@ impl BlockFormattingContext {
|
||||||
style: &Arc<ComputedValues>,
|
style: &Arc<ComputedValues>,
|
||||||
contents: NonReplacedContents<impl NodeExt<'dom>>,
|
contents: NonReplacedContents<impl NodeExt<'dom>>,
|
||||||
content_sizes: ContentSizesRequest,
|
content_sizes: ContentSizesRequest,
|
||||||
) -> (Self, Option<ContentSizes>) {
|
) -> (Self, BoxContentSizes) {
|
||||||
let (contents, contains_floats, inline_content_sizes) =
|
let (contents, contains_floats, inline_content_sizes) =
|
||||||
BlockContainer::construct(context, style, contents, content_sizes);
|
BlockContainer::construct(context, style, contents, content_sizes);
|
||||||
// FIXME: add contribution to `inline_content_sizes` of floats in this formatting context
|
// FIXME: add contribution to `inline_content_sizes` of floats in this formatting context
|
||||||
|
@ -134,7 +134,7 @@ impl BlockContainer {
|
||||||
block_container_style: &Arc<ComputedValues>,
|
block_container_style: &Arc<ComputedValues>,
|
||||||
contents: NonReplacedContents<impl NodeExt<'dom>>,
|
contents: NonReplacedContents<impl NodeExt<'dom>>,
|
||||||
content_sizes: ContentSizesRequest,
|
content_sizes: ContentSizesRequest,
|
||||||
) -> (BlockContainer, ContainsFloats, Option<ContentSizes>) {
|
) -> (BlockContainer, ContainsFloats, BoxContentSizes) {
|
||||||
let mut builder = BlockContainerBuilder {
|
let mut builder = BlockContainerBuilder {
|
||||||
context,
|
context,
|
||||||
block_container_style,
|
block_container_style,
|
||||||
|
@ -155,7 +155,7 @@ impl BlockContainer {
|
||||||
.is_empty()
|
.is_empty()
|
||||||
{
|
{
|
||||||
if builder.block_level_boxes.is_empty() {
|
if builder.block_level_boxes.is_empty() {
|
||||||
let inline_content_sizes = content_sizes.if_requests_inline(|| {
|
let content_sizes = content_sizes.compute(|| {
|
||||||
builder
|
builder
|
||||||
.ongoing_inline_formatting_context
|
.ongoing_inline_formatting_context
|
||||||
.inline_content_sizes(context)
|
.inline_content_sizes(context)
|
||||||
|
@ -163,7 +163,7 @@ impl BlockContainer {
|
||||||
let container = BlockContainer::InlineFormattingContext(
|
let container = BlockContainer::InlineFormattingContext(
|
||||||
builder.ongoing_inline_formatting_context,
|
builder.ongoing_inline_formatting_context,
|
||||||
);
|
);
|
||||||
return (container, builder.contains_floats, inline_content_sizes);
|
return (container, builder.contains_floats, content_sizes);
|
||||||
}
|
}
|
||||||
builder.end_ongoing_inline_formatting_context();
|
builder.end_ongoing_inline_formatting_context();
|
||||||
}
|
}
|
||||||
|
@ -212,9 +212,8 @@ impl BlockContainer {
|
||||||
contains_floats,
|
contains_floats,
|
||||||
outer_content_sizes_of_children,
|
outer_content_sizes_of_children,
|
||||||
} = target;
|
} = target;
|
||||||
let inline_content_sizes =
|
let content_sizes = content_sizes.compute(|| outer_content_sizes_of_children);
|
||||||
content_sizes.if_requests_inline(|| outer_content_sizes_of_children);
|
(container, contains_floats, content_sizes)
|
||||||
(container, contains_floats, inline_content_sizes)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -586,7 +585,7 @@ where
|
||||||
) -> (Arc<BlockLevelBox>, ContainsFloats) {
|
) -> (Arc<BlockLevelBox>, ContainsFloats) {
|
||||||
match self {
|
match self {
|
||||||
IntermediateBlockLevelBox::SameFormattingContextBlock { style, contents } => {
|
IntermediateBlockLevelBox::SameFormattingContextBlock { style, contents } => {
|
||||||
let (contents, contains_floats, inline_content_sizes) = contents.finish(
|
let (contents, contains_floats, box_content_sizes) = contents.finish(
|
||||||
context,
|
context,
|
||||||
&style,
|
&style,
|
||||||
ContentSizesRequest::inline_if(
|
ContentSizesRequest::inline_if(
|
||||||
|
@ -595,7 +594,7 @@ where
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
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, &inline_content_sizes))
|
to.max_assign(&box_content_sizes.outer_inline(&style))
|
||||||
}
|
}
|
||||||
let block_level_box =
|
let block_level_box =
|
||||||
Arc::new(BlockLevelBox::SameFormattingContextBlock { contents, style });
|
Arc::new(BlockLevelBox::SameFormattingContextBlock { contents, style });
|
||||||
|
@ -618,10 +617,7 @@ where
|
||||||
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(&contents.content_sizes.outer_inline(&contents.style))
|
||||||
&contents.style,
|
|
||||||
&contents.inline_content_sizes,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
Arc::new(BlockLevelBox::Independent(contents)),
|
Arc::new(BlockLevelBox::Independent(contents)),
|
||||||
|
@ -661,21 +657,20 @@ where
|
||||||
context: &LayoutContext,
|
context: &LayoutContext,
|
||||||
style: &Arc<ComputedValues>,
|
style: &Arc<ComputedValues>,
|
||||||
content_sizes: ContentSizesRequest,
|
content_sizes: ContentSizesRequest,
|
||||||
) -> (BlockContainer, ContainsFloats, Option<ContentSizes>) {
|
) -> (BlockContainer, ContainsFloats, BoxContentSizes) {
|
||||||
match self {
|
match self {
|
||||||
IntermediateBlockContainer::Deferred { contents } => {
|
IntermediateBlockContainer::Deferred { contents } => {
|
||||||
BlockContainer::construct(context, style, contents, content_sizes)
|
BlockContainer::construct(context, style, contents, content_sizes)
|
||||||
},
|
},
|
||||||
IntermediateBlockContainer::InlineFormattingContext(ifc) => {
|
IntermediateBlockContainer::InlineFormattingContext(ifc) => {
|
||||||
let inline_content_sizes =
|
let content_sizes = content_sizes.compute(|| ifc.inline_content_sizes(context));
|
||||||
content_sizes.if_requests_inline(|| ifc.inline_content_sizes(context));
|
|
||||||
// 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,
|
||||||
inline_content_sizes,
|
content_sizes,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_and_percentages, shrink_to_fit, ContentSizes};
|
use crate::sizing::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;
|
||||||
|
@ -139,10 +139,9 @@ impl InlineFormattingContext {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
InlineLevelBox::Atomic(atomic) => {
|
InlineLevelBox::Atomic(atomic) => {
|
||||||
let (outer, pc) = outer_inline_content_sizes_and_percentages(
|
let (outer, pc) = atomic
|
||||||
&atomic.style,
|
.content_sizes
|
||||||
&atomic.inline_content_sizes,
|
.outer_inline_and_percentages(&atomic.style);
|
||||||
);
|
|
||||||
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;
|
||||||
|
@ -439,7 +438,7 @@ fn layout_atomic<'box_tree>(
|
||||||
let box_size = atomic.style.box_size();
|
let box_size = atomic.style.box_size();
|
||||||
let inline_size = box_size.inline.percentage_relative_to(cbis).auto_is(|| {
|
let inline_size = box_size.inline.percentage_relative_to(cbis).auto_is(|| {
|
||||||
let available_size = cbis - pbm.inline_sum();
|
let available_size = cbis - pbm.inline_sum();
|
||||||
shrink_to_fit(&atomic.inline_content_sizes, available_size)
|
atomic.content_sizes.shrink_to_fit(available_size)
|
||||||
});
|
});
|
||||||
let block_size = box_size
|
let block_size = box_size
|
||||||
.block
|
.block
|
||||||
|
|
|
@ -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, ContentSizesRequest};
|
use crate::sizing::{BoxContentSizes, 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;
|
||||||
|
@ -22,7 +22,7 @@ pub(crate) struct IndependentFormattingContext {
|
||||||
pub style: Arc<ComputedValues>,
|
pub style: Arc<ComputedValues>,
|
||||||
|
|
||||||
/// If it was requested during construction
|
/// If it was requested during construction
|
||||||
pub inline_content_sizes: Option<ContentSizes>,
|
pub content_sizes: BoxContentSizes,
|
||||||
|
|
||||||
contents: IndependentFormattingContextContents,
|
contents: IndependentFormattingContextContents,
|
||||||
}
|
}
|
||||||
|
@ -58,27 +58,30 @@ impl IndependentFormattingContext {
|
||||||
content_sizes: ContentSizesRequest,
|
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, 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, inline_content_sizes) = BlockFormattingContext::construct(
|
let (bfc, box_content_sizes) = BlockFormattingContext::construct(
|
||||||
context,
|
context,
|
||||||
&style,
|
&style,
|
||||||
non_replaced,
|
non_replaced,
|
||||||
content_sizes,
|
content_sizes,
|
||||||
);
|
);
|
||||||
(Contents::Flow(bfc), inline_content_sizes)
|
(Contents::Flow(bfc), box_content_sizes)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Err(replaced) => {
|
Err(replaced) => {
|
||||||
let inline_content_sizes = None; // Unused by layout code
|
// The `content_sizes` field is not used by layout code:
|
||||||
(Contents::Replaced(replaced), inline_content_sizes)
|
(
|
||||||
|
Contents::Replaced(replaced),
|
||||||
|
BoxContentSizes::NoneWereRequested,
|
||||||
|
)
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
Self {
|
Self {
|
||||||
style,
|
style,
|
||||||
contents,
|
contents,
|
||||||
inline_content_sizes,
|
content_sizes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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, ContentSizesRequest};
|
use crate::sizing::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};
|
||||||
|
@ -295,10 +295,10 @@ impl<'a> AbsolutelyPositionedFragment<'a> {
|
||||||
// FIXME: implement https://drafts.csswg.org/css2/visudet.html#abs-replaced-width
|
// FIXME: implement https://drafts.csswg.org/css2/visudet.html#abs-replaced-width
|
||||||
available_size
|
available_size
|
||||||
} else {
|
} else {
|
||||||
shrink_to_fit(
|
self.absolutely_positioned_box
|
||||||
&self.absolutely_positioned_box.contents.inline_content_sizes,
|
.contents
|
||||||
available_size,
|
.content_sizes
|
||||||
)
|
.shrink_to_fit(available_size)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,13 @@ impl ContentSizesRequest {
|
||||||
Self::None => None,
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -74,69 +81,72 @@ impl ContentSizes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://dbaron.org/css/intrinsic/#outer-intrinsic
|
/// Optional min/max-content for storage in the box tree
|
||||||
pub(crate) fn outer_inline_content_sizes(
|
#[derive(Debug)]
|
||||||
style: &ComputedValues,
|
pub(crate) enum BoxContentSizes {
|
||||||
inner_content_sizes: &Option<ContentSizes>,
|
NoneWereRequested, // … during box construction
|
||||||
) -> ContentSizes {
|
Inline(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(
|
impl BoxContentSizes {
|
||||||
style: &ComputedValues,
|
fn expect_inline(&self) -> &ContentSizes {
|
||||||
inner_content_sizes: &Option<ContentSizes>,
|
match self {
|
||||||
) -> (ContentSizes, Percentage) {
|
Self::NoneWereRequested => panic!("Accessing content size that was not requested"),
|
||||||
// FIXME: account for 'min-width', 'max-width', 'box-sizing'
|
Self::Inline(s) => s,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let inline_size = style.box_size().inline;
|
/// https://dbaron.org/css/intrinsic/#outer-intrinsic
|
||||||
// Percentages for 'width' are treated as 'auto'
|
pub fn outer_inline(&self, style: &ComputedValues) -> ContentSizes {
|
||||||
let inline_size = inline_size.map(|lp| lp.as_length());
|
let (mut outer, percentages) = self.outer_inline_and_percentages(style);
|
||||||
// The (inner) min/max-content are only used for 'auto'
|
outer.adjust_for_pbm_percentages(percentages);
|
||||||
let mut outer = match inline_size.non_auto().flatten() {
|
outer
|
||||||
None => expect(inner_content_sizes).clone(),
|
}
|
||||||
Some(length) => ContentSizes {
|
|
||||||
min_content: length,
|
|
||||||
max_content: length,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut pbm_lengths = Length::zero();
|
pub(crate) fn outer_inline_and_percentages(
|
||||||
let mut pbm_percentages = Percentage::zero();
|
&self,
|
||||||
let padding = style.padding();
|
style: &ComputedValues,
|
||||||
let border = style.border_width();
|
) -> (ContentSizes, Percentage) {
|
||||||
let margin = style.margin();
|
// FIXME: account for 'min-width', 'max-width', 'box-sizing'
|
||||||
pbm_lengths += border.inline_sum();
|
|
||||||
let mut add = |x: LengthPercentage| {
|
|
||||||
pbm_lengths += x.length_component();
|
|
||||||
pbm_percentages += x.percentage_component();
|
|
||||||
};
|
|
||||||
add(padding.inline_start);
|
|
||||||
add(padding.inline_end);
|
|
||||||
margin.inline_start.non_auto().map(&mut add);
|
|
||||||
margin.inline_end.non_auto().map(&mut add);
|
|
||||||
|
|
||||||
outer.min_content += pbm_lengths;
|
let inline_size = style.box_size().inline;
|
||||||
outer.max_content += pbm_lengths;
|
// Percentages for 'width' are treated as 'auto'
|
||||||
|
let inline_size = inline_size.map(|lp| lp.as_length());
|
||||||
|
// The (inner) min/max-content are only used for 'auto'
|
||||||
|
let mut outer = match inline_size.non_auto().flatten() {
|
||||||
|
None => self.expect_inline().clone(),
|
||||||
|
Some(length) => ContentSizes {
|
||||||
|
min_content: length,
|
||||||
|
max_content: length,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
(outer, pbm_percentages)
|
let mut pbm_lengths = Length::zero();
|
||||||
}
|
let mut pbm_percentages = Percentage::zero();
|
||||||
|
let padding = style.padding();
|
||||||
/// https://drafts.csswg.org/css2/visudet.html#shrink-to-fit-float
|
let border = style.border_width();
|
||||||
pub(crate) fn shrink_to_fit(
|
let margin = style.margin();
|
||||||
content_sizes: &Option<ContentSizes>,
|
pbm_lengths += border.inline_sum();
|
||||||
available_size: Length,
|
let mut add = |x: LengthPercentage| {
|
||||||
) -> Length {
|
pbm_lengths += x.length_component();
|
||||||
let content_sizes = expect(content_sizes);
|
pbm_percentages += x.percentage_component();
|
||||||
available_size
|
};
|
||||||
.max(content_sizes.min_content)
|
add(padding.inline_start);
|
||||||
.min(content_sizes.max_content)
|
add(padding.inline_end);
|
||||||
}
|
margin.inline_start.non_auto().map(&mut add);
|
||||||
|
margin.inline_end.non_auto().map(&mut add);
|
||||||
fn expect(content_sizes: &Option<ContentSizes>) -> &ContentSizes {
|
|
||||||
content_sizes
|
outer.min_content += pbm_lengths;
|
||||||
.as_ref()
|
outer.max_content += pbm_lengths;
|
||||||
.expect("Accessing content size that was not requested")
|
|
||||||
|
(outer, pbm_percentages)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://drafts.csswg.org/css2/visudet.html#shrink-to-fit-float
|
||||||
|
pub(crate) fn shrink_to_fit(&self, available_size: Length) -> Length {
|
||||||
|
let inline = self.expect_inline();
|
||||||
|
available_size
|
||||||
|
.max(inline.min_content)
|
||||||
|
.min(inline.max_content)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue