mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
Use LazyCells instead of callbacks when resolving size keywords (#34211)
In most cases we already had a LazyCell anyways, since we could need the value for multiple properties. Instead of passing a callback that forces the evaluation of the LazyCell, it's simpler to just pass the LazyCell directly. Also, this way we no longer need mutable references. Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
5423e622ed
commit
6a62d52cbb
4 changed files with 75 additions and 78 deletions
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
//! Flow layout, also known as block-and-inline layout.
|
//! Flow layout, also known as block-and-inline layout.
|
||||||
|
|
||||||
|
use std::cell::LazyCell;
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use inline::InlineFormattingContext;
|
use inline::InlineFormattingContext;
|
||||||
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
||||||
|
@ -2053,21 +2055,19 @@ impl IndependentFormattingContext {
|
||||||
let tentative_block_size =
|
let tentative_block_size =
|
||||||
SizeConstraint::new(preferred_block_size, min_block_size, max_block_size);
|
SizeConstraint::new(preferred_block_size, min_block_size, max_block_size);
|
||||||
|
|
||||||
let mut get_content_size = || {
|
let content_size = LazyCell::new(|| {
|
||||||
let constraint_space = ConstraintSpace::new(tentative_block_size, writing_mode);
|
let constraint_space = ConstraintSpace::new(tentative_block_size, writing_mode);
|
||||||
non_replaced
|
non_replaced
|
||||||
.inline_content_sizes(layout_context, &constraint_space)
|
.inline_content_sizes(layout_context, &constraint_space)
|
||||||
.sizes
|
.sizes
|
||||||
};
|
});
|
||||||
|
|
||||||
// https://drafts.csswg.org/css2/visudet.html#float-width
|
// https://drafts.csswg.org/css2/visudet.html#float-width
|
||||||
// https://drafts.csswg.org/css2/visudet.html#inlineblock-width
|
// https://drafts.csswg.org/css2/visudet.html#inlineblock-width
|
||||||
let tentative_inline_size =
|
let tentative_inline_size = content_box_sizes_and_pbm
|
||||||
content_box_sizes_and_pbm.content_box_size.inline.resolve(
|
.content_box_size
|
||||||
Size::FitContent,
|
.inline
|
||||||
available_inline_size,
|
.resolve(Size::FitContent, available_inline_size, &content_size);
|
||||||
&mut get_content_size,
|
|
||||||
);
|
|
||||||
|
|
||||||
// https://drafts.csswg.org/css2/visudet.html#min-max-widths
|
// https://drafts.csswg.org/css2/visudet.html#min-max-widths
|
||||||
// In this case “applying the rules above again” with a non-auto inline-size
|
// In this case “applying the rules above again” with a non-auto inline-size
|
||||||
|
@ -2075,12 +2075,12 @@ impl IndependentFormattingContext {
|
||||||
let min_inline_size = content_box_sizes_and_pbm
|
let min_inline_size = content_box_sizes_and_pbm
|
||||||
.content_min_box_size
|
.content_min_box_size
|
||||||
.inline
|
.inline
|
||||||
.resolve_non_initial(available_inline_size, &mut get_content_size)
|
.resolve_non_initial(available_inline_size, &content_size)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let max_inline_size = content_box_sizes_and_pbm
|
let max_inline_size = content_box_sizes_and_pbm
|
||||||
.content_max_box_size
|
.content_max_box_size
|
||||||
.inline
|
.inline
|
||||||
.resolve_non_initial(available_inline_size, &mut get_content_size);
|
.resolve_non_initial(available_inline_size, &content_size);
|
||||||
let inline_size =
|
let inline_size =
|
||||||
tentative_inline_size.clamp_between_extremums(min_inline_size, max_inline_size);
|
tentative_inline_size.clamp_between_extremums(min_inline_size, max_inline_size);
|
||||||
|
|
||||||
|
@ -2101,24 +2101,24 @@ impl IndependentFormattingContext {
|
||||||
&containing_block_for_children,
|
&containing_block_for_children,
|
||||||
containing_block,
|
containing_block,
|
||||||
);
|
);
|
||||||
let (inline_size, block_size) = match independent_layout
|
let (inline_size, block_size) =
|
||||||
.content_inline_size_for_table
|
match independent_layout.content_inline_size_for_table {
|
||||||
{
|
|
||||||
Some(inline) => (inline, independent_layout.content_block_size),
|
Some(inline) => (inline, independent_layout.content_block_size),
|
||||||
None => {
|
None => {
|
||||||
// https://drafts.csswg.org/css2/visudet.html#block-root-margin
|
// https://drafts.csswg.org/css2/visudet.html#block-root-margin
|
||||||
let stretch_size =
|
let stretch_size = available_block_size
|
||||||
available_block_size.unwrap_or(independent_layout.content_block_size);
|
.unwrap_or(independent_layout.content_block_size);
|
||||||
let mut get_content_size = || independent_layout.content_block_size.into();
|
let content_size =
|
||||||
|
LazyCell::new(|| independent_layout.content_block_size.into());
|
||||||
let min_block_size = content_box_sizes_and_pbm
|
let min_block_size = content_box_sizes_and_pbm
|
||||||
.content_min_box_size
|
.content_min_box_size
|
||||||
.block
|
.block
|
||||||
.resolve_non_initial(stretch_size, &mut get_content_size)
|
.resolve_non_initial(stretch_size, &content_size)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let max_block_size = content_box_sizes_and_pbm
|
let max_block_size = content_box_sizes_and_pbm
|
||||||
.content_max_box_size
|
.content_max_box_size
|
||||||
.block
|
.block
|
||||||
.resolve_non_initial(stretch_size, &mut get_content_size);
|
.resolve_non_initial(stretch_size, &content_size);
|
||||||
let block_size = tentative_block_size
|
let block_size = tentative_block_size
|
||||||
.to_definite()
|
.to_definite()
|
||||||
.unwrap_or(independent_layout.content_block_size)
|
.unwrap_or(independent_layout.content_block_size)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::cell::LazyCell;
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::{Add, AddAssign, Neg, Sub, SubAssign};
|
use std::ops::{Add, AddAssign, Neg, Sub, SubAssign};
|
||||||
|
@ -798,17 +799,17 @@ impl LogicalVec2<Size<LengthPercentage>> {
|
||||||
impl Size<Au> {
|
impl Size<Au> {
|
||||||
/// Resolves any size into a numerical value.
|
/// Resolves any size into a numerical value.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn resolve(
|
pub(crate) fn resolve<F: FnOnce() -> ContentSizes>(
|
||||||
&self,
|
&self,
|
||||||
initial_behavior: Self,
|
initial_behavior: Self,
|
||||||
stretch_size: Au,
|
stretch_size: Au,
|
||||||
get_content_size: &mut impl FnMut() -> ContentSizes,
|
content_size: &LazyCell<ContentSizes, F>,
|
||||||
) -> Au {
|
) -> Au {
|
||||||
if self.is_initial() {
|
if self.is_initial() {
|
||||||
assert!(!initial_behavior.is_initial());
|
assert!(!initial_behavior.is_initial());
|
||||||
initial_behavior.resolve_non_initial(stretch_size, get_content_size)
|
initial_behavior.resolve_non_initial(stretch_size, content_size)
|
||||||
} else {
|
} else {
|
||||||
self.resolve_non_initial(stretch_size, get_content_size)
|
self.resolve_non_initial(stretch_size, content_size)
|
||||||
}
|
}
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
@ -816,16 +817,16 @@ impl Size<Au> {
|
||||||
/// Resolves a non-initial size into a numerical value.
|
/// Resolves a non-initial size into a numerical value.
|
||||||
/// Returns `None` if the size is the initial one.
|
/// Returns `None` if the size is the initial one.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn resolve_non_initial(
|
pub(crate) fn resolve_non_initial<F: FnOnce() -> ContentSizes>(
|
||||||
&self,
|
&self,
|
||||||
stretch_size: Au,
|
stretch_size: Au,
|
||||||
get_content_size: &mut impl FnMut() -> ContentSizes,
|
content_size: &LazyCell<ContentSizes, F>,
|
||||||
) -> Option<Au> {
|
) -> Option<Au> {
|
||||||
match self {
|
match self {
|
||||||
Self::Initial => None,
|
Self::Initial => None,
|
||||||
Self::MinContent => Some(get_content_size().min_content),
|
Self::MinContent => Some(content_size.min_content),
|
||||||
Self::MaxContent => Some(get_content_size().max_content),
|
Self::MaxContent => Some(content_size.max_content),
|
||||||
Self::FitContent => Some(get_content_size().shrink_to_fit(stretch_size)),
|
Self::FitContent => Some(content_size.shrink_to_fit(stretch_size)),
|
||||||
Self::Stretch => Some(stretch_size),
|
Self::Stretch => Some(stretch_size),
|
||||||
Self::Numeric(numeric) => Some(*numeric),
|
Self::Numeric(numeric) => Some(*numeric),
|
||||||
}
|
}
|
||||||
|
|
|
@ -773,28 +773,25 @@ impl<'a> AbsoluteAxisSolver<'a> {
|
||||||
///
|
///
|
||||||
/// In the replaced case, `size` is never `Auto`.
|
/// In the replaced case, `size` is never `Auto`.
|
||||||
fn solve(&self, get_content_size: Option<impl FnOnce() -> ContentSizes>) -> AxisResult {
|
fn solve(&self, get_content_size: Option<impl FnOnce() -> ContentSizes>) -> AxisResult {
|
||||||
let mut get_content_size = get_content_size.map(|get_content_size| {
|
|
||||||
// The provided `get_content_size` is a FnOnce but we may need its result multiple times.
|
// The provided `get_content_size` is a FnOnce but we may need its result multiple times.
|
||||||
// A LazyCell will only invoke it once if needed, and then reuse the result.
|
// A LazyCell will only invoke it once if needed, and then reuse the result.
|
||||||
let content_size = LazyCell::new(get_content_size);
|
let content_size = get_content_size.map(LazyCell::new);
|
||||||
move || *content_size
|
let solve_size = |initial_behavior, stretch_size: Au| -> SizeConstraint {
|
||||||
});
|
|
||||||
let mut solve_size = |initial_behavior, stretch_size: Au| -> SizeConstraint {
|
|
||||||
let initial_is_stretch = initial_behavior == Size::Stretch;
|
let initial_is_stretch = initial_behavior == Size::Stretch;
|
||||||
let stretch_size = stretch_size.max(Au::zero());
|
let stretch_size = stretch_size.max(Au::zero());
|
||||||
if let Some(mut get_content_size) = get_content_size.as_mut() {
|
if let Some(ref content_size) = content_size {
|
||||||
let preferred_size = Some(self.computed_size.resolve(
|
let preferred_size = Some(self.computed_size.resolve(
|
||||||
initial_behavior,
|
initial_behavior,
|
||||||
stretch_size,
|
stretch_size,
|
||||||
&mut get_content_size,
|
content_size,
|
||||||
));
|
));
|
||||||
let min_size = self
|
let min_size = self
|
||||||
.computed_min_size
|
.computed_min_size
|
||||||
.resolve_non_initial(stretch_size, &mut get_content_size)
|
.resolve_non_initial(stretch_size, content_size)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let max_size = self
|
let max_size = self
|
||||||
.computed_max_size
|
.computed_max_size
|
||||||
.resolve_non_initial(stretch_size, &mut get_content_size);
|
.resolve_non_initial(stretch_size, content_size);
|
||||||
SizeConstraint::new(preferred_size, min_size, max_size)
|
SizeConstraint::new(preferred_size, min_size, max_size)
|
||||||
} else {
|
} else {
|
||||||
let preferred_size = self
|
let preferred_size = self
|
||||||
|
@ -811,7 +808,7 @@ impl<'a> AbsoluteAxisSolver<'a> {
|
||||||
SizeConstraint::new(preferred_size, min_size, max_size)
|
SizeConstraint::new(preferred_size, min_size, max_size)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut solve_for_anchor = |anchor: Anchor| {
|
let solve_for_anchor = |anchor: Anchor| {
|
||||||
let margin_start = self.computed_margin_start.auto_is(Au::zero);
|
let margin_start = self.computed_margin_start.auto_is(Au::zero);
|
||||||
let margin_end = self.computed_margin_end.auto_is(Au::zero);
|
let margin_end = self.computed_margin_end.auto_is(Au::zero);
|
||||||
let stretch_size = self.containing_size -
|
let stretch_size = self.containing_size -
|
||||||
|
|
|
@ -29,7 +29,7 @@ use crate::context::LayoutContext;
|
||||||
use crate::dom::NodeExt;
|
use crate::dom::NodeExt;
|
||||||
use crate::fragment_tree::{BaseFragmentInfo, Fragment, IFrameFragment, ImageFragment};
|
use crate::fragment_tree::{BaseFragmentInfo, Fragment, IFrameFragment, ImageFragment};
|
||||||
use crate::geom::{LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSize, Size};
|
use crate::geom::{LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSize, Size};
|
||||||
use crate::sizing::InlineContentSizesResult;
|
use crate::sizing::{ContentSizes, InlineContentSizesResult};
|
||||||
use crate::style_ext::{AspectRatio, Clamp, ComputedValuesExt, ContentBoxSizesAndPBM};
|
use crate::style_ext::{AspectRatio, Clamp, ComputedValuesExt, ContentBoxSizesAndPBM};
|
||||||
use crate::{ConstraintSpace, ContainingBlock, IndefiniteContainingBlock, SizeConstraint};
|
use crate::{ConstraintSpace, ContainingBlock, IndefiniteContainingBlock, SizeConstraint};
|
||||||
|
|
||||||
|
@ -561,21 +561,21 @@ impl ReplacedContent {
|
||||||
&get_block_size,
|
&get_block_size,
|
||||||
&get_inline_fallback_size,
|
&get_inline_fallback_size,
|
||||||
)
|
)
|
||||||
|
.into()
|
||||||
});
|
});
|
||||||
let block_content_size = LazyCell::new(|| {
|
let block_content_size = LazyCell::new(|| -> ContentSizes {
|
||||||
let get_inline_size = || {
|
let get_inline_size = || {
|
||||||
let mut get_inline_content_size = || (*inline_content_size).into();
|
|
||||||
SizeConstraint::new(
|
SizeConstraint::new(
|
||||||
box_size
|
box_size
|
||||||
.inline
|
.inline
|
||||||
.maybe_resolve_extrinsic(Some(inline_stretch_size)),
|
.maybe_resolve_extrinsic(Some(inline_stretch_size)),
|
||||||
min_box_size
|
min_box_size
|
||||||
.inline
|
.inline
|
||||||
.resolve_non_initial(inline_stretch_size, &mut get_inline_content_size)
|
.resolve_non_initial(inline_stretch_size, &inline_content_size)
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
max_box_size
|
max_box_size
|
||||||
.inline
|
.inline
|
||||||
.resolve_non_initial(inline_stretch_size, &mut get_inline_content_size),
|
.resolve_non_initial(inline_stretch_size, &inline_content_size),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
self.content_size(
|
self.content_size(
|
||||||
|
@ -584,36 +584,35 @@ impl ReplacedContent {
|
||||||
&get_inline_size,
|
&get_inline_size,
|
||||||
&get_block_fallback_size,
|
&get_block_fallback_size,
|
||||||
)
|
)
|
||||||
|
.into()
|
||||||
});
|
});
|
||||||
let mut get_inline_content_size = || (*inline_content_size).into();
|
let block_stretch_size =
|
||||||
let mut get_block_content_size = || (*block_content_size).into();
|
block_stretch_size.unwrap_or_else(|| block_content_size.max_content);
|
||||||
let block_stretch_size = block_stretch_size.unwrap_or_else(|| *block_content_size);
|
|
||||||
|
|
||||||
// <https://drafts.csswg.org/css-sizing-3/#sizing-properties>
|
// <https://drafts.csswg.org/css-sizing-3/#sizing-properties>
|
||||||
let preferred_inline = box_size.inline.resolve(
|
let preferred_inline =
|
||||||
Size::FitContent,
|
box_size
|
||||||
inline_stretch_size,
|
.inline
|
||||||
&mut get_inline_content_size,
|
.resolve(Size::FitContent, inline_stretch_size, &inline_content_size);
|
||||||
);
|
let preferred_block =
|
||||||
let preferred_block = box_size.block.resolve(
|
box_size
|
||||||
Size::FitContent,
|
.block
|
||||||
block_stretch_size,
|
.resolve(Size::FitContent, block_stretch_size, &block_content_size);
|
||||||
&mut get_block_content_size,
|
|
||||||
);
|
|
||||||
let min_inline = min_box_size
|
let min_inline = min_box_size
|
||||||
.inline
|
.inline
|
||||||
.resolve_non_initial(inline_stretch_size, &mut get_inline_content_size)
|
.resolve_non_initial(inline_stretch_size, &inline_content_size)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let min_block = min_box_size
|
let min_block = min_box_size
|
||||||
.block
|
.block
|
||||||
.resolve_non_initial(block_stretch_size, &mut get_block_content_size)
|
.resolve_non_initial(block_stretch_size, &block_content_size)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let max_inline = max_box_size
|
let max_inline = max_box_size
|
||||||
.inline
|
.inline
|
||||||
.resolve_non_initial(inline_stretch_size, &mut get_inline_content_size);
|
.resolve_non_initial(inline_stretch_size, &inline_content_size);
|
||||||
let max_block = max_box_size
|
let max_block = max_box_size
|
||||||
.block
|
.block
|
||||||
.resolve_non_initial(block_stretch_size, &mut get_block_content_size);
|
.resolve_non_initial(block_stretch_size, &block_content_size);
|
||||||
|
|
||||||
LogicalVec2 {
|
LogicalVec2 {
|
||||||
inline: preferred_inline.clamp_between_extremums(min_inline, max_inline),
|
inline: preferred_inline.clamp_between_extremums(min_inline, max_inline),
|
||||||
block: preferred_block.clamp_between_extremums(min_block, max_block),
|
block: preferred_block.clamp_between_extremums(min_block, max_block),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue