layout/fragment_tree/
positioning_fragment.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use app_units::Au;
6use base::print_tree::PrintTree;
7use malloc_size_of_derive::MallocSizeOf;
8use servo_arc::Arc as ServoArc;
9use style::properties::ComputedValues;
10
11use super::{BaseFragment, BaseFragmentInfo, Fragment};
12use crate::cell::ArcRefCell;
13use crate::geom::PhysicalRect;
14
15/// Can contain child fragments with relative coordinates, but does not contribute to painting
16/// itself. [`PositioningFragment`]s may be completely anonymous, or just non-painting Fragments
17/// generated by boxes.
18#[derive(MallocSizeOf)]
19pub(crate) struct PositioningFragment {
20    pub base: BaseFragment,
21    pub children: Vec<Fragment>,
22
23    /// The scrollable overflow of this anonymous fragment's children.
24    scrollable_overflow: Option<PhysicalRect<Au>>,
25
26    /// This [`PositioningFragment`]'s containing block rectangle in coordinates relative to
27    /// the initial containing block, but not taking into account any transforms.
28    pub cumulative_containing_block_rect: PhysicalRect<Au>,
29}
30
31impl PositioningFragment {
32    pub fn new_anonymous(
33        style: ServoArc<ComputedValues>,
34        rect: PhysicalRect<Au>,
35        children: Vec<Fragment>,
36    ) -> ArcRefCell<Self> {
37        Self::new_with_base_fragment_info(BaseFragmentInfo::anonymous(), style, rect, children)
38    }
39
40    pub fn new_empty(
41        base_fragment_info: BaseFragmentInfo,
42        rect: PhysicalRect<Au>,
43        style: ServoArc<ComputedValues>,
44    ) -> ArcRefCell<Self> {
45        Self::new_with_base_fragment_info(base_fragment_info, style, rect, Vec::new())
46    }
47
48    fn new_with_base_fragment_info(
49        base_fragment_info: BaseFragmentInfo,
50        style: ServoArc<ComputedValues>,
51        rect: PhysicalRect<Au>,
52        children: Vec<Fragment>,
53    ) -> ArcRefCell<Self> {
54        ArcRefCell::new(PositioningFragment {
55            base: BaseFragment::new(base_fragment_info, style.into(), rect),
56            children,
57            scrollable_overflow: None,
58            cumulative_containing_block_rect: PhysicalRect::zero(),
59        })
60    }
61
62    pub(crate) fn set_containing_block(&mut self, containing_block: &PhysicalRect<Au>) {
63        self.cumulative_containing_block_rect = *containing_block;
64    }
65
66    pub fn offset_by_containing_block(&self, rect: &PhysicalRect<Au>) -> PhysicalRect<Au> {
67        rect.translate(self.cumulative_containing_block_rect.origin.to_vector())
68    }
69
70    pub(crate) fn calculate_scrollable_overflow(&mut self) {
71        self.scrollable_overflow = Some(self.children.iter().fold(
72            PhysicalRect::zero(),
73            |acc, child| {
74                acc.union(
75                    &child
76                        .calculate_scrollable_overflow_for_parent()
77                        .translate(self.base.rect.origin.to_vector()),
78                )
79            },
80        ));
81    }
82
83    pub(crate) fn scrollable_overflow_for_parent(&self) -> PhysicalRect<Au> {
84        self.scrollable_overflow.expect(
85            "Should only call `scrollable_overflow_for_parent()` after calculating overflow",
86        )
87    }
88
89    pub fn print(&self, tree: &mut PrintTree) {
90        tree.new_level(format!(
91            "PositioningFragment\
92                \nbase={:?}\
93                \nrect={:?}\
94                \nscrollable_overflow={:?}",
95            self.base, self.base.rect, self.scrollable_overflow
96        ));
97
98        for child in &self.children {
99            child.print(tree);
100        }
101        tree.end_level();
102    }
103}