layout/
layout_box_base.rs1use std::fmt::{Debug, Formatter};
6use std::sync::atomic::AtomicBool;
7
8use app_units::Au;
9use atomic_refcell::AtomicRefCell;
10use malloc_size_of_derive::MallocSizeOf;
11use servo_arc::Arc;
12use style::properties::ComputedValues;
13
14use crate::context::LayoutContext;
15use crate::dom::{LayoutBox, WeakLayoutBox};
16use crate::formatting_contexts::Baselines;
17use crate::fragment_tree::{BaseFragmentInfo, CollapsedBlockMargins, Fragment, SpecificLayoutInfo};
18use crate::positioned::PositioningContext;
19use crate::sizing::{ComputeInlineContentSizes, InlineContentSizesResult, SizeConstraint};
20use crate::{ConstraintSpace, ContainingBlockSize};
21
22#[derive(MallocSizeOf)]
29pub(crate) struct LayoutBoxBase {
30 pub base_fragment_info: BaseFragmentInfo,
31 pub style: Arc<ComputedValues>,
32 pub cached_inline_content_size:
33 AtomicRefCell<Option<Box<(SizeConstraint, InlineContentSizesResult)>>>,
34 pub outer_inline_content_sizes_depend_on_content: AtomicBool,
35 pub cached_layout_result: AtomicRefCell<Option<Box<CacheableLayoutResultAndInputs>>>,
36 pub fragments: AtomicRefCell<Vec<Fragment>>,
37 pub parent_box: Option<WeakLayoutBox>,
38}
39
40impl LayoutBoxBase {
41 pub(crate) fn new(base_fragment_info: BaseFragmentInfo, style: Arc<ComputedValues>) -> Self {
42 Self {
43 base_fragment_info,
44 style,
45 cached_inline_content_size: AtomicRefCell::default(),
46 outer_inline_content_sizes_depend_on_content: AtomicBool::new(true),
47 cached_layout_result: AtomicRefCell::default(),
48 fragments: AtomicRefCell::default(),
49 parent_box: None,
50 }
51 }
52
53 pub(crate) fn inline_content_sizes(
56 &self,
57 layout_context: &LayoutContext,
58 constraint_space: &ConstraintSpace,
59 layout_box: &impl ComputeInlineContentSizes,
60 ) -> InlineContentSizesResult {
61 let mut cache = self.cached_inline_content_size.borrow_mut();
62 if let Some(cached_inline_content_size) = cache.as_ref() {
63 let (previous_cb_block_size, result) = **cached_inline_content_size;
64 if !result.depends_on_block_constraints ||
65 previous_cb_block_size == constraint_space.block_size
66 {
67 return result;
68 }
69 }
71
72 let result =
73 layout_box.compute_inline_content_sizes_with_fixup(layout_context, constraint_space);
74 *cache = Some(Box::new((constraint_space.block_size, result)));
75 result
76 }
77
78 pub(crate) fn fragments(&self) -> Vec<Fragment> {
79 self.fragments.borrow().clone()
80 }
81
82 pub(crate) fn add_fragment(&self, fragment: Fragment) {
83 self.fragments.borrow_mut().push(fragment);
84 }
85
86 pub(crate) fn set_fragment(&self, fragment: Fragment) {
87 *self.fragments.borrow_mut() = vec![fragment];
88 }
89
90 pub(crate) fn clear_fragments(&self) {
91 self.fragments.borrow_mut().clear();
92 }
93
94 pub(crate) fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {
95 self.style = new_style.clone();
96 for fragment in self.fragments.borrow_mut().iter_mut() {
97 if let Some(mut base) = fragment.base_mut() {
98 base.repair_style(new_style);
99 }
100 }
101 }
102
103 #[expect(unused)]
104 pub(crate) fn parent_box(&self) -> Option<LayoutBox> {
105 self.parent_box.as_ref().and_then(WeakLayoutBox::upgrade)
106 }
107}
108
109impl Debug for LayoutBoxBase {
110 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
111 f.debug_struct("LayoutBoxBase").finish()
112 }
113}
114
115#[derive(Clone, MallocSizeOf)]
116pub(crate) struct CacheableLayoutResult {
117 pub fragments: Vec<Fragment>,
118
119 pub content_block_size: Au,
121
122 pub collapsible_margins_in_children: CollapsedBlockMargins,
125
126 pub content_inline_size_for_table: Option<Au>,
130
131 pub baselines: Baselines,
135
136 pub depends_on_block_constraints: bool,
138
139 pub specific_layout_info: Option<SpecificLayoutInfo>,
141}
142
143#[derive(MallocSizeOf)]
145pub(crate) struct CacheableLayoutResultAndInputs {
146 pub result: CacheableLayoutResult,
148
149 pub containing_block_for_children_size: ContainingBlockSize,
152
153 pub positioning_context: PositioningContext,
156}