layout/fragment_tree/
positioning_fragment.rs1use std::sync::Arc;
6
7use app_units::Au;
8use atomic_refcell::AtomicRefCell;
9use malloc_size_of_derive::MallocSizeOf;
10use servo_arc::Arc as ServoArc;
11use servo_base::print_tree::PrintTree;
12use style::properties::ComputedValues;
13
14use super::{BaseFragment, BaseFragmentInfo, Fragment};
15use crate::fragment_tree::ContainingBlockCalculation;
16use crate::geom::PhysicalRect;
17
18#[derive(MallocSizeOf)]
22pub(crate) struct PositioningFragment {
23 pub base: BaseFragment,
24 pub children: Vec<Fragment>,
25
26 scrollable_overflow: AtomicRefCell<Option<PhysicalRect<Au>>>,
28
29 pub cumulative_containing_block_rect: AtomicRefCell<PhysicalRect<Au>>,
32}
33
34impl PositioningFragment {
35 pub fn new_anonymous(
36 style: ServoArc<ComputedValues>,
37 rect: PhysicalRect<Au>,
38 children: Vec<Fragment>,
39 ) -> Arc<Self> {
40 Self::new_with_base_fragment_info(BaseFragmentInfo::anonymous(), style, rect, children)
41 }
42
43 pub fn new_empty(
44 base_fragment_info: BaseFragmentInfo,
45 rect: PhysicalRect<Au>,
46 style: ServoArc<ComputedValues>,
47 ) -> Arc<Self> {
48 Self::new_with_base_fragment_info(base_fragment_info, style, rect, Vec::new())
49 }
50
51 fn new_with_base_fragment_info(
52 base_fragment_info: BaseFragmentInfo,
53 style: ServoArc<ComputedValues>,
54 rect: PhysicalRect<Au>,
55 children: Vec<Fragment>,
56 ) -> Arc<Self> {
57 Arc::new(Self {
58 base: BaseFragment::new(base_fragment_info, style.into(), rect),
59 children,
60 scrollable_overflow: Default::default(),
61 cumulative_containing_block_rect: Default::default(),
62 })
63 }
64
65 pub(crate) fn set_containing_block(&self, containing_block: &PhysicalRect<Au>) {
66 *self.cumulative_containing_block_rect.borrow_mut() = *containing_block;
67 }
68
69 pub fn offset_by_containing_block(
70 &self,
71 rect: &PhysicalRect<Au>,
72 containing_block_computation: ContainingBlockCalculation<'_>,
73 ) -> PhysicalRect<Au> {
74 containing_block_computation.ensure();
75 rect.translate(
76 self.cumulative_containing_block_rect
77 .borrow()
78 .origin
79 .to_vector(),
80 )
81 }
82
83 pub(crate) fn scrollable_overflow_for_parent(&self) -> PhysicalRect<Au> {
87 *self
88 .scrollable_overflow
89 .borrow_mut()
90 .get_or_insert_with(|| self.calculate_scrollable_overflow())
91 }
92
93 pub(crate) fn clear_scrollable_overflow(&self) {
97 *self.scrollable_overflow.borrow_mut() = None;
98 }
99
100 fn calculate_scrollable_overflow(&self) -> PhysicalRect<Au> {
101 self.children
102 .iter()
103 .fold(PhysicalRect::zero(), |acc, child| {
104 acc.union(
105 &child
106 .scrollable_overflow_for_parent()
107 .translate(self.base.rect().origin.to_vector()),
108 )
109 })
110 }
111
112 pub fn print(&self, tree: &mut PrintTree) {
113 tree.new_level(format!(
114 "PositioningFragment\
115 \nbase={:?}\
116 \nrect={:?}\
117 \nscrollable_overflow={:?}",
118 self.base,
119 self.base.rect(),
120 self.scrollable_overflow
121 ));
122
123 for child in &self.children {
124 child.print(tree);
125 }
126 tree.end_level();
127 }
128}