aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout/geom.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/layout/geom.rs')
-rw-r--r--components/layout/geom.rs86
1 files changed, 85 insertions, 1 deletions
diff --git a/components/layout/geom.rs b/components/layout/geom.rs
index 6a09519b7ed..4065b785832 100644
--- a/components/layout/geom.rs
+++ b/components/layout/geom.rs
@@ -2,7 +2,7 @@
* 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/. */
-use std::cell::LazyCell;
+use std::cell::{LazyCell, OnceCell};
use std::convert::From;
use std::fmt;
use std::ops::{Add, AddAssign, Neg, Sub, SubAssign};
@@ -1102,3 +1102,87 @@ impl Sizes {
)
}
}
+
+struct LazySizeData<'a> {
+ sizes: &'a Sizes,
+ axis: Direction,
+ automatic_size: Size<Au>,
+ get_automatic_minimum_size: fn() -> Au,
+ stretch_size: Option<Au>,
+ is_table: bool,
+}
+
+/// Represents a size that can't be fully resolved until the intrinsic size
+/// is known. This is useful in the block axis, since the intrinsic size
+/// depends on layout, but the other inputs are known beforehand.
+pub(crate) struct LazySize<'a> {
+ result: OnceCell<Au>,
+ data: Option<LazySizeData<'a>>,
+}
+
+impl<'a> LazySize<'a> {
+ pub(crate) fn new(
+ sizes: &'a Sizes,
+ axis: Direction,
+ automatic_size: Size<Au>,
+ get_automatic_minimum_size: fn() -> Au,
+ stretch_size: Option<Au>,
+ is_table: bool,
+ ) -> Self {
+ Self {
+ result: OnceCell::new(),
+ data: Some(LazySizeData {
+ sizes,
+ axis,
+ automatic_size,
+ get_automatic_minimum_size,
+ stretch_size,
+ is_table,
+ }),
+ }
+ }
+
+ /// Creates a [`LazySize`] that will resolve to the intrinsic size.
+ /// Should be equivalent to [`LazySize::new()`] with default parameters,
+ /// but avoiding the trouble of getting a reference to a [`Sizes::default()`]
+ /// which lives long enough.
+ ///
+ /// TODO: It's not clear what this should do if/when [`LazySize::resolve()`]
+ /// is changed to accept a [`ContentSizes`] as the intrinsic size.
+ pub(crate) fn intrinsic() -> Self {
+ Self {
+ result: OnceCell::new(),
+ data: None,
+ }
+ }
+
+ /// Resolves the [`LazySize`] into [`Au`], caching the result.
+ /// The argument is a callback that computes the intrinsic size lazily.
+ ///
+ /// TODO: The intrinsic size should probably be a [`ContentSizes`] instead of [`Au`].
+ pub(crate) fn resolve(&self, get_content_size: impl FnOnce() -> Au) -> Au {
+ *self.result.get_or_init(|| {
+ let Some(ref data) = self.data else {
+ return get_content_size();
+ };
+ data.sizes.resolve(
+ data.axis,
+ data.automatic_size,
+ data.get_automatic_minimum_size,
+ data.stretch_size,
+ || get_content_size().into(),
+ data.is_table,
+ )
+ })
+ }
+}
+
+impl From<Au> for LazySize<'_> {
+ /// Creates a [`LazySize`] that will resolve to the given [`Au`],
+ /// ignoring the intrinsic size.
+ fn from(value: Au) -> Self {
+ let result = OnceCell::new();
+ result.set(value).unwrap();
+ LazySize { result, data: None }
+ }
+}