aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout/fragment_tree/fragment.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/layout/fragment_tree/fragment.rs')
-rw-r--r--components/layout/fragment_tree/fragment.rs84
1 files changed, 78 insertions, 6 deletions
diff --git a/components/layout/fragment_tree/fragment.rs b/components/layout/fragment_tree/fragment.rs
index d0d1b9b1104..ceccd1ec304 100644
--- a/components/layout/fragment_tree/fragment.rs
+++ b/components/layout/fragment_tree/fragment.rs
@@ -7,6 +7,7 @@ use std::sync::Arc;
use app_units::Au;
use base::id::PipelineId;
use base::print_tree::PrintTree;
+use euclid::{Point2D, Rect, Size2D, UnknownUnit};
use fonts::{ByteIndex, FontMetrics, GlyphStore};
use malloc_size_of_derive::MallocSizeOf;
use range::Range as ServoRange;
@@ -21,7 +22,7 @@ use super::{
Tag,
};
use crate::cell::ArcRefCell;
-use crate::geom::{LogicalSides, PhysicalRect};
+use crate::geom::{LogicalSides, PhysicalPoint, PhysicalRect};
use crate::style_ext::ComputedValuesExt;
#[derive(Clone, MallocSizeOf)]
@@ -112,6 +113,7 @@ impl Fragment {
Fragment::Float(fragment) => fragment.borrow().base.clone(),
})
}
+
pub(crate) fn mutate_content_rect(&mut self, callback: impl FnOnce(&mut PhysicalRect<Au>)) {
match self {
Fragment::Box(box_fragment) | Fragment::Float(box_fragment) => {
@@ -124,6 +126,26 @@ impl Fragment {
}
}
+ pub(crate) fn set_containing_block(&self, containing_block: &PhysicalRect<Au>) {
+ match self {
+ Fragment::Box(box_fragment) => box_fragment
+ .borrow_mut()
+ .set_containing_block(containing_block),
+ Fragment::Float(float_fragment) => float_fragment
+ .borrow_mut()
+ .set_containing_block(containing_block),
+ Fragment::Positioning(_) => {},
+ Fragment::AbsoluteOrFixedPositioned(hoisted_shared_fragment) => {
+ if let Some(ref fragment) = hoisted_shared_fragment.borrow().fragment {
+ fragment.set_containing_block(containing_block);
+ }
+ },
+ Fragment::Text(_) => {},
+ Fragment::Image(_) => {},
+ Fragment::IFrame(_) => {},
+ }
+ }
+
pub fn tag(&self) -> Option<Tag> {
self.base().and_then(|base| base.tag)
}
@@ -146,12 +168,12 @@ impl Fragment {
}
}
- pub fn scrolling_area(&self, containing_block: &PhysicalRect<Au>) -> PhysicalRect<Au> {
+ pub fn scrolling_area(&self) -> PhysicalRect<Au> {
match self {
- Fragment::Box(fragment) | Fragment::Float(fragment) => fragment
- .borrow()
- .scrollable_overflow()
- .translate(containing_block.origin.to_vector()),
+ Fragment::Box(fragment) | Fragment::Float(fragment) => {
+ let fragment = fragment.borrow();
+ fragment.offset_by_containing_block(&fragment.scrollable_overflow())
+ },
_ => self.scrollable_overflow(),
}
}
@@ -169,6 +191,56 @@ impl Fragment {
}
}
+ pub(crate) fn cumulative_content_box_rect(&self) -> Option<PhysicalRect<Au>> {
+ match self {
+ Fragment::Box(fragment) | Fragment::Float(fragment) => {
+ let fragment = fragment.borrow();
+ Some(fragment.offset_by_containing_block(&fragment.border_rect()))
+ },
+ Fragment::Positioning(_) |
+ Fragment::Text(_) |
+ Fragment::AbsoluteOrFixedPositioned(_) |
+ Fragment::Image(_) |
+ Fragment::IFrame(_) => None,
+ }
+ }
+
+ pub(crate) fn client_rect(&self) -> Rect<i32, UnknownUnit> {
+ let rect = match self {
+ Fragment::Box(fragment) | Fragment::Float(fragment) => {
+ // https://drafts.csswg.org/cssom-view/#dom-element-clienttop
+ // " If the element has no associated CSS layout box or if the
+ // CSS layout box is inline, return zero." For this check we
+ // also explicitly ignore the list item portion of the display
+ // style.
+ let fragment = fragment.borrow();
+ if fragment.is_inline_box() {
+ return Rect::zero();
+ }
+
+ if fragment.is_table_wrapper() {
+ // For tables the border actually belongs to the table grid box,
+ // so we need to include it in the dimension of the table wrapper box.
+ let mut rect = fragment.border_rect();
+ rect.origin = PhysicalPoint::zero();
+ rect
+ } else {
+ let mut rect = fragment.padding_rect();
+ rect.origin = PhysicalPoint::new(fragment.border.left, fragment.border.top);
+ rect
+ }
+ },
+ _ => return Rect::zero(),
+ }
+ .to_untyped();
+
+ let rect = Rect::new(
+ Point2D::new(rect.origin.x.to_f32_px(), rect.origin.y.to_f32_px()),
+ Size2D::new(rect.size.width.to_f32_px(), rect.size.height.to_f32_px()),
+ );
+ rect.round().to_i32()
+ }
+
pub(crate) fn find<T>(
&self,
manager: &ContainingBlockManager<PhysicalRect<Au>>,