mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Instead of computing scrollable overflow while constructing the fragment tree, we will now do it later. In the future this will also allow to only recalculate the overflow without rebuilding the tree when transform properties change, but that's left for a follow-up. Stylo PR: https://github.com/servo/stylo/pull/194 Testing: One test is now passing (more investigation is needed), but otherwise this isn't expected to have any effect. Signed-off-by: Oriol Brufau <obrufau@igalia.com> Co-authored-by: Martin Robinson <mrobinson@igalia.com>
109 lines
3.6 KiB
Rust
109 lines
3.6 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
|
|
use app_units::Au;
|
|
use base::print_tree::PrintTree;
|
|
use malloc_size_of_derive::MallocSizeOf;
|
|
use servo_arc::Arc as ServoArc;
|
|
use style::properties::ComputedValues;
|
|
|
|
use super::{BaseFragment, BaseFragmentInfo, Fragment};
|
|
use crate::cell::ArcRefCell;
|
|
use crate::geom::PhysicalRect;
|
|
|
|
/// Can contain child fragments with relative coordinates, but does not contribute to painting
|
|
/// itself. [`PositioningFragment`]s may be completely anonymous, or just non-painting Fragments
|
|
/// generated by boxes.
|
|
#[derive(MallocSizeOf)]
|
|
pub(crate) struct PositioningFragment {
|
|
pub base: BaseFragment,
|
|
pub rect: PhysicalRect<Au>,
|
|
pub children: Vec<Fragment>,
|
|
|
|
/// The scrollable overflow of this anonymous fragment's children.
|
|
scrollable_overflow: Option<PhysicalRect<Au>>,
|
|
|
|
/// The style of the fragment.
|
|
pub style: ServoArc<ComputedValues>,
|
|
|
|
/// This [`PositioningFragment`]'s containing block rectangle in coordinates relative to
|
|
/// the initial containing block, but not taking into account any transforms.
|
|
pub cumulative_containing_block_rect: PhysicalRect<Au>,
|
|
}
|
|
|
|
impl PositioningFragment {
|
|
pub fn new_anonymous(
|
|
style: ServoArc<ComputedValues>,
|
|
rect: PhysicalRect<Au>,
|
|
children: Vec<Fragment>,
|
|
) -> ArcRefCell<Self> {
|
|
Self::new_with_base_fragment(BaseFragment::anonymous(), style, rect, children)
|
|
}
|
|
|
|
pub fn new_empty(
|
|
base_fragment_info: BaseFragmentInfo,
|
|
rect: PhysicalRect<Au>,
|
|
style: ServoArc<ComputedValues>,
|
|
) -> ArcRefCell<Self> {
|
|
Self::new_with_base_fragment(base_fragment_info.into(), style, rect, Vec::new())
|
|
}
|
|
|
|
fn new_with_base_fragment(
|
|
base: BaseFragment,
|
|
style: ServoArc<ComputedValues>,
|
|
rect: PhysicalRect<Au>,
|
|
children: Vec<Fragment>,
|
|
) -> ArcRefCell<Self> {
|
|
ArcRefCell::new(PositioningFragment {
|
|
base,
|
|
style,
|
|
rect,
|
|
children,
|
|
scrollable_overflow: None,
|
|
cumulative_containing_block_rect: PhysicalRect::zero(),
|
|
})
|
|
}
|
|
|
|
pub(crate) fn set_containing_block(&mut self, containing_block: &PhysicalRect<Au>) {
|
|
self.cumulative_containing_block_rect = *containing_block;
|
|
}
|
|
|
|
pub fn offset_by_containing_block(&self, rect: &PhysicalRect<Au>) -> PhysicalRect<Au> {
|
|
rect.translate(self.cumulative_containing_block_rect.origin.to_vector())
|
|
}
|
|
|
|
pub(crate) fn calculate_scrollable_overflow(&mut self) {
|
|
self.scrollable_overflow = Some(self.children.iter().fold(
|
|
PhysicalRect::zero(),
|
|
|acc, child| {
|
|
acc.union(
|
|
&child
|
|
.calculate_scrollable_overflow_for_parent()
|
|
.translate(self.rect.origin.to_vector()),
|
|
)
|
|
},
|
|
));
|
|
}
|
|
|
|
pub(crate) fn scrollable_overflow_for_parent(&self) -> PhysicalRect<Au> {
|
|
self.scrollable_overflow.expect(
|
|
"Should only call `scrollable_overflow_for_parent()` after calculating overflow",
|
|
)
|
|
}
|
|
|
|
pub fn print(&self, tree: &mut PrintTree) {
|
|
tree.new_level(format!(
|
|
"PositioningFragment\
|
|
\nbase={:?}\
|
|
\nrect={:?}\
|
|
\nscrollable_overflow={:?}",
|
|
self.base, self.rect, self.scrollable_overflow
|
|
));
|
|
|
|
for child in &self.children {
|
|
child.print(tree);
|
|
}
|
|
tree.end_level();
|
|
}
|
|
}
|