layout: Add LayoutBoxBase and use it for IndependentFormattingContext (#34507)

Add a new struct `LayoutBoxBase`, that will be used throughout the box
tree. The idea of this struct is that we have a place to consistently
store common layout information (style and node information) and also to
cache layout results such as content sizes (inline and maybe later box
sizes) and eventually layout results.

In addition to the addition of this struct,
`IndependentFormattingContext` is flattened slightly so that it directly
holds the contents of both replaced and non-replaced elements.

This is only added to independent formatting contexts, but will later be
added to all block containers as well.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Martin Robinson 2024-12-07 20:12:25 +01:00 committed by GitHub
parent 97e9841d47
commit 264c0f972f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 425 additions and 441 deletions

View file

@ -0,0 +1,61 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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 atomic_refcell::AtomicRefCell;
use serde::Serialize;
use servo_arc::Arc;
use style::properties::ComputedValues;
use crate::fragment_tree::BaseFragmentInfo;
use crate::geom::SizeConstraint;
use crate::sizing::InlineContentSizesResult;
use crate::ConstraintSpace;
/// A box tree node that handles containing information about style and the original DOM
/// node or pseudo-element that it is based on. This also handles caching of layout values
/// such as the inline content sizes to avoid recalculating these values during layout
/// passes.
///
/// In the future, this will hold layout results to support incremental layout.
#[derive(Debug, Serialize)]
pub(crate) struct LayoutBoxBase {
pub base_fragment_info: BaseFragmentInfo,
#[serde(skip_serializing)]
pub style: Arc<ComputedValues>,
#[serde(skip_serializing)]
pub cached_inline_content_size:
AtomicRefCell<Option<(SizeConstraint, InlineContentSizesResult)>>,
}
impl LayoutBoxBase {
pub(crate) fn new(base_fragment_info: BaseFragmentInfo, style: Arc<ComputedValues>) -> Self {
Self {
base_fragment_info,
style,
cached_inline_content_size: AtomicRefCell::default(),
}
}
/// Get the inline content sizes of a box tree node that extends this [`LayoutBoxBase`], fetch
/// the result from a cache when possible.
pub(crate) fn inline_content_sizes(
&self,
constraint_space: &ConstraintSpace,
inline_content_sizes_fn: impl FnOnce() -> InlineContentSizesResult,
) -> InlineContentSizesResult {
let mut cache = self.cached_inline_content_size.borrow_mut();
if let Some((previous_cb_block_size, result)) = *cache {
if !result.depends_on_block_constraints ||
previous_cb_block_size == constraint_space.block_size
{
return result;
}
// TODO: Should we keep multiple caches for various block sizes?
}
let result = inline_content_sizes_fn();
*cache = Some((constraint_space.block_size, result));
result
}
}