layout/
layout_box_base.rs1use std::fmt::{Debug, Formatter};
6use std::sync::atomic::{AtomicBool, Ordering};
7
8use app_units::Au;
9use atomic_refcell::AtomicRefCell;
10use layout_api::LayoutDamage;
11use malloc_size_of_derive::MallocSizeOf;
12use servo_arc::Arc;
13use style::properties::ComputedValues;
14
15use crate::context::LayoutContext;
16use crate::dom::{LayoutBox, WeakLayoutBox};
17use crate::formatting_contexts::Baselines;
18use crate::fragment_tree::{BaseFragmentInfo, CollapsedBlockMargins, Fragment, SpecificLayoutInfo};
19use crate::positioned::PositioningContext;
20use crate::sizing::{ComputeInlineContentSizes, InlineContentSizesResult, SizeConstraint};
21use crate::{ConstraintSpace, ContainingBlockSize};
22
23#[derive(MallocSizeOf)]
30pub(crate) struct LayoutBoxBase {
31 pub base_fragment_info: BaseFragmentInfo,
32 pub style: Arc<ComputedValues>,
33 pub cached_inline_content_size:
34 AtomicRefCell<Option<Box<(SizeConstraint, InlineContentSizesResult)>>>,
35 pub outer_inline_content_sizes_depend_on_content: AtomicBool,
36 pub cached_layout_result: AtomicRefCell<Option<Box<CacheableLayoutResultAndInputs>>>,
37 pub fragments: AtomicRefCell<Vec<Fragment>>,
38 pub parent_box: Option<WeakLayoutBox>,
39}
40
41impl LayoutBoxBase {
42 pub(crate) fn new(base_fragment_info: BaseFragmentInfo, style: Arc<ComputedValues>) -> Self {
43 Self {
44 base_fragment_info,
45 style,
46 cached_inline_content_size: AtomicRefCell::default(),
47 outer_inline_content_sizes_depend_on_content: AtomicBool::new(true),
48 cached_layout_result: AtomicRefCell::default(),
49 fragments: AtomicRefCell::default(),
50 parent_box: None,
51 }
52 }
53
54 pub(crate) fn inline_content_sizes(
57 &self,
58 layout_context: &LayoutContext,
59 constraint_space: &ConstraintSpace,
60 layout_box: &impl ComputeInlineContentSizes,
61 ) -> InlineContentSizesResult {
62 let mut cache = self.cached_inline_content_size.borrow_mut();
63 if let Some(cached_inline_content_size) = cache.as_ref() {
64 let (previous_cb_block_size, result) = **cached_inline_content_size;
65 if !result.depends_on_block_constraints ||
66 previous_cb_block_size == constraint_space.block_size
67 {
68 return result;
69 }
70 }
72
73 let result =
74 layout_box.compute_inline_content_sizes_with_fixup(layout_context, constraint_space);
75 *cache = Some(Box::new((constraint_space.block_size, result)));
76 result
77 }
78
79 pub(crate) fn fragments(&self) -> Vec<Fragment> {
80 self.fragments.borrow().clone()
81 }
82
83 pub(crate) fn add_fragment(&self, fragment: Fragment) {
84 self.fragments.borrow_mut().push(fragment);
85 }
86
87 pub(crate) fn set_fragment(&self, fragment: Fragment) {
88 *self.fragments.borrow_mut() = vec![fragment];
89 }
90
91 pub(crate) fn clear_fragments(&self) {
92 self.fragments.borrow_mut().clear();
93 }
94
95 pub(crate) fn clear_fragments_and_fragment_cache(&self) {
96 self.fragments.borrow_mut().clear();
97 *self.cached_layout_result.borrow_mut() = None;
98 }
99
100 pub(crate) fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {
101 self.style = new_style.clone();
102 for fragment in self.fragments.borrow_mut().iter_mut() {
103 if let Some(mut base) = fragment.base_mut() {
104 base.repair_style(new_style);
105 }
106 }
107 }
108
109 #[expect(unused)]
110 pub(crate) fn parent_box(&self) -> Option<LayoutBox> {
111 self.parent_box.as_ref().and_then(WeakLayoutBox::upgrade)
112 }
113
114 pub(crate) fn add_damage(
115 &self,
116 element_damage: LayoutDamage,
117 damage_from_children: LayoutDamage,
118 ) -> LayoutDamage {
119 self.clear_fragments_and_fragment_cache();
120
121 if !element_damage.is_empty() ||
122 damage_from_children.contains(LayoutDamage::RECOMPUTE_INLINE_CONTENT_SIZES)
123 {
124 *self.cached_inline_content_size.borrow_mut() = None;
125 }
126
127 let mut damage_for_parent = element_damage | damage_from_children;
128
129 damage_for_parent.set(
140 LayoutDamage::RECOMPUTE_INLINE_CONTENT_SIZES,
141 !element_damage.is_empty() ||
142 (!self.base_fragment_info.is_anonymous() &&
143 self.outer_inline_content_sizes_depend_on_content
144 .load(Ordering::Relaxed)),
145 );
146
147 damage_for_parent
148 }
149}
150
151impl Debug for LayoutBoxBase {
152 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
153 f.debug_struct("LayoutBoxBase").finish()
154 }
155}
156
157#[derive(Clone, MallocSizeOf)]
158pub(crate) struct CacheableLayoutResult {
159 pub fragments: Vec<Fragment>,
160
161 pub content_block_size: Au,
163
164 pub collapsible_margins_in_children: CollapsedBlockMargins,
167
168 pub content_inline_size_for_table: Option<Au>,
172
173 pub baselines: Baselines,
177
178 pub depends_on_block_constraints: bool,
180
181 pub specific_layout_info: Option<SpecificLayoutInfo>,
183}
184
185#[derive(MallocSizeOf)]
187pub(crate) struct CacheableLayoutResultAndInputs {
188 pub result: CacheableLayoutResult,
190
191 pub containing_block_for_children_size: ContainingBlockSize,
194
195 pub positioning_context: PositioningContext,
198}