1use std::marker::PhantomData;
6
7use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
8use layout_api::{
9 GenericLayoutDataTrait, LayoutDataTrait, LayoutElement, LayoutElementType, LayoutNode,
10 LayoutNodeType as ScriptLayoutNodeType, NodeRenderingType, SVGElementData,
11};
12use malloc_size_of_derive::MallocSizeOf;
13use script::layout_dom::ServoLayoutNode;
14use servo_arc::Arc as ServoArc;
15use smallvec::SmallVec;
16use style::context::SharedStyleContext;
17use style::properties::ComputedValues;
18use style::selector_parser::PseudoElement;
19use style::values::specified::box_::DisplayOutside as StyloDisplayOutside;
20use web_atoms::{local_name, ns};
21
22use crate::cell::{ArcRefCell, WeakRefCell};
23use crate::context::LayoutContext;
24use crate::dom_traversal::{Contents, NodeAndStyleInfo};
25use crate::flexbox::FlexLevelBox;
26use crate::flow::inline::{InlineItem, SharedInlineStyles, WeakInlineItem};
27use crate::flow::{BlockLevelBox, BlockLevelCreator};
28use crate::fragment_tree::{Fragment, FragmentFlags};
29use crate::geom::PhysicalSize;
30use crate::layout_box_base::LayoutBoxBase;
31use crate::replaced::{CanvasInfo, IFrameInfo, ImageInfo, VideoInfo};
32use crate::style_ext::{
33 ComputedValuesExt, Display, DisplayGeneratingBox, DisplayLayoutInternal, DisplayOutside,
34};
35use crate::table::{TableLevelBox, WeakTableLevelBox};
36use crate::taffy::TaffyItemBox;
37
38#[derive(MallocSizeOf)]
39pub struct PseudoLayoutData {
40 pseudo: PseudoElement,
41 data: ArcRefCell<InnerDOMLayoutData>,
42}
43
44#[derive(Default, MallocSizeOf)]
46pub struct InnerDOMLayoutData {
47 pub(super) self_box: ArcRefCell<Option<LayoutBox>>,
48 pub(super) pseudo_boxes: SmallVec<[PseudoLayoutData; 2]>,
49}
50
51impl InnerDOMLayoutData {
52 fn pseudo_layout_data(
53 &self,
54 pseudo_element: PseudoElement,
55 ) -> Option<ArcRefCell<InnerDOMLayoutData>> {
56 for pseudo_layout_data in self.pseudo_boxes.iter() {
57 if pseudo_element == pseudo_layout_data.pseudo {
58 return Some(pseudo_layout_data.data.clone());
59 }
60 }
61 None
62 }
63
64 fn create_pseudo_layout_data(
65 &mut self,
66 pseudo_element: PseudoElement,
67 ) -> ArcRefCell<InnerDOMLayoutData> {
68 let data: ArcRefCell<InnerDOMLayoutData> = Default::default();
69 self.pseudo_boxes.push(PseudoLayoutData {
70 pseudo: pseudo_element,
71 data: data.clone(),
72 });
73 data
74 }
75
76 fn fragments(&self) -> Vec<Fragment> {
77 self.self_box
78 .borrow()
79 .as_ref()
80 .and_then(|layout_box| layout_box.with_base(LayoutBoxBase::fragments))
81 .unwrap_or_default()
82 }
83
84 fn repair_style(&self, node: &ServoLayoutNode, context: &SharedStyleContext) {
85 if let Some(layout_object) = &*self.self_box.borrow() {
86 layout_object.repair_style(context, node, &node.style(context));
87 }
88
89 for pseudo_layout_data in self.pseudo_boxes.iter() {
90 let Some(node_with_pseudo) = node.with_pseudo(pseudo_layout_data.pseudo) else {
91 continue;
92 };
93 pseudo_layout_data
94 .data
95 .borrow()
96 .repair_style(&node_with_pseudo, context);
97 }
98 }
99
100 fn with_layout_box_base(&self, callback: impl Fn(&LayoutBoxBase)) {
101 if let Some(data) = self.self_box.borrow().as_ref() {
102 data.with_base(callback);
103 }
104 }
105
106 fn with_layout_box_base_including_pseudos(&self, callback: impl Fn(&LayoutBoxBase)) {
107 self.with_layout_box_base(&callback);
108 for pseudo_layout_data in self.pseudo_boxes.iter() {
109 pseudo_layout_data
110 .data
111 .borrow()
112 .with_layout_box_base(&callback);
113 }
114 }
115}
116
117#[derive(Debug, MallocSizeOf)]
119pub(super) enum LayoutBox {
120 DisplayContents(SharedInlineStyles),
121 BlockLevel(ArcRefCell<BlockLevelBox>),
122 InlineLevel(InlineItem),
123 FlexLevel(ArcRefCell<FlexLevelBox>),
124 TableLevelBox(TableLevelBox),
125 TaffyItemBox(ArcRefCell<TaffyItemBox>),
126}
127
128impl LayoutBox {
129 pub(crate) fn with_base<T>(&self, callback: impl FnOnce(&LayoutBoxBase) -> T) -> Option<T> {
130 Some(match self {
131 LayoutBox::DisplayContents(..) => return None,
132 LayoutBox::BlockLevel(block_level_box) => block_level_box.borrow().with_base(callback),
133 LayoutBox::InlineLevel(inline_item) => inline_item.with_base(callback),
134 LayoutBox::FlexLevel(flex_level_box) => flex_level_box.borrow().with_base(callback),
135 LayoutBox::TaffyItemBox(taffy_item_box) => taffy_item_box.borrow().with_base(callback),
136 LayoutBox::TableLevelBox(table_box) => table_box.with_base(callback),
137 })
138 }
139
140 pub(crate) fn with_base_mut<T>(
141 &mut self,
142 callback: impl FnOnce(&mut LayoutBoxBase) -> T,
143 ) -> Option<T> {
144 Some(match self {
145 LayoutBox::DisplayContents(..) => return None,
146 LayoutBox::BlockLevel(block_level_box) => {
147 block_level_box.borrow_mut().with_base_mut(callback)
148 },
149 LayoutBox::InlineLevel(inline_item) => inline_item.with_base_mut(callback),
150 LayoutBox::FlexLevel(flex_level_box) => {
151 flex_level_box.borrow_mut().with_base_mut(callback)
152 },
153 LayoutBox::TaffyItemBox(taffy_item_box) => {
154 taffy_item_box.borrow_mut().with_base_mut(callback)
155 },
156 LayoutBox::TableLevelBox(table_box) => table_box.with_base_mut(callback),
157 })
158 }
159
160 fn repair_style(
161 &self,
162 context: &SharedStyleContext,
163 node: &ServoLayoutNode,
164 new_style: &ServoArc<ComputedValues>,
165 ) {
166 match self {
167 LayoutBox::DisplayContents(inline_shared_styles) => {
168 *inline_shared_styles.style.borrow_mut() = new_style.clone();
169 *inline_shared_styles.selected.borrow_mut() = node.selected_style(context);
170 },
171 LayoutBox::BlockLevel(block_level_box) => {
172 block_level_box
173 .borrow_mut()
174 .repair_style(context, node, new_style);
175 },
176 LayoutBox::InlineLevel(inline_item) => {
177 inline_item.repair_style(context, node, new_style);
178 },
179 LayoutBox::FlexLevel(flex_level_box) => flex_level_box
180 .borrow_mut()
181 .repair_style(context, node, new_style),
182 LayoutBox::TableLevelBox(table_level_box) => {
183 table_level_box.repair_style(context, node, new_style)
184 },
185 LayoutBox::TaffyItemBox(taffy_item_box) => taffy_item_box
186 .borrow_mut()
187 .repair_style(context, node, new_style),
188 }
189 }
190
191 fn attached_to_tree(&self, layout_box: WeakLayoutBox) {
192 match self {
193 Self::DisplayContents(_) => {
194 },
197 Self::BlockLevel(block_level_box) => {
198 block_level_box.borrow().attached_to_tree(layout_box)
199 },
200 Self::InlineLevel(inline_item) => inline_item.attached_to_tree(layout_box),
201 Self::FlexLevel(flex_level_box) => flex_level_box.borrow().attached_to_tree(layout_box),
202 Self::TableLevelBox(table_level_box) => table_level_box.attached_to_tree(layout_box),
203 Self::TaffyItemBox(taffy_item_box) => {
204 taffy_item_box.borrow().attached_to_tree(layout_box)
205 },
206 }
207 }
208
209 fn downgrade(&self) -> WeakLayoutBox {
210 match self {
211 Self::DisplayContents(inline_shared_styles) => {
212 WeakLayoutBox::DisplayContents(inline_shared_styles.clone())
213 },
214 Self::BlockLevel(block_level_box) => {
215 WeakLayoutBox::BlockLevel(block_level_box.downgrade())
216 },
217 Self::InlineLevel(inline_item) => WeakLayoutBox::InlineLevel(inline_item.downgrade()),
218 Self::FlexLevel(flex_level_box) => WeakLayoutBox::FlexLevel(flex_level_box.downgrade()),
219 Self::TableLevelBox(table_level_box) => {
220 WeakLayoutBox::TableLevelBox(table_level_box.downgrade())
221 },
222 Self::TaffyItemBox(taffy_item_box) => {
223 WeakLayoutBox::TaffyItemBox(taffy_item_box.downgrade())
224 },
225 }
226 }
227}
228
229#[derive(Clone, Debug, MallocSizeOf)]
230pub(super) enum WeakLayoutBox {
231 DisplayContents(SharedInlineStyles),
232 BlockLevel(WeakRefCell<BlockLevelBox>),
233 InlineLevel(WeakInlineItem),
234 FlexLevel(WeakRefCell<FlexLevelBox>),
235 TableLevelBox(WeakTableLevelBox),
236 TaffyItemBox(WeakRefCell<TaffyItemBox>),
237}
238
239impl WeakLayoutBox {
240 pub(crate) fn upgrade(&self) -> Option<LayoutBox> {
241 Some(match self {
242 Self::DisplayContents(inline_shared_styles) => {
243 LayoutBox::DisplayContents(inline_shared_styles.clone())
244 },
245 Self::BlockLevel(block_level_box) => LayoutBox::BlockLevel(block_level_box.upgrade()?),
246 Self::InlineLevel(inline_item) => LayoutBox::InlineLevel(inline_item.upgrade()?),
247 Self::FlexLevel(flex_level_box) => LayoutBox::FlexLevel(flex_level_box.upgrade()?),
248 Self::TableLevelBox(table_level_box) => {
249 LayoutBox::TableLevelBox(table_level_box.upgrade()?)
250 },
251 Self::TaffyItemBox(taffy_item_box) => {
252 LayoutBox::TaffyItemBox(taffy_item_box.upgrade()?)
253 },
254 })
255 }
256}
257
258#[derive(Default, MallocSizeOf)]
262pub struct DOMLayoutData(AtomicRefCell<InnerDOMLayoutData>);
263
264impl LayoutDataTrait for DOMLayoutData {}
266impl GenericLayoutDataTrait for DOMLayoutData {
267 fn as_any(&self) -> &dyn std::any::Any {
268 self
269 }
270}
271
272pub struct BoxSlot<'dom> {
273 pub(crate) slot: ArcRefCell<Option<LayoutBox>>,
274 pub(crate) marker: PhantomData<&'dom ()>,
275}
276
277impl From<ArcRefCell<Option<LayoutBox>>> for BoxSlot<'_> {
278 fn from(slot: ArcRefCell<Option<LayoutBox>>) -> Self {
279 Self {
280 slot,
281 marker: PhantomData,
282 }
283 }
284}
285
286impl BoxSlot<'_> {
288 pub(crate) fn set(self, layout_box: LayoutBox) {
289 layout_box.attached_to_tree(layout_box.downgrade());
290 *self.slot.borrow_mut() = Some(layout_box);
291 }
292
293 pub(crate) fn take_layout_box(&self) -> Option<LayoutBox> {
294 self.slot.borrow_mut().take()
295 }
296}
297
298impl Drop for BoxSlot<'_> {
299 fn drop(&mut self) {
300 if !std::thread::panicking() {
301 assert!(self.slot.borrow().is_some(), "failed to set a layout box");
302 }
303 }
304}
305
306pub(crate) trait NodeExt<'dom> {
307 fn as_image(&self) -> Option<(ImageInfo, PhysicalSize<f64>)>;
309 fn as_canvas(&self) -> Option<(CanvasInfo, PhysicalSize<f64>)>;
310 fn as_iframe(&self) -> Option<IFrameInfo>;
311 fn as_video(&self) -> Option<(VideoInfo, Option<PhysicalSize<f64>>)>;
312 fn as_svg(&self) -> Option<SVGElementData<'dom>>;
313 fn as_typeless_object_with_data_attribute(&self) -> Option<String>;
314
315 fn ensure_inner_layout_data(&self) -> AtomicRefMut<'dom, InnerDOMLayoutData>;
316 fn inner_layout_data(&self) -> Option<AtomicRef<'dom, InnerDOMLayoutData>>;
317 fn inner_layout_data_mut(&self) -> Option<AtomicRefMut<'dom, InnerDOMLayoutData>>;
318 fn box_slot(&self) -> BoxSlot<'dom>;
319
320 fn unset_all_boxes(&self);
322
323 fn rendering_type(&self) -> NodeRenderingType;
327
328 fn fragments_for_pseudo(&self, pseudo_element: Option<PseudoElement>) -> Vec<Fragment>;
329 fn with_layout_box_base_including_pseudos(&self, callback: impl Fn(&LayoutBoxBase));
330
331 fn repair_style(&self, context: &SharedStyleContext);
332
333 fn isolates_damage_for_damage_propagation(&self) -> bool;
344
345 fn rebuild_box_tree_from_independent_formatting_context(
352 &self,
353 layout_context: &LayoutContext,
354 ) -> bool;
355}
356
357impl<'dom> NodeExt<'dom> for ServoLayoutNode<'dom> {
358 fn as_image(&self) -> Option<(ImageInfo, PhysicalSize<f64>)> {
359 let (resource, metadata) = self.image_data()?;
360 let width = metadata.map(|metadata| metadata.width).unwrap_or_default();
361 let height = metadata.map(|metadata| metadata.height).unwrap_or_default();
362 let (mut width, mut height) = (width as f64, height as f64);
363 if let Some(density) = self.image_density().filter(|density| *density != 1.) {
365 width /= density;
366 height /= density;
367 }
368 Some((
369 ImageInfo {
370 image: resource,
371 showing_broken_image_icon: self.showing_broken_image_icon(),
372 url: self.image_url(),
373 },
374 PhysicalSize::new(width, height),
375 ))
376 }
377
378 fn as_svg(&self) -> Option<SVGElementData<'dom>> {
379 self.svg_data()
380 }
381
382 fn as_video(&self) -> Option<(VideoInfo, Option<PhysicalSize<f64>>)> {
383 let data = self.media_data()?;
384 let natural_size = if let Some(frame) = data.current_frame {
385 Some(PhysicalSize::new(frame.width.into(), frame.height.into()))
386 } else {
387 data.metadata
388 .map(|meta| PhysicalSize::new(meta.width.into(), meta.height.into()))
389 };
390 Some((
391 VideoInfo {
392 image_key: data.current_frame.map(|frame| frame.image_key),
393 },
394 natural_size,
395 ))
396 }
397
398 fn as_canvas(&self) -> Option<(CanvasInfo, PhysicalSize<f64>)> {
399 let canvas_data = self.canvas_data()?;
400 let source = canvas_data.image_key;
401 Some((
402 CanvasInfo { source },
403 PhysicalSize::new(canvas_data.width.into(), canvas_data.height.into()),
404 ))
405 }
406
407 fn as_iframe(&self) -> Option<IFrameInfo> {
408 match (self.iframe_pipeline_id(), self.iframe_browsing_context_id()) {
409 (Some(pipeline_id), Some(browsing_context_id)) => Some(IFrameInfo {
410 pipeline_id,
411 browsing_context_id,
412 }),
413 _ => None,
414 }
415 }
416
417 fn as_typeless_object_with_data_attribute(&self) -> Option<String> {
418 if self.type_id() !=
419 Some(ScriptLayoutNodeType::Element(
420 LayoutElementType::HTMLObjectElement,
421 ))
422 {
423 return None;
424 }
425
426 let element = self.as_element()?;
430 if element.attribute(&ns!(), &local_name!("type")).is_some() {
431 return None;
432 }
433 element
434 .attribute_as_str(&ns!(), &local_name!("data"))
435 .map(|string| string.to_owned())
436 }
437
438 fn ensure_inner_layout_data(&self) -> AtomicRefMut<'dom, InnerDOMLayoutData> {
439 if self.layout_data().is_none() {
440 self.initialize_layout_data::<DOMLayoutData>();
441 }
442 self.layout_data()
443 .unwrap()
444 .as_any()
445 .downcast_ref::<DOMLayoutData>()
446 .unwrap()
447 .0
448 .borrow_mut()
449 }
450
451 fn inner_layout_data(&self) -> Option<AtomicRef<'dom, InnerDOMLayoutData>> {
452 self.layout_data().map(|data| {
453 data.as_any()
454 .downcast_ref::<DOMLayoutData>()
455 .unwrap()
456 .0
457 .borrow()
458 })
459 }
460
461 fn inner_layout_data_mut(&self) -> Option<AtomicRefMut<'dom, InnerDOMLayoutData>> {
462 self.layout_data().map(|data| {
463 data.as_any()
464 .downcast_ref::<DOMLayoutData>()
465 .unwrap()
466 .0
467 .borrow_mut()
468 })
469 }
470
471 fn box_slot(&self) -> BoxSlot<'dom> {
472 let pseudo_element_chain = self.pseudo_element_chain();
473 let Some(primary) = pseudo_element_chain.primary else {
474 return self.ensure_inner_layout_data().self_box.clone().into();
475 };
476
477 let Some(secondary) = pseudo_element_chain.secondary else {
478 let primary_layout_data = self
479 .ensure_inner_layout_data()
480 .create_pseudo_layout_data(primary);
481 return primary_layout_data.borrow().self_box.clone().into();
482 };
483
484 let primary_layout_data = self
491 .inner_layout_data()
492 .expect("Should already have element InnerLayoutData here.")
493 .pseudo_layout_data(primary)
494 .expect("Should already have primary pseudo-element InnerLayoutData here");
495 let secondary_layout_data = primary_layout_data
496 .borrow_mut()
497 .create_pseudo_layout_data(secondary);
498 secondary_layout_data.borrow().self_box.clone().into()
499 }
500
501 fn unset_all_boxes(&self) {
502 let mut layout_data = self.ensure_inner_layout_data();
503 *layout_data.self_box.borrow_mut() = None;
504 layout_data.pseudo_boxes.clear();
505
506 }
509
510 fn rendering_type(&self) -> NodeRenderingType {
511 let Some(layout_data) = self.inner_layout_data() else {
512 return NodeRenderingType::NotRendered;
513 };
514 match &*layout_data.self_box.borrow() {
515 Some(LayoutBox::DisplayContents(..)) => NodeRenderingType::DelegatesRendering,
516 Some(..) => NodeRenderingType::Rendered,
517 None => NodeRenderingType::NotRendered,
518 }
519 }
520
521 fn with_layout_box_base_including_pseudos(&self, callback: impl Fn(&LayoutBoxBase)) {
522 if let Some(inner_layout_data) = self.inner_layout_data() {
523 inner_layout_data.with_layout_box_base_including_pseudos(callback);
524 }
525 }
526
527 fn fragments_for_pseudo(&self, pseudo_element: Option<PseudoElement>) -> Vec<Fragment> {
528 let Some(layout_data) = self.inner_layout_data() else {
529 return vec![];
530 };
531 match pseudo_element {
532 Some(pseudo_element) => layout_data
533 .pseudo_layout_data(pseudo_element)
534 .map(|pseudo_layout_data| pseudo_layout_data.borrow().fragments())
535 .unwrap_or_default(),
536 None => layout_data.fragments(),
537 }
538 }
539
540 fn repair_style(&self, context: &SharedStyleContext) {
541 if let Some(layout_data) = self.inner_layout_data() {
542 layout_data.repair_style(self, context);
543 }
544 }
545
546 fn isolates_damage_for_damage_propagation(&self) -> bool {
547 if self.as_element().is_some_and(|element| {
551 element.is_body_element_of_html_element_root() || element.is_root()
552 }) {
553 return false;
554 }
555
556 let Some(inner_layout_data) = self.inner_layout_data() else {
557 return false;
558 };
559 let self_box = inner_layout_data.self_box.borrow();
560 let Some(self_box) = &*self_box else {
561 return false;
562 };
563
564 match self_box {
565 LayoutBox::DisplayContents(..) => false,
566 LayoutBox::BlockLevel(block_level) => matches!(
567 &*block_level.borrow(),
568 BlockLevelBox::Independent(..) |
569 BlockLevelBox::OutOfFlowFloatBox(..) |
570 BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(..)
571 ),
572 LayoutBox::InlineLevel(inline_level) => matches!(
573 inline_level,
574 InlineItem::OutOfFlowAbsolutelyPositionedBox(..) | InlineItem::Atomic(..)
575 ),
576 LayoutBox::FlexLevel(..) => true,
577 LayoutBox::TableLevelBox(table_level_box) => matches!(
578 table_level_box,
579 TableLevelBox::Cell(..) | TableLevelBox::Caption(..),
580 ),
581 LayoutBox::TaffyItemBox(..) => true,
582 }
583 }
584
585 fn rebuild_box_tree_from_independent_formatting_context(
586 &self,
587 layout_context: &LayoutContext,
588 ) -> bool {
589 if self.as_element().is_some_and(|element| {
593 element.is_body_element_of_html_element_root() || element.is_root()
594 }) {
595 return false;
596 }
597
598 let layout_box = {
599 let Some(mut inner_layout_data) = self.inner_layout_data_mut() else {
600 return false;
601 };
602 inner_layout_data.pseudo_boxes.clear();
603 inner_layout_data.self_box.clone()
604 };
605
606 let layout_box = layout_box.borrow();
607 let Some(layout_box) = &*layout_box else {
608 return false;
609 };
610
611 let info = NodeAndStyleInfo::new(*self, self.style(&layout_context.style_context));
612 let box_style = info.style.get_box();
613 let Display::GeneratingBox(display) = box_style.display.into() else {
614 return false;
615 };
616 let contents = || {
617 assert!(
618 self.pseudo_element_chain().is_empty(),
619 "Shouldn't try to rebuild box tree from a pseudo-element"
620 );
621 Contents::for_element(info.node, layout_context)
622 };
623 match layout_box {
624 LayoutBox::DisplayContents(..) => false,
625 LayoutBox::BlockLevel(block_level) => {
626 let mut block_level = block_level.borrow_mut();
627 match &mut *block_level {
628 BlockLevelBox::Independent(independent_formatting_context) => {
629 let DisplayGeneratingBox::OutsideInside {
630 outside: DisplayOutside::Block,
631 inside: display_inside,
632 } = display
633 else {
634 return false;
635 };
636 if !matches!(
637 BlockLevelCreator::new_for_inflow_block_level_element(
638 &info,
639 display_inside,
640 contents(),
641 independent_formatting_context.propagated_data,
642 ),
643 BlockLevelCreator::Independent { .. }
644 ) {
645 return false;
646 }
647 independent_formatting_context.rebuild(layout_context, &info);
648 true
649 },
650 BlockLevelBox::OutOfFlowFloatBox(float_box) => {
651 if !info.style.clone_float().is_floating() {
652 return false;
653 }
654 float_box.contents.rebuild(layout_context, &info);
655 true
656 },
657 BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(positioned_box) => {
658 if !info.style.clone_position().is_absolutely_positioned() ||
663 box_style.original_display.outside() != StyloDisplayOutside::Block
664 {
665 return false;
666 }
667 positioned_box
668 .borrow_mut()
669 .context
670 .rebuild(layout_context, &info);
671 true
672 },
673 _ => false,
674 }
675 },
676 LayoutBox::InlineLevel(inline_level) => match inline_level {
677 InlineItem::OutOfFlowAbsolutelyPositionedBox(positioned_box, ..) => {
678 if !info.style.clone_position().is_absolutely_positioned() {
679 return false;
680 }
681 positioned_box
682 .borrow_mut()
683 .context
684 .rebuild(layout_context, &info);
685 true
686 },
687 InlineItem::Atomic(atomic_box, _, _) => {
688 let flags = match contents() {
689 Contents::NonReplaced(_) => FragmentFlags::empty(),
690 Contents::Replaced(_) => FragmentFlags::IS_REPLACED,
691 Contents::Widget(_) => FragmentFlags::IS_WIDGET,
692 };
693 if !info.style.is_atomic_inline_level(flags) {
694 return false;
695 }
696 atomic_box.borrow_mut().rebuild(layout_context, &info);
697 true
698 },
699 _ => false,
700 },
701 LayoutBox::FlexLevel(flex_level_box) => {
702 let mut flex_level_box = flex_level_box.borrow_mut();
703 match &mut *flex_level_box {
704 FlexLevelBox::FlexItem(flex_item_box) => {
705 if info.style.clone_position().is_absolutely_positioned() ||
706 flex_item_box.style().clone_order() != info.style.clone_order()
707 {
708 return false;
709 }
710 flex_item_box
711 .independent_formatting_context
712 .rebuild(layout_context, &info)
713 },
714 FlexLevelBox::OutOfFlowAbsolutelyPositionedBox(positioned_box) => {
715 if !info.style.clone_position().is_absolutely_positioned() {
716 return false;
717 }
718 positioned_box
719 .borrow_mut()
720 .context
721 .rebuild(layout_context, &info);
722 },
723 }
724 true
725 },
726 LayoutBox::TableLevelBox(table_level_box) => match table_level_box {
727 TableLevelBox::Caption(caption) => {
728 if display !=
729 DisplayGeneratingBox::LayoutInternal(DisplayLayoutInternal::TableCaption)
730 {
731 return false;
732 }
733 caption.borrow_mut().context.rebuild(layout_context, &info);
734 true
735 },
736 TableLevelBox::Cell(table_cell) => {
737 if display !=
738 DisplayGeneratingBox::LayoutInternal(DisplayLayoutInternal::TableCell)
739 {
740 return false;
741 }
742 table_cell
743 .borrow_mut()
744 .context
745 .rebuild(layout_context, &info);
746 true
747 },
748 _ => false,
749 },
750 LayoutBox::TaffyItemBox(..) => false,
751 }
752 }
753}