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 rect: PhysicalRect<Au>,
22    pub children: Vec<Fragment>,
23
24    /// The scrollable overflow of this anonymous fragment's children.
25    scrollable_overflow: Option<PhysicalRect<Au>>,
26
27    /// The style of the fragment.
28    pub style: ServoArc<ComputedValues>,
29
30    /// This [`PositioningFragment`]'s containing block rectangle in coordinates relative to
31    /// the initial containing block, but not taking into account any transforms.
32    pub cumulative_containing_block_rect: PhysicalRect<Au>,
33}
34
35impl PositioningFragment {
36    pub fn new_anonymous(
37        style: ServoArc<ComputedValues>,
38        rect: PhysicalRect<Au>,
39        children: Vec<Fragment>,
40    ) -> ArcRefCell<Self> {
41        Self::new_with_base_fragment(BaseFragment::anonymous(), style, rect, children)
42    }
43
44    pub fn new_empty(
45        base_fragment_info: BaseFragmentInfo,
46        rect: PhysicalRect<Au>,
47        style: ServoArc<ComputedValues>,
48    ) -> ArcRefCell<Self> {
49        Self::new_with_base_fragment(base_fragment_info.into(), style, rect, Vec::new())
50    }
51
52    fn new_with_base_fragment(
53        base: BaseFragment,
54        style: ServoArc<ComputedValues>,
55        rect: PhysicalRect<Au>,
56        children: Vec<Fragment>,
57    ) -> ArcRefCell<Self> {
58        ArcRefCell::new(PositioningFragment {
59            base,
60            style,
61            rect,
62            children,
63            scrollable_overflow: None,
64            cumulative_containing_block_rect: PhysicalRect::zero(),
65        })
66    }
67
68    pub(crate) fn set_containing_block(&mut self, containing_block: &PhysicalRect<Au>) {
69        self.cumulative_containing_block_rect = *containing_block;
70    }
71
72    pub fn offset_by_containing_block(&self, rect: &PhysicalRect<Au>) -> PhysicalRect<Au> {
73        rect.translate(self.cumulative_containing_block_rect.origin.to_vector())
74    }
75
76    pub(crate) fn calculate_scrollable_overflow(&mut self) {
77        self.scrollable_overflow = Some(self.children.iter().fold(
78            PhysicalRect::zero(),
79            |acc, child| {
80                acc.union(
81                    &child
82                        .calculate_scrollable_overflow_for_parent()
83                        .translate(self.rect.origin.to_vector()),
84                )
85            },
86        ));
87    }
88
89    pub(crate) fn scrollable_overflow_for_parent(&self) -> PhysicalRect<Au> {
90        self.scrollable_overflow.expect(
91            "Should only call `scrollable_overflow_for_parent()` after calculating overflow",
92        )
93    }
94
95    pub fn print(&self, tree: &mut PrintTree) {
96        tree.new_level(format!(
97            "PositioningFragment\
98                \nbase={:?}\
99                \nrect={:?}\
100                \nscrollable_overflow={:?}",
101            self.base, self.rect, self.scrollable_overflow
102        ));
103
104        for child in &self.children {
105            child.print(tree);
106        }
107        tree.end_level();
108    }
109}