aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout_2020/fragment_tree/box_fragment.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/layout_2020/fragment_tree/box_fragment.rs')
-rw-r--r--components/layout_2020/fragment_tree/box_fragment.rs133
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;