1mod layout;
5mod stylo_taffy;
6use std::fmt;
7
8use app_units::Au;
9use malloc_size_of_derive::MallocSizeOf;
10use script::layout_dom::ServoThreadSafeLayoutNode;
11use servo_arc::Arc;
12use style::context::SharedStyleContext;
13use style::properties::ComputedValues;
14use stylo_taffy::TaffyStyloStyle;
15
16use crate::PropagatedBoxTreeData;
17use crate::cell::ArcRefCell;
18use crate::construct_modern::{ModernContainerBuilder, ModernItemKind};
19use crate::context::LayoutContext;
20use crate::dom::LayoutBox;
21use crate::dom_traversal::{NodeAndStyleInfo, NonReplacedContents};
22use crate::formatting_contexts::IndependentFormattingContext;
23use crate::fragment_tree::Fragment;
24use crate::layout_box_base::LayoutBoxBase;
25use crate::positioned::{AbsolutelyPositionedBox, PositioningContext};
26
27#[derive(Debug, MallocSizeOf)]
28pub(crate) struct TaffyContainer {
29 children: Vec<ArcRefCell<TaffyItemBox>>,
30 style: Arc<ComputedValues>,
31}
32
33impl TaffyContainer {
34 pub fn construct(
35 context: &LayoutContext,
36 info: &NodeAndStyleInfo,
37 contents: NonReplacedContents,
38 propagated_data: PropagatedBoxTreeData,
39 ) -> Self {
40 let mut builder = ModernContainerBuilder::new(context, info, propagated_data);
41 contents.traverse(context, info, &mut builder);
42 let items = builder.finish();
43
44 let children = items
45 .into_iter()
46 .map(|item| {
47 let box_ = match item.kind {
48 ModernItemKind::InFlow(independent_formatting_context) => {
49 ArcRefCell::new(TaffyItemBox::new(TaffyItemBoxInner::InFlowBox(
50 independent_formatting_context,
51 )))
52 },
53 ModernItemKind::OutOfFlow(independent_formatting_context) => {
54 let abs_pos_box = ArcRefCell::new(AbsolutelyPositionedBox::new(
55 independent_formatting_context,
56 ));
57 ArcRefCell::new(TaffyItemBox::new(
58 TaffyItemBoxInner::OutOfFlowAbsolutelyPositionedBox(abs_pos_box),
59 ))
60 },
61 ModernItemKind::ReusedBox(layout_box) => match layout_box {
62 LayoutBox::TaffyItemBox(taffy_item_box) => taffy_item_box,
63 _ => unreachable!("Undamaged taffy level element should be associated with taffy level box"),
64 },
65 };
66
67 if let Some(box_slot) = item.box_slot {
68 box_slot.set(LayoutBox::TaffyItemBox(box_.clone()));
69 }
70
71 box_
72 })
73 .collect();
74
75 Self {
76 children,
77 style: info.style.clone(),
78 }
79 }
80
81 pub(crate) fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {
82 self.style = new_style.clone();
83 }
84}
85
86#[derive(MallocSizeOf)]
87pub(crate) struct TaffyItemBox {
88 pub(crate) taffy_layout: taffy::Layout,
89 pub(crate) child_fragments: Vec<Fragment>,
90 pub(crate) positioning_context: PositioningContext,
91 pub(crate) style: Arc<ComputedValues>,
92 pub(crate) taffy_level_box: TaffyItemBoxInner,
93}
94
95#[allow(clippy::large_enum_variant)]
96#[derive(Debug, MallocSizeOf)]
97pub(crate) enum TaffyItemBoxInner {
98 InFlowBox(IndependentFormattingContext),
99 OutOfFlowAbsolutelyPositionedBox(ArcRefCell<AbsolutelyPositionedBox>),
100}
101
102impl fmt::Debug for TaffyItemBox {
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 f.debug_struct("TaffyItemBox")
105 .field("taffy_layout", &self.taffy_layout)
106 .field("child_fragments", &self.child_fragments.len())
107 .field("style", &self.style)
108 .field("taffy_level_box", &self.taffy_level_box)
109 .finish()
110 }
111}
112
113impl TaffyItemBox {
114 fn new(inner: TaffyItemBoxInner) -> Self {
115 let style: Arc<ComputedValues> = match &inner {
116 TaffyItemBoxInner::InFlowBox(item) => item.style().clone(),
117 TaffyItemBoxInner::OutOfFlowAbsolutelyPositionedBox(absbox) => {
118 (*absbox).borrow().context.style().clone()
119 },
120 };
121
122 Self {
123 taffy_layout: Default::default(),
124 child_fragments: Vec::new(),
125 positioning_context: PositioningContext::default(),
126 style,
127 taffy_level_box: inner,
128 }
129 }
130
131 pub(crate) fn clear_fragment_layout_cache(&mut self) {
132 self.taffy_layout = Default::default();
133 self.positioning_context = PositioningContext::default();
134 match self.taffy_level_box {
135 TaffyItemBoxInner::InFlowBox(ref independent_formatting_context) => {
136 independent_formatting_context
137 .base
138 .clear_fragment_layout_cache()
139 },
140 TaffyItemBoxInner::OutOfFlowAbsolutelyPositionedBox(ref positioned_box) => {
141 positioned_box
142 .borrow()
143 .context
144 .base
145 .clear_fragment_layout_cache()
146 },
147 }
148 }
149
150 pub(crate) fn with_base<T>(&self, callback: impl FnOnce(&LayoutBoxBase) -> T) -> T {
151 match self.taffy_level_box {
152 TaffyItemBoxInner::InFlowBox(ref independent_formatting_context) => {
153 callback(&independent_formatting_context.base)
154 },
155 TaffyItemBoxInner::OutOfFlowAbsolutelyPositionedBox(ref positioned_box) => {
156 callback(&positioned_box.borrow().context.base)
157 },
158 }
159 }
160
161 pub(crate) fn with_base_mut<T>(&mut self, callback: impl Fn(&mut LayoutBoxBase) -> T) -> T {
162 match &mut self.taffy_level_box {
163 TaffyItemBoxInner::InFlowBox(independent_formatting_context) => {
164 callback(&mut independent_formatting_context.base)
165 },
166 TaffyItemBoxInner::OutOfFlowAbsolutelyPositionedBox(positioned_box) => {
167 callback(&mut positioned_box.borrow_mut().context.base)
168 },
169 }
170 }
171
172 pub(crate) fn repair_style(
173 &mut self,
174 context: &SharedStyleContext,
175 node: &ServoThreadSafeLayoutNode,
176 new_style: &Arc<ComputedValues>,
177 ) {
178 self.style = new_style.clone();
179 match &mut self.taffy_level_box {
180 TaffyItemBoxInner::InFlowBox(independent_formatting_context) => {
181 independent_formatting_context.repair_style(context, node, new_style)
182 },
183 TaffyItemBoxInner::OutOfFlowAbsolutelyPositionedBox(positioned_box) => positioned_box
184 .borrow_mut()
185 .context
186 .repair_style(context, node, new_style),
187 }
188 }
189
190 fn is_in_flow_replaced(&self) -> bool {
191 match &self.taffy_level_box {
192 TaffyItemBoxInner::InFlowBox(fc) => fc.is_replaced(),
193 TaffyItemBoxInner::OutOfFlowAbsolutelyPositionedBox(_) => false,
194 }
195 }
196}
197
198#[derive(Clone, Debug, MallocSizeOf)]
200pub(crate) struct SpecificTaffyGridInfo {
201 pub rows: SpecificTaffyGridTrackInfo,
202 pub columns: SpecificTaffyGridTrackInfo,
203}
204
205impl SpecificTaffyGridInfo {
206 fn from_detailed_grid_layout(grid_info: taffy::DetailedGridInfo) -> Self {
207 Self {
208 rows: SpecificTaffyGridTrackInfo {
209 sizes: grid_info
210 .rows
211 .sizes
212 .iter()
213 .map(|size| Au::from_f32_px(*size))
214 .collect(),
215 },
216 columns: SpecificTaffyGridTrackInfo {
217 sizes: grid_info
218 .columns
219 .sizes
220 .iter()
221 .map(|size| Au::from_f32_px(*size))
222 .collect(),
223 },
224 }
225 }
226}
227
228#[derive(Clone, Debug, MallocSizeOf)]
229pub(crate) struct SpecificTaffyGridTrackInfo {
230 pub sizes: Box<[Au]>,
231}