aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout/fragment_tree
diff options
context:
space:
mode:
Diffstat (limited to 'components/layout/fragment_tree')
-rw-r--r--components/layout/fragment_tree/box_fragment.rs44
-rw-r--r--components/layout/fragment_tree/fragment.rs23
-rw-r--r--components/layout/fragment_tree/fragment_tree.rs43
-rw-r--r--components/layout/fragment_tree/positioning_fragment.rs31
4 files changed, 100 insertions, 41 deletions
diff --git a/components/layout/fragment_tree/box_fragment.rs b/components/layout/fragment_tree/box_fragment.rs
index b7c3a2a3524..eb63038b7d7 100644
--- a/components/layout/fragment_tree/box_fragment.rs
+++ b/components/layout/fragment_tree/box_fragment.rs
@@ -89,7 +89,7 @@ pub(crate) struct BoxFragment {
block_margins_collapsed_with_children: Option<Box<CollapsedBlockMargins>>,
/// The scrollable overflow of this box fragment.
- pub scrollable_overflow_from_children: PhysicalRect<Au>,
+ scrollable_overflow: Option<PhysicalRect<Au>>,
/// The resolved box insets if this box is `position: sticky`. These are calculated
/// during `StackingContextTree` construction because they rely on the size of the
@@ -114,11 +114,6 @@ impl BoxFragment {
margin: PhysicalSides<Au>,
clearance: Option<Au>,
) -> BoxFragment {
- let scrollable_overflow_from_children =
- children.iter().fold(PhysicalRect::zero(), |acc, child| {
- acc.union(&child.scrollable_overflow_for_parent())
- });
-
BoxFragment {
base: base_fragment_info.into(),
style,
@@ -131,7 +126,7 @@ impl BoxFragment {
clearance,
baselines: Baselines::default(),
block_margins_collapsed_with_children: None,
- scrollable_overflow_from_children,
+ scrollable_overflow: None,
resolved_sticky_insets: AtomicRefCell::default(),
background_mode: BackgroundMode::Normal,
specific_layout_info: None,
@@ -203,13 +198,23 @@ impl BoxFragment {
/// Get the scrollable overflow for this [`BoxFragment`] relative to its
/// containing block.
pub fn scrollable_overflow(&self) -> PhysicalRect<Au> {
+ self.scrollable_overflow
+ .expect("Should only call `scrollable_overflow()` after calculating overflow")
+ }
+
+ pub(crate) fn calculate_scrollable_overflow(&mut self) {
+ let scrollable_overflow_from_children = self
+ .children
+ .iter()
+ .fold(PhysicalRect::zero(), |acc, child| {
+ acc.union(&child.calculate_scrollable_overflow_for_parent())
+ });
let physical_padding_rect = self.padding_rect();
let content_origin = self.content_rect.origin.to_vector();
- physical_padding_rect.union(
- &self
- .scrollable_overflow_from_children
- .translate(content_origin),
- )
+ self.scrollable_overflow = Some(
+ physical_padding_rect
+ .union(&scrollable_overflow_from_children.translate(content_origin)),
+ );
}
pub(crate) fn set_containing_block(&mut self, containing_block: &PhysicalRect<Au>) {
@@ -275,7 +280,12 @@ impl BoxFragment {
tree.end_level();
}
- pub fn scrollable_overflow_for_parent(&self) -> PhysicalRect<Au> {
+ pub(crate) fn scrollable_overflow_for_parent(&self) -> PhysicalRect<Au> {
+ // TODO: Properly handle absolutely positioned fragments.
+ if self.style.get_box().position.is_absolutely_positioned() {
+ return PhysicalRect::zero();
+ }
+
let mut overflow = self.border_rect();
if !self.style.establishes_scroll_container(self.base.flags) {
// https://www.w3.org/TR/css-overflow-3/#scrollable
@@ -328,7 +338,7 @@ impl BoxFragment {
///
/// Return the clipped the scrollable overflow based on its scroll origin, determined by overflow direction.
/// For an element, the clip rect is the padding rect and for viewport, it is the initial containing block.
- pub fn clip_unreachable_scrollable_overflow_region(
+ pub(crate) fn clip_unreachable_scrollable_overflow_region(
&self,
scrollable_overflow: PhysicalRect<Au>,
clipping_rect: PhysicalRect<Au>,
@@ -362,7 +372,7 @@ impl BoxFragment {
///
/// Return the clipped the scrollable overflow based on its scroll origin, determined by overflow direction.
/// This will coincides with the scrollport if the fragment is a scroll container.
- pub fn reachable_scrollable_overflow_region(&self) -> PhysicalRect<Au> {
+ pub(crate) fn reachable_scrollable_overflow_region(&self) -> PhysicalRect<Au> {
self.clip_unreachable_scrollable_overflow_region(
self.scrollable_overflow(),
self.padding_rect(),
@@ -421,9 +431,7 @@ impl BoxFragment {
return convert_to_au_or_auto(PhysicalSides::new(top, right, bottom, left));
}
- debug_assert!(
- position == ComputedPosition::Fixed || position == ComputedPosition::Absolute
- );
+ debug_assert!(position.is_absolutely_positioned());
let margin_rect = self.margin_rect();
let (top, bottom) = match (&insets.top, &insets.bottom) {
diff --git a/components/layout/fragment_tree/fragment.rs b/components/layout/fragment_tree/fragment.rs
index c81fd59e36b..10338c78743 100644
--- a/components/layout/fragment_tree/fragment.rs
+++ b/components/layout/fragment_tree/fragment.rs
@@ -183,19 +183,36 @@ impl Fragment {
}
}
- pub fn scrollable_overflow_for_parent(&self) -> PhysicalRect<Au> {
+ pub(crate) fn scrollable_overflow_for_parent(&self) -> PhysicalRect<Au> {
match self {
Fragment::Box(fragment) | Fragment::Float(fragment) => {
- fragment.borrow().scrollable_overflow_for_parent()
+ return fragment.borrow().scrollable_overflow_for_parent();
},
Fragment::AbsoluteOrFixedPositioned(_) => PhysicalRect::zero(),
- Fragment::Positioning(fragment) => fragment.borrow().scrollable_overflow,
+ Fragment::Positioning(fragment) => fragment.borrow().scrollable_overflow_for_parent(),
Fragment::Text(fragment) => fragment.borrow().rect,
Fragment::Image(fragment) => fragment.borrow().rect,
Fragment::IFrame(fragment) => fragment.borrow().rect,
}
}
+ pub(crate) fn calculate_scrollable_overflow_for_parent(&self) -> PhysicalRect<Au> {
+ self.calculate_scrollable_overflow();
+ self.scrollable_overflow_for_parent()
+ }
+
+ pub(crate) fn calculate_scrollable_overflow(&self) {
+ match self {
+ Fragment::Box(fragment) | Fragment::Float(fragment) => {
+ fragment.borrow_mut().calculate_scrollable_overflow()
+ },
+ Fragment::Positioning(fragment) => {
+ fragment.borrow_mut().calculate_scrollable_overflow()
+ },
+ _ => {},
+ }
+ }
+
pub(crate) fn cumulative_border_box_rect(&self) -> Option<PhysicalRect<Au>> {
match self {
Fragment::Box(fragment) | Fragment::Float(fragment) => {
diff --git a/components/layout/fragment_tree/fragment_tree.rs b/components/layout/fragment_tree/fragment_tree.rs
index ba03a72ac21..b59ace43aa6 100644
--- a/components/layout/fragment_tree/fragment_tree.rs
+++ b/components/layout/fragment_tree/fragment_tree.rs
@@ -2,14 +2,14 @@
* 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 std::cell::Cell;
+
use app_units::Au;
use base::print_tree::PrintTree;
use compositing_traits::display_list::AxesScrollSensitivity;
-use euclid::default::Size2D;
use fxhash::FxHashSet;
use malloc_size_of_derive::MallocSizeOf;
use style::animation::AnimationSetKey;
-use webrender_api::units;
use super::{BoxFragment, ContainingBlockManager, Fragment};
use crate::ArcRefCell;
@@ -30,7 +30,7 @@ pub struct FragmentTree {
/// The scrollable overflow rectangle for the entire tree
/// <https://drafts.csswg.org/css-overflow/#scrollable>
- pub(crate) scrollable_overflow: PhysicalRect<Au>,
+ scrollable_overflow: Cell<Option<PhysicalRect<Au>>>,
/// The containing block used in the layout of this fragment tree.
pub(crate) initial_containing_block: PhysicalRect<Au>,
@@ -43,13 +43,12 @@ impl FragmentTree {
pub(crate) fn new(
layout_context: &LayoutContext,
root_fragments: Vec<Fragment>,
- scrollable_overflow: PhysicalRect<Au>,
initial_containing_block: PhysicalRect<Au>,
viewport_scroll_sensitivity: AxesScrollSensitivity,
) -> Self {
let fragment_tree = Self {
root_fragments,
- scrollable_overflow,
+ scrollable_overflow: Cell::default(),
initial_containing_block,
viewport_scroll_sensitivity,
};
@@ -97,11 +96,35 @@ impl FragmentTree {
}
}
- pub fn scrollable_overflow(&self) -> units::LayoutSize {
- units::LayoutSize::from_untyped(Size2D::new(
- self.scrollable_overflow.size.width.to_f32_px(),
- self.scrollable_overflow.size.height.to_f32_px(),
- ))
+ pub(crate) fn scrollable_overflow(&self) -> PhysicalRect<Au> {
+ self.scrollable_overflow
+ .get()
+ .expect("Should only call `scrollable_overflow()` after calculating overflow")
+ }
+
+ pub(crate) fn calculate_scrollable_overflow(&self) {
+ self.scrollable_overflow
+ .set(Some(self.root_fragments.iter().fold(
+ PhysicalRect::zero(),
+ |acc, child| {
+ let child_overflow = child.calculate_scrollable_overflow_for_parent();
+
+ // https://drafts.csswg.org/css-overflow/#scrolling-direction
+ // We want to clip scrollable overflow on box-start and inline-start
+ // sides of the scroll container.
+ //
+ // FIXME(mrobinson, bug 25564): This should take into account writing
+ // mode.
+ let child_overflow = PhysicalRect::new(
+ euclid::Point2D::zero(),
+ euclid::Size2D::new(
+ child_overflow.size.width + child_overflow.origin.x,
+ child_overflow.size.height + child_overflow.origin.y,
+ ),
+ );
+ acc.union(&child_overflow)
+ },
+ )));
}
pub(crate) fn find<T>(
diff --git a/components/layout/fragment_tree/positioning_fragment.rs b/components/layout/fragment_tree/positioning_fragment.rs
index e45a6137bff..5547a9d86a1 100644
--- a/components/layout/fragment_tree/positioning_fragment.rs
+++ b/components/layout/fragment_tree/positioning_fragment.rs
@@ -22,7 +22,7 @@ pub(crate) struct PositioningFragment {
pub children: Vec<Fragment>,
/// The scrollable overflow of this anonymous fragment's children.
- pub scrollable_overflow: PhysicalRect<Au>,
+ scrollable_overflow: Option<PhysicalRect<Au>>,
/// The style of the fragment.
pub style: ServoArc<ComputedValues>,
@@ -55,20 +55,12 @@ impl PositioningFragment {
rect: PhysicalRect<Au>,
children: Vec<Fragment>,
) -> ArcRefCell<Self> {
- let content_origin = rect.origin;
- let scrollable_overflow = children.iter().fold(PhysicalRect::zero(), |acc, child| {
- acc.union(
- &child
- .scrollable_overflow_for_parent()
- .translate(content_origin.to_vector()),
- )
- });
ArcRefCell::new(PositioningFragment {
base,
style,
rect,
children,
- scrollable_overflow,
+ scrollable_overflow: None,
cumulative_containing_block_rect: PhysicalRect::zero(),
})
}
@@ -81,6 +73,25 @@ impl PositioningFragment {
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\