diff options
Diffstat (limited to 'components/layout_2020/fragment_tree/box_fragment.rs')
-rw-r--r-- | components/layout_2020/fragment_tree/box_fragment.rs | 133 |
1 files changed, 63 insertions, 70 deletions
diff --git a/components/layout_2020/fragment_tree/box_fragment.rs b/components/layout_2020/fragment_tree/box_fragment.rs index 3c6d737c4d8..dd2a31f17d1 100644 --- a/components/layout_2020/fragment_tree/box_fragment.rs +++ b/components/layout_2020/fragment_tree/box_fragment.rs @@ -8,6 +8,7 @@ use serde::Serialize; use servo_arc::Arc as ServoArc; use style::computed_values::overflow_x::T as ComputedOverflow; use style::computed_values::position::T as ComputedPosition; +use style::logical_geometry::WritingMode; use style::properties::ComputedValues; use style::values::computed::{CSSPixelLength, Length, LengthPercentage, LengthPercentageOrAuto}; use style::Zero; @@ -16,7 +17,7 @@ use super::{BaseFragment, BaseFragmentInfo, CollapsedBlockMargins, Fragment}; use crate::cell::ArcRefCell; use crate::formatting_contexts::Baselines; use crate::geom::{ - AuOrAuto, LogicalRect, LogicalSides, PhysicalPoint, PhysicalRect, PhysicalSides, PhysicalSize, + AuOrAuto, LogicalRect, PhysicalPoint, PhysicalRect, PhysicalSides, PhysicalSize, ToLogical, }; use crate::style_ext::ComputedValuesExt; @@ -46,14 +47,13 @@ pub(crate) struct BoxFragment { pub style: ServoArc<ComputedValues>, pub children: Vec<ArcRefCell<Fragment>>, - /// From the containing block’s start corner…? - /// This might be broken when the containing block is in a different writing mode: - /// <https://drafts.csswg.org/css-writing-modes/#orthogonal-flows> - pub content_rect: LogicalRect<Au>, + /// The content rect of this fragment in the parent fragment's content rectangle. This + /// does not include padding, border, or margin -- it only includes content. + pub content_rect: PhysicalRect<Au>, - pub padding: LogicalSides<Au>, - pub border: LogicalSides<Au>, - pub margin: LogicalSides<Au>, + pub padding: PhysicalSides<Au>, + pub border: PhysicalSides<Au>, + pub margin: PhysicalSides<Au>, /// When the `clear` property is not set to `none`, it may introduce clearance. /// Clearance is some extra spacing that is added above the top margin, @@ -66,7 +66,7 @@ pub(crate) struct BoxFragment { /// When this [`BoxFragment`] is for content that has a baseline, this tracks /// the first and last baselines of that content. This is used to propagate baselines /// to things such as tables and inline formatting contexts. - pub baselines: Baselines, + baselines: Baselines, pub block_margins_collapsed_with_children: CollapsedBlockMargins, @@ -91,10 +91,10 @@ impl BoxFragment { base_fragment_info: BaseFragmentInfo, style: ServoArc<ComputedValues>, children: Vec<Fragment>, - content_rect: LogicalRect<Au>, - padding: LogicalSides<Au>, - border: LogicalSides<Au>, - margin: LogicalSides<Au>, + content_rect: PhysicalRect<Au>, + padding: PhysicalSides<Au>, + border: PhysicalSides<Au>, + margin: PhysicalSides<Au>, clearance: Option<Au>, block_margins_collapsed_with_children: CollapsedBlockMargins, ) -> BoxFragment { @@ -126,37 +126,19 @@ impl BoxFragment { base_fragment_info: BaseFragmentInfo, style: ServoArc<ComputedValues>, children: Vec<Fragment>, - content_rect: LogicalRect<Au>, - padding: LogicalSides<Au>, - border: LogicalSides<Au>, - margin: LogicalSides<Au>, + content_rect: PhysicalRect<Au>, + padding: PhysicalSides<Au>, + border: PhysicalSides<Au>, + margin: PhysicalSides<Au>, clearance: Option<Au>, block_margins_collapsed_with_children: CollapsedBlockMargins, overconstrained: PhysicalSize<bool>, ) -> BoxFragment { - // FIXME(mrobinson, bug 25564): We should be using the containing block - // here to properly convert scrollable overflow to physical geometry. - let containing_block = PhysicalRect::zero(); let scrollable_overflow_from_children = children.iter().fold(PhysicalRect::zero(), |acc, child| { - acc.union(&child.scrollable_overflow(&containing_block)) + acc.union(&child.scrollable_overflow()) }); - // From the https://drafts.csswg.org/css-align-3/#baseline-export section on "block containers": - // > However, for legacy reasons if its baseline-source is auto (the initial - // > value) a block-level or inline-level block container that is a scroll container - // > always has a last baseline set, whose baselines all correspond to its block-end - // > margin edge. - // - // This applies even if there is no baseline set, so we unconditionally set the value here - // and ignore anything that is set via [`Self::with_baselines`]. - let mut baselines = Baselines::default(); - if style.establishes_scroll_container() { - baselines.last = Some( - content_rect.size.block + padding.block_end + border.block_end + margin.block_end, - ) - } - BoxFragment { base: base_fragment_info.into(), style, @@ -166,7 +148,7 @@ impl BoxFragment { border, margin, clearance, - baselines, + baselines: Baselines::default(), block_margins_collapsed_with_children, scrollable_overflow_from_children, overconstrained, @@ -176,16 +158,41 @@ impl BoxFragment { } pub fn with_baselines(mut self, baselines: Baselines) -> Self { + self.baselines = baselines; + self + } + + /// Get the baselines for this [`BoxFragment`] if they are compatible with the given [`WritingMode`]. + /// If they are not compatible, [`Baselines::default()`] is returned. + pub fn baselines(&self, writing_mode: WritingMode) -> Baselines { + let mut baselines = + if writing_mode.is_horizontal() == self.style.writing_mode.is_horizontal() { + self.baselines + } else { + // If the writing mode of the container requesting baselines is not + // compatible, ensure that the baselines established by this fragment are + // not used. + Baselines::default() + }; + // From the https://drafts.csswg.org/css-align-3/#baseline-export section on "block containers": // > However, for legacy reasons if its baseline-source is auto (the initial // > value) a block-level or inline-level block container that is a scroll container // > always has a last baseline set, whose baselines all correspond to its block-end // > margin edge. - if !self.style.establishes_scroll_container() { - self.baselines.last = baselines.last; + // + // This applies even if there is no baseline set, so we unconditionally set the value here + // and ignore anything that is set via [`Self::with_baselines`]. + if self.style.establishes_scroll_container() { + let content_rect = self.content_rect.to_logical(writing_mode); + let padding = self.padding.to_logical(writing_mode); + let border = self.border.to_logical(writing_mode); + let margin = self.margin.to_logical(writing_mode); + baselines.last = Some( + content_rect.size.block + padding.block_end + border.block_end + margin.block_end, + ) } - self.baselines.first = baselines.first; - self + baselines } pub fn add_extra_background(&mut self, extra_background: ExtraBackground) { @@ -199,32 +206,26 @@ impl BoxFragment { self.background_mode = BackgroundMode::None; } - pub fn scrollable_overflow(&self, containing_block: &PhysicalRect<Au>) -> PhysicalRect<Au> { - let physical_padding_rect = self - .padding_rect() - .to_physical(self.style.writing_mode, containing_block); - - let content_origin = self - .content_rect - .start_corner - .to_physical(self.style.writing_mode); + pub fn scrollable_overflow(&self) -> PhysicalRect<Au> { + 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.to_vector()), + .translate(content_origin), ) } - pub(crate) fn padding_rect(&self) -> LogicalRect<Au> { - self.content_rect.inflate(&self.padding) + pub(crate) fn padding_rect(&self) -> PhysicalRect<Au> { + self.content_rect.outer_rect(self.padding) } - pub(crate) fn border_rect(&self) -> LogicalRect<Au> { - self.padding_rect().inflate(&self.border) + pub(crate) fn border_rect(&self) -> PhysicalRect<Au> { + self.padding_rect().outer_rect(self.border) } - pub(crate) fn margin_rect(&self) -> LogicalRect<Au> { - self.border_rect().inflate(&self.margin) + pub(crate) fn margin_rect(&self) -> PhysicalRect<Au> { + self.border_rect().outer_rect(self.margin) } pub fn print(&self, tree: &mut PrintTree) { @@ -245,7 +246,7 @@ impl BoxFragment { self.border_rect(), self.margin, self.clearance, - self.scrollable_overflow(&PhysicalRect::zero()), + self.scrollable_overflow(), self.baselines, self.style.get_box().overflow_x, self.style.get_box().overflow_y, @@ -257,21 +258,15 @@ impl BoxFragment { tree.end_level(); } - pub fn scrollable_overflow_for_parent( - &self, - containing_block: &PhysicalRect<Au>, - ) -> PhysicalRect<Au> { - let mut overflow = self - .border_rect() - .to_physical(self.style.writing_mode, containing_block); - + pub fn scrollable_overflow_for_parent(&self) -> PhysicalRect<Au> { + let mut overflow = self.border_rect(); if self.style.establishes_scroll_container() { return overflow; } // https://www.w3.org/TR/css-overflow-3/#scrollable // Only include the scrollable overflow of a child box if it has overflow: visible. - let scrollable_overflow = self.scrollable_overflow(containing_block); + let scrollable_overflow = self.scrollable_overflow(); let bottom_right = PhysicalPoint::new( overflow.max_x().max(scrollable_overflow.max_x()), overflow.max_y().max(scrollable_overflow.max_y()), @@ -302,9 +297,7 @@ impl BoxFragment { ); let (cb_width, cb_height) = (containing_block.width(), containing_block.height()); - let content_rect = self - .content_rect - .to_physical(self.style.writing_mode, containing_block); + let content_rect = self.content_rect; if let Some(resolved_sticky_insets) = self.resolved_sticky_insets { return resolved_sticky_insets; |