diff --git a/components/layout_2020/display_list/mod.rs b/components/layout_2020/display_list/mod.rs index 657c99184e9..9e03761eed8 100644 --- a/components/layout_2020/display_list/mod.rs +++ b/components/layout_2020/display_list/mod.rs @@ -260,7 +260,6 @@ impl Fragment { if let Some(style) = positioning_fragment.style.as_ref() { let rect = positioning_fragment .rect - .to_physical(style.writing_mode, containing_block) .translate(containing_block.origin.to_vector()); self.maybe_push_hit_test_for_style_and_tag( builder, @@ -274,10 +273,7 @@ impl Fragment { Fragment::Image(i) => match i.style.get_inherited_box().visibility { Visibility::Visible => { builder.is_contentful = true; - let rect = i - .rect - .to_physical(i.style.writing_mode, containing_block) - .translate(containing_block.origin.to_vector()); + let rect = i.rect.translate(containing_block.origin.to_vector()); let common = builder.common_properties(rect.to_webrender(), &i.style); builder.wr().push_image( @@ -295,10 +291,7 @@ impl Fragment { Fragment::IFrame(iframe) => match iframe.style.get_inherited_box().visibility { Visibility::Visible => { builder.is_contentful = true; - let rect = iframe - .rect - .to_physical(iframe.style.writing_mode, containing_block) - .translate(containing_block.origin.to_vector()); + let rect = iframe.rect.translate(containing_block.origin.to_vector()); builder.iframe_sizes.insert( iframe.browsing_context_id, @@ -366,10 +359,7 @@ impl Fragment { builder.is_contentful = true; - let rect = fragment - .rect - .to_physical(fragment.parent_style.writing_mode, containing_block) - .translate(containing_block.origin.to_vector()); + let rect = fragment.rect.translate(containing_block.origin.to_vector()); let mut baseline_origin = rect.origin; baseline_origin.y += fragment.font_metrics.ascent; let glyphs = glyphs( @@ -504,7 +494,6 @@ impl<'a> BuilderForBoxFragment<'a> { fn new(fragment: &'a BoxFragment, containing_block: &'a PhysicalRect) -> Self { let border_rect: units::LayoutRect = fragment .border_rect() - .to_physical(fragment.style.writing_mode, containing_block) .translate(containing_block.origin.to_vector()) .to_webrender(); @@ -562,7 +551,6 @@ impl<'a> BuilderForBoxFragment<'a> { self.content_rect.get_or_init(|| { self.fragment .content_rect - .to_physical(self.fragment.style.writing_mode, self.containing_block) .translate(self.containing_block.origin.to_vector()) .to_webrender() }) @@ -572,7 +560,6 @@ impl<'a> BuilderForBoxFragment<'a> { self.padding_rect.get_or_init(|| { self.fragment .padding_rect() - .to_physical(self.fragment.style.writing_mode, self.containing_block) .translate(self.containing_block.origin.to_vector()) .to_webrender() }) @@ -606,13 +593,7 @@ impl<'a> BuilderForBoxFragment<'a> { return Some(clip); } - let radii = inner_radii( - self.border_radius, - self.fragment - .border - .to_physical(self.fragment.style.writing_mode) - .to_webrender(), - ); + let radii = inner_radii(self.border_radius, self.fragment.border.to_webrender()); let maybe_clip = create_clip_chain(radii, *self.padding_rect(), builder, force_clip_creation); *self.padding_edge_clip_chain_id.borrow_mut() = maybe_clip; @@ -630,9 +611,7 @@ impl<'a> BuilderForBoxFragment<'a> { let radii = inner_radii( self.border_radius, - (self.fragment.border + self.fragment.padding) - .to_physical(self.fragment.style.writing_mode) - .to_webrender(), + (self.fragment.border + self.fragment.padding).to_webrender(), ); let maybe_clip = create_clip_chain(radii, *self.content_rect(), builder, force_clip_creation); @@ -731,7 +710,7 @@ impl<'a> BuilderForBoxFragment<'a> { painting_area_override: None, positioning_area_override: Some( positioning_area - .to_physical(self.fragment.style.writing_mode, self.containing_block) + .to_physical(self.fragment.style.writing_mode) .translate(self.containing_block.origin.to_vector()) .to_webrender(), ), @@ -887,11 +866,7 @@ impl<'a> BuilderForBoxFragment<'a> { fn build_border(&mut self, builder: &mut DisplayListBuilder) { let border = self.fragment.style.get_border(); - let border_widths = self - .fragment - .border - .to_physical(self.fragment.style.writing_mode) - .to_webrender(); + let border_widths = self.fragment.border.to_webrender(); if border_widths == SideOffsets2D::zero() { return; diff --git a/components/layout_2020/display_list/stacking_context.rs b/components/layout_2020/display_list/stacking_context.rs index 0e66debab81..31feace5170 100644 --- a/components/layout_2020/display_list/stacking_context.rs +++ b/components/layout_2020/display_list/stacking_context.rs @@ -1178,11 +1178,9 @@ impl BoxFragment { let padding_rect = self .padding_rect() - .to_physical(self.style.writing_mode, &containing_block.rect) .translate(containing_block.rect.origin.to_vector()); let content_rect = self .content_rect - .to_physical(self.style.writing_mode, &containing_block.rect) .translate(containing_block.rect.origin.to_vector()); let for_absolute_descendants = ContainingBlock::new( @@ -1246,9 +1244,7 @@ impl BoxFragment { _ => return None, }; - let border_rect = self - .border_rect() - .to_physical(self.style.writing_mode, containing_block_rect); + let border_rect = self.border_rect(); let clip_rect = clip_rect .for_border_rect(border_rect) .translate(containing_block_rect.origin.to_vector()) @@ -1306,7 +1302,6 @@ impl BoxFragment { let padding_rect = self .padding_rect() - .to_physical(self.style.writing_mode, containing_block_rect) .translate(containing_block_rect.origin.to_vector()) .to_webrender(); @@ -1314,8 +1309,7 @@ impl BoxFragment { parent_scroll_node_id, parent_clip_id, external_id, - self.scrollable_overflow(containing_block_rect) - .to_webrender(), + self.scrollable_overflow().to_webrender(), padding_rect, sensitivity, ); @@ -1380,7 +1374,6 @@ impl BoxFragment { let frame_rect = self .border_rect() - .to_physical(self.style.writing_mode, containing_block_rect) .translate(containing_block_rect.origin.to_vector()) .to_webrender(); @@ -1426,9 +1419,7 @@ impl BoxFragment { return None; } - let relative_border_rect = self - .border_rect() - .to_physical(self.style.writing_mode, containing_block_rect); + let relative_border_rect = self.border_rect(); let border_rect = relative_border_rect.translate(containing_block_rect.origin.to_vector()); let untyped_border_rect = border_rect.to_untyped(); @@ -1560,7 +1551,6 @@ impl PositioningFragment { ) { let rect = self .rect - .to_physical(self.writing_mode, &containing_block.rect) .translate(containing_block.rect.origin.to_vector()); let new_containing_block = containing_block.new_replacing_rect(&rect); let new_containing_block_info = diff --git a/components/layout_2020/flexbox/layout.rs b/components/layout_2020/flexbox/layout.rs index 167c6adb247..25c2bec24eb 100644 --- a/components/layout_2020/flexbox/layout.rs +++ b/components/layout_2020/flexbox/layout.rs @@ -676,8 +676,10 @@ impl FlexContainer { all_baselines.last = line_all_baselines.last; } + let physical_line_position = + flow_relative_line_position.to_physical_size(self.style.writing_mode); for (fragment, _) in &mut final_line_layout.item_fragments { - fragment.content_rect.start_corner += flow_relative_line_position + fragment.content_rect.origin += physical_line_position; } final_line_layout.item_fragments }) @@ -705,6 +707,7 @@ impl FlexContainer { let fragment = Fragment::Box(fragment); child_positioning_context.adjust_static_position_of_hoisted_fragments( &fragment, + self.style.writing_mode, PositioningContextLength::zero(), ); positioning_context.append(child_positioning_context); @@ -1545,15 +1548,20 @@ impl InitialFlexLineLayout<'_> { let mut fragment_info = item.box_.base_fragment_info(); fragment_info.flags.insert(FragmentFlags::IS_FLEX_ITEM); + let container_writing_mode = flex_context.containing_block.style.writing_mode; ( BoxFragment::new( fragment_info, item.box_.style().clone(), item_layout_result.fragments, - content_rect, - flex_context.sides_to_flow_relative(item.padding), - flex_context.sides_to_flow_relative(item.border), - margin, + content_rect.to_physical(container_writing_mode), + flex_context + .sides_to_flow_relative(item.padding) + .to_physical(container_writing_mode), + flex_context + .sides_to_flow_relative(item.border) + .to_physical(container_writing_mode), + margin.to_physical(container_writing_mode), None, /* clearance */ collapsed_margin, ), @@ -1620,7 +1628,12 @@ impl FlexItem<'_> { &pbm, ); let cross_size = flex_context.vec2_to_flex_relative(size).cross; - let fragments = replaced.contents.make_fragments(&replaced.style, size); + let container_writing_mode = + flex_context.containing_block.style.writing_mode; + let fragments = replaced.contents.make_fragments( + &replaced.style, + size.to_physical_size(container_writing_mode), + ); FlexItemLayoutResult { hypothetical_cross_size: cross_size, diff --git a/components/layout_2020/flow/float.rs b/components/layout_2020/flow/float.rs index 6f4d3b2d89e..70b8612f6e7 100644 --- a/components/layout_2020/flow/float.rs +++ b/components/layout_2020/flow/float.rs @@ -16,6 +16,7 @@ use euclid::num::Zero; use serde::Serialize; use servo_arc::Arc; use style::computed_values::float::T as FloatProperty; +use style::logical_geometry::WritingMode; use style::properties::ComputedValues; use style::values::computed::{Clear, Length}; use style::values::specified::text::TextDecorationLine; @@ -25,7 +26,7 @@ use crate::dom::NodeExt; use crate::dom_traversal::{Contents, NodeAndStyleInfo}; use crate::formatting_contexts::IndependentFormattingContext; use crate::fragment_tree::{BoxFragment, CollapsedBlockMargins, CollapsedMargin}; -use crate::geom::{LogicalRect, LogicalVec2}; +use crate::geom::{LogicalRect, LogicalVec2, ToLogical}; use crate::positioned::PositioningContext; use crate::style_ext::{ComputedValuesExt, DisplayInside, PaddingBorderMargin}; use crate::ContainingBlock; @@ -959,26 +960,24 @@ impl FloatBox { ), }; content_size = LogicalVec2 { - inline: inline_size, - block: block_size, + inline: inline_size.into(), + block: block_size.into(), }; children = independent_layout.fragments; }, IndependentFormattingContext::Replaced(ref replaced) => { // https://drafts.csswg.org/css2/#float-replaced-width // https://drafts.csswg.org/css2/#inline-replaced-height - content_size = replaced - .contents - .used_size_as_if_inline_element( - containing_block, - &replaced.style, - None, - &pbm, - ) - .into(); - children = replaced - .contents - .make_fragments(&replaced.style, content_size.into()); + content_size = replaced.contents.used_size_as_if_inline_element( + containing_block, + &replaced.style, + None, + &pbm, + ); + children = replaced.contents.make_fragments( + &replaced.style, + content_size.to_physical_size(containing_block.style.writing_mode), + ) }, }; @@ -987,14 +986,15 @@ impl FloatBox { size: content_size, }; + let containing_block_writing_mode = containing_block.style.writing_mode; BoxFragment::new( self.contents.base_fragment_info(), style.clone(), children, - content_rect.into(), - pbm.padding, - pbm.border, - margin, + content_rect.to_physical(containing_block_writing_mode), + pbm.padding.to_physical(containing_block_writing_mode), + pbm.border.to_physical(containing_block_writing_mode), + margin.to_physical(containing_block_writing_mode), // Clearance is handled internally by the float placement logic, so there's no need // to store it explicitly in the fragment. None, // clearance @@ -1194,6 +1194,7 @@ impl SequentialLayoutState { pub(crate) fn place_float_fragment( &mut self, box_fragment: &mut BoxFragment, + container_writing_mode: WritingMode, margins_collapsing_with_parent_containing_block: CollapsedMargin, block_offset_from_containing_block_top: Au, ) { @@ -1208,8 +1209,9 @@ impl SequentialLayoutState { block_start_of_containing_block_in_bfc + block_offset_from_containing_block_top, ); - let pbm_sums = box_fragment.padding + box_fragment.border + box_fragment.margin; - let content_rect = &box_fragment.content_rect; + let pbm_sums = (box_fragment.padding + box_fragment.border + box_fragment.margin) + .to_logical(container_writing_mode); + let content_rect = &box_fragment.content_rect.to_logical(container_writing_mode); let margin_box_start_corner = self.floats.add_float(&PlacementInfo { size: content_rect.size + pbm_sums.sum(), side: FloatSide::from_style(&box_fragment.style).expect("Float box wasn't floated!"), @@ -1227,6 +1229,7 @@ impl SequentialLayoutState { block: new_position_in_bfc.block - block_start_of_containing_block_in_bfc, }; - box_fragment.content_rect.start_corner = new_position_in_containing_block; + box_fragment.content_rect.origin = + new_position_in_containing_block.to_physical_point(container_writing_mode); } } diff --git a/components/layout_2020/flow/inline/line.rs b/components/layout_2020/flow/inline/line.rs index 765728b96a3..611e6640683 100644 --- a/components/layout_2020/flow/inline/line.rs +++ b/components/layout_2020/flow/inline/line.rs @@ -29,7 +29,7 @@ use crate::context::LayoutContext; use crate::fragment_tree::{ BaseFragmentInfo, BoxFragment, CollapsedBlockMargins, Fragment, TextFragment, }; -use crate::geom::{LogicalRect, LogicalVec2}; +use crate::geom::{LogicalRect, LogicalVec2, ToLogical}; use crate::positioned::{ relative_adjustement, AbsolutelyPositionedBox, PositioningContext, PositioningContextLength, }; @@ -360,13 +360,15 @@ impl<'a> LineItemLayout<'a> { }, }; + let ifc_writing_mode = self.ifc_containing_block.style.writing_mode; if inner_state .flags .contains(LineLayoutInlineContainerFlags::HAD_ANY_FLOATS) { for fragment in inner_state.fragments.iter_mut() { if let Fragment::Float(box_fragment) = fragment { - box_fragment.content_rect.start_corner -= pbm_sums.start_offset(); + box_fragment.content_rect.origin -= + pbm_sums.start_offset().to_physical_size(ifc_writing_mode); } } } @@ -382,10 +384,10 @@ impl<'a> LineItemLayout<'a> { inline_box.base_fragment_info, style.clone(), inner_state.fragments, - content_rect, - padding, - border, - margin, + content_rect.to_physical(ifc_writing_mode), + padding.to_physical(ifc_writing_mode), + border.to_physical(ifc_writing_mode), + margin.to_physical(ifc_writing_mode), None, /* clearance */ CollapsedBlockMargins::zero(), ); @@ -394,7 +396,7 @@ impl<'a> LineItemLayout<'a> { Either::First(mut positioning_context) => { positioning_context.layout_collected_children(self.layout_context, &mut fragment); positioning_context.adjust_static_position_of_hoisted_fragments_with_offset( - &fragment.content_rect.start_corner, + &fragment.content_rect.origin.to_logical(ifc_writing_mode), PositioningContextLength::zero(), ); self.current_positioning_context_mut() @@ -403,7 +405,7 @@ impl<'a> LineItemLayout<'a> { Either::Second(start_offset) => { self.current_positioning_context_mut() .adjust_static_position_of_hoisted_fragments_with_offset( - &fragment.content_rect.start_corner, + &fragment.content_rect.origin.to_logical(ifc_writing_mode), start_offset, ); }, @@ -484,7 +486,7 @@ impl<'a> LineItemLayout<'a> { self.state.fragments.push(Fragment::Text(TextFragment { base: text_item.base_fragment_info.into(), parent_style: text_item.parent_style, - rect, + rect: rect.to_physical(self.ifc_containing_block.style.writing_mode), font_metrics: text_item.font_metrics, font_key: text_item.font_key, glyphs: text_item.text, @@ -498,18 +500,27 @@ impl<'a> LineItemLayout<'a> { // offset, which is the sum of the start component of the padding, border, and margin. // This needs to be added to the calculated block and inline positions. // Make the final result relative to the parent box. - atomic.fragment.content_rect.start_corner.inline += self.state.inline_advance; - atomic.fragment.content_rect.start_corner.block += - atomic.calculate_block_start(&self.line_metrics) - self.state.parent_offset.block; + let mut atomic_offset = LogicalVec2 { + inline: self.state.inline_advance, + block: atomic.calculate_block_start(&self.line_metrics) - + self.state.parent_offset.block, + }; if atomic.fragment.style.clone_position().is_relative() { - atomic.fragment.content_rect.start_corner += + atomic_offset += relative_adjustement(&atomic.fragment.style, self.ifc_containing_block); } + let ifc_writing_mode = self.ifc_containing_block.style.writing_mode; + atomic.fragment.content_rect.origin += atomic_offset.to_physical_size(ifc_writing_mode); + if let Some(mut positioning_context) = atomic.positioning_context { positioning_context.adjust_static_position_of_hoisted_fragments_with_offset( - &atomic.fragment.content_rect.start_corner, + &atomic + .fragment + .content_rect + .origin + .to_logical(ifc_writing_mode), PositioningContextLength::zero(), ); self.current_positioning_context_mut() @@ -577,7 +588,8 @@ impl<'a> LineItemLayout<'a> { inline: self.state.parent_offset.inline, block: self.line_metrics.block_offset + self.state.parent_offset.block, }; - float.fragment.content_rect.start_corner -= distance_from_parent_to_ifc; + float.fragment.content_rect.origin -= distance_from_parent_to_ifc + .to_physical_size(self.ifc_containing_block.style.writing_mode); self.state.fragments.push(Fragment::Float(float.fragment)); } } diff --git a/components/layout_2020/flow/inline/mod.rs b/components/layout_2020/flow/inline/mod.rs index 3c480466ff7..88447a87e33 100644 --- a/components/layout_2020/flow/inline/mod.rs +++ b/components/layout_2020/flow/inline/mod.rs @@ -123,7 +123,7 @@ use crate::fragment_tree::{ BoxFragment, CollapsedBlockMargins, CollapsedMargin, Fragment, FragmentFlags, PositioningFragment, }; -use crate::geom::{LogicalRect, LogicalVec2}; +use crate::geom::{LogicalRect, LogicalVec2, PhysicalRect, ToLogical}; use crate::positioned::{AbsolutelyPositionedBox, PositioningContext}; use crate::sizing::ContentSizes; use crate::style_ext::{ComputedValuesExt, PaddingBorderMargin}; @@ -890,11 +890,10 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> { start_positioning_context_length, ); + let line_rect = line_rect.to_physical(self.containing_block.style.writing_mode); self.fragments .push(Fragment::Positioning(PositioningFragment::new_anonymous( - line_rect, - fragments, - self.containing_block.style.writing_mode, + line_rect, fragments, ))); } @@ -1014,6 +1013,7 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> { state.current_containing_block_offset(); state.place_float_fragment( fragment, + self.containing_block.style.writing_mode, CollapsedMargin::zero(), block_offset_from_containining_block_top, ); @@ -1034,8 +1034,8 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> { ) { let margin_box = float_item .fragment - .border_rect() - .inflate(&float_item.fragment.margin); + .margin_rect() + .to_logical(self.containing_block.style.writing_mode); let inline_size = margin_box.size.inline.max(Au::zero()); let available_inline_size = match self.current_line.placement_among_floats.get() { @@ -1909,34 +1909,41 @@ impl IndependentFormattingContext { offset_in_text: usize, ) { let style = self.style(); + let container_writing_mode = inline_formatting_context_state + .containing_block + .style + .writing_mode; let pbm = style.padding_border_margin(inline_formatting_context_state.containing_block); let margin = pbm.margin.auto_is(Au::zero); let pbm_sums = pbm.padding + pbm.border + margin; + let pbm_physical_origin = pbm_sums + .start_offset() + .to_physical_point(container_writing_mode); let mut child_positioning_context = None; // We need to know the inline size of the atomic before deciding whether to do the line break. let fragment = match self { IndependentFormattingContext::Replaced(replaced) => { - let size = replaced.contents.used_size_as_if_inline_element( - inline_formatting_context_state.containing_block, - &replaced.style, - None, - &pbm, - ); + let size = replaced + .contents + .used_size_as_if_inline_element( + inline_formatting_context_state.containing_block, + &replaced.style, + None, + &pbm, + ) + .to_physical_size(container_writing_mode); let fragments = replaced.contents.make_fragments(&replaced.style, size); - let content_rect = LogicalRect { - start_corner: pbm_sums.start_offset(), - size, - }; + let content_rect = PhysicalRect::new(pbm_physical_origin, size); BoxFragment::new( replaced.base_fragment_info, replaced.style.clone(), fragments, content_rect, - pbm.padding, - pbm.border, - margin, + pbm.padding.to_physical(container_writing_mode), + pbm.border.to_physical(container_writing_mode), + margin.to_physical(container_writing_mode), None, /* clearance */ CollapsedBlockMargins::zero(), ) @@ -2015,22 +2022,23 @@ impl IndependentFormattingContext { }, }; - let content_rect = LogicalRect { - start_corner: pbm_sums.start_offset(), - size: LogicalVec2 { + let content_rect = PhysicalRect::new( + pbm_physical_origin, + LogicalVec2 { block: block_size, inline: inline_size, - }, - }; + } + .to_physical_size(container_writing_mode), + ); BoxFragment::new( non_replaced.base_fragment_info, non_replaced.style.clone(), independent_layout.fragments, content_rect, - pbm.padding, - pbm.border, - margin, + pbm.padding.to_physical(container_writing_mode), + pbm.border.to_physical(container_writing_mode), + margin.to_physical(container_writing_mode), None, CollapsedBlockMargins::zero(), ) @@ -2045,9 +2053,13 @@ impl IndependentFormattingContext { inline_formatting_context_state.process_soft_wrap_opportunity(); } - let size = pbm_sums.sum() + fragment.content_rect.size; + let size = pbm_sums.sum() + + fragment + .content_rect + .to_logical(container_writing_mode) + .size; let baseline_offset = self - .pick_baseline(&fragment.baselines) + .pick_baseline(&fragment.baselines(container_writing_mode)) .map(|baseline| pbm_sums.block_start + baseline) .unwrap_or(size.block); diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index ff99397c1a3..d6a647c62cb 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -29,7 +29,9 @@ use crate::formatting_contexts::{ use crate::fragment_tree::{ BaseFragmentInfo, BoxFragment, CollapsedBlockMargins, CollapsedMargin, Fragment, FragmentFlags, }; -use crate::geom::{AuOrAuto, LogicalRect, LogicalSides, LogicalVec2}; +use crate::geom::{ + AuOrAuto, LogicalRect, LogicalSides, LogicalVec2, PhysicalRect, PhysicalSides, ToLogical, +}; use crate::positioned::{AbsolutelyPositionedBox, PositioningContext, PositioningContextLength}; use crate::replaced::ReplacedContent; use crate::sizing::{self, ContentSizes}; @@ -225,9 +227,10 @@ impl OutsideMarker { sequential_layout_state: Option<&mut SequentialLayoutState>, collapsible_with_parent_start_margin: Option, ) -> Fragment { + let containing_block_writing_mode = containing_block.style.writing_mode; let content_sizes = self .block_container - .inline_content_sizes(layout_context, containing_block.style.writing_mode); + .inline_content_sizes(layout_context, containing_block_writing_mode); let containing_block_for_children = ContainingBlock { inline_size: content_sizes.max_content, block_size: AuOrAuto::auto(), @@ -241,22 +244,29 @@ impl OutsideMarker { sequential_layout_state, collapsible_with_parent_start_margin.unwrap_or(CollapsibleWithParentStartMargin(false)), ); - let max_inline_size = flow_layout.fragments.iter().fold( - Length::zero(), - |current_max, fragment| match fragment { - Fragment::Text(text) => current_max.max(text.rect.max_inline_position().into()), - Fragment::Image(image) => current_max.max(image.rect.max_inline_position().into()), - Fragment::Positioning(positioning) => { - current_max.max(positioning.rect.max_inline_position().into()) - }, - Fragment::Box(_) | - Fragment::Float(_) | - Fragment::AbsoluteOrFixedPositioned(_) | - Fragment::IFrame(_) => { - unreachable!("Found unexpected fragment type in outside list marker!"); - }, - }, - ); + let max_inline_size = + flow_layout + .fragments + .iter() + .fold(Au::zero(), |current_max, fragment| { + current_max.max( + match fragment { + Fragment::Text(text) => text.rect, + Fragment::Image(image) => image.rect, + Fragment::Positioning(positioning) => positioning.rect, + Fragment::Box(_) | + Fragment::Float(_) | + Fragment::AbsoluteOrFixedPositioned(_) | + Fragment::IFrame(_) => { + unreachable!( + "Found unexpected fragment type in outside list marker!" + ); + }, + } + .to_logical(containing_block_writing_mode) + .max_inline_position(), + ) + }); // Position the marker beyond the inline start of the border box list item. This needs to // take into account the border and padding of the item. @@ -269,13 +279,12 @@ impl OutsideMarker { start_corner: LogicalVec2 { inline: -max_inline_size - (pbm_of_list_item.border.inline_start + - pbm_of_list_item.padding.inline_start) - .into(), + pbm_of_list_item.padding.inline_start), block: Zero::zero(), }, size: LogicalVec2 { inline: max_inline_size, - block: flow_layout.content_block_size, + block: flow_layout.content_block_size.into(), }, }; @@ -286,10 +295,10 @@ impl OutsideMarker { base_fragment_info, self.marker_style.clone(), flow_layout.fragments, - content_rect.into(), - LogicalSides::zero(), - LogicalSides::zero(), - LogicalSides::zero(), + content_rect.to_physical(containing_block_writing_mode), + PhysicalSides::zero(), + PhysicalSides::zero(), + PhysicalSides::zero(), None, CollapsedBlockMargins::zero(), )) @@ -567,6 +576,7 @@ fn layout_block_level_children_in_parallel( placement_state.place_fragment_and_update_baseline(&mut fragment, None); child_positioning_context.adjust_static_position_of_hoisted_fragments( &fragment, + containing_block.style.writing_mode, PositioningContextLength::zero(), ); positioning_context.append(child_positioning_context); @@ -604,6 +614,7 @@ fn layout_block_level_children_sequentially( .place_fragment_and_update_baseline(&mut fragment, Some(sequential_layout_state)); positioning_context.adjust_static_position_of_hoisted_fragments( &fragment, + containing_block.style.writing_mode, positioning_context_length_before_layout, ); @@ -906,14 +917,15 @@ fn layout_in_flow_non_replaced_block_level_same_formatting_context( }, }; + let containing_block_writing_mode = containing_block.style.writing_mode; BoxFragment::new( base_fragment_info, style.clone(), flow_layout.fragments, - content_rect, - pbm.padding, - pbm.border, - margin, + content_rect.to_physical(containing_block_writing_mode), + pbm.padding.to_physical(containing_block_writing_mode), + pbm.border.to_physical(containing_block_writing_mode), + margin.to_physical(containing_block_writing_mode), clearance, block_margins_collapsed_with_children, ) @@ -991,15 +1003,15 @@ impl NonReplacedFormattingContext { }; let block_margins_collapsed_with_children = CollapsedBlockMargins::from_margin(&margin); - + let containing_block_writing_mode = containing_block.style.writing_mode; BoxFragment::new( self.base_fragment_info, self.style.clone(), layout.fragments, - content_rect, - pbm.padding, - pbm.border, - margin, + content_rect.to_physical(containing_block_writing_mode), + pbm.padding.to_physical(containing_block_writing_mode), + pbm.border.to_physical(containing_block_writing_mode), + margin.to_physical(containing_block_writing_mode), None, /* clearance */ block_margins_collapsed_with_children, ) @@ -1242,14 +1254,15 @@ impl NonReplacedFormattingContext { }; let block_margins_collapsed_with_children = CollapsedBlockMargins::from_margin(&margin); + let containing_block_writing_mode = containing_block.style.writing_mode; BoxFragment::new( self.base_fragment_info, self.style.clone(), layout.fragments, - content_rect, - pbm.padding, - pbm.border, - margin, + content_rect.to_physical(containing_block_writing_mode), + pbm.padding.to_physical(containing_block_writing_mode), + pbm.border.to_physical(containing_block_writing_mode), + margin.to_physical(containing_block_writing_mode), clearance, block_margins_collapsed_with_children, ) @@ -1274,7 +1287,10 @@ fn layout_in_flow_replaced_block_level( let margin_inline_end; let effective_margin_inline_start; let (margin_block_start, margin_block_end) = solve_block_margins_for_in_flow_block_level(&pbm); - let fragments = replaced.make_fragments(style, content_size); + + let containing_block_writing_mode = containing_block.style.writing_mode; + let physical_content_size = content_size.to_physical_size(containing_block_writing_mode); + let fragments = replaced.make_fragments(style, physical_content_size); let clearance; if let Some(ref mut sequential_layout_state) = sequential_layout_state { @@ -1341,10 +1357,10 @@ fn layout_in_flow_replaced_block_level( inline: pbm.padding.inline_start + pbm.border.inline_start + effective_margin_inline_start, }; - let content_rect = LogicalRect { - start_corner, - size: content_size, - }; + let content_rect = PhysicalRect::new( + start_corner.to_physical_point(containing_block_writing_mode), + physical_content_size, + ); let block_margins_collapsed_with_children = CollapsedBlockMargins::from_margin(&margin); BoxFragment::new( @@ -1352,9 +1368,9 @@ fn layout_in_flow_replaced_block_level( style.clone(), fragments, content_rect, - pbm.padding, - pbm.border, - margin, + pbm.padding.to_physical(containing_block_writing_mode), + pbm.border.to_physical(containing_block_writing_mode), + margin.to_physical(containing_block_writing_mode), clearance, block_margins_collapsed_with_children, ) @@ -1618,6 +1634,9 @@ struct PlacementState { /// least as tall as the marker size -- even though the marker doesn't advance the block /// position of the placement. marker_block_size: Option, + + /// The [`WritingMode`] of the containing fragment where these fragments are being laid out. + writing_mode: WritingMode, } impl PlacementState { @@ -1637,6 +1656,7 @@ impl PlacementState { inflow_baselines: Baselines::default(), is_inline_block_context, marker_block_size: None, + writing_mode: containing_block_style.writing_mode, } } @@ -1662,11 +1682,16 @@ impl PlacementState { return; } - let box_block_offset = box_fragment.content_rect.start_corner.block; - if let (None, Some(first)) = (self.inflow_baselines.first, box_fragment.baselines.first) { + let box_block_offset = box_fragment + .content_rect + .origin + .to_logical(self.writing_mode) + .block; + let box_fragment_baselines = box_fragment.baselines(self.writing_mode); + if let (None, Some(first)) = (self.inflow_baselines.first, box_fragment_baselines.first) { self.inflow_baselines.first = Some(first + box_block_offset); } - if let Some(last) = box_fragment.baselines.last { + if let Some(last) = box_fragment_baselines.last { self.inflow_baselines.last = Some(last + box_block_offset); } } @@ -1694,14 +1719,22 @@ impl PlacementState { .contains(FragmentFlags::IS_OUTSIDE_LIST_ITEM_MARKER); if is_outside_marker { assert!(self.marker_block_size.is_none()); - self.marker_block_size = Some(fragment.content_rect.size.block); + self.marker_block_size = Some( + fragment + .content_rect + .size + .to_logical(self.writing_mode) + .block, + ); return; } let fragment_block_margins = &fragment.block_margins_collapsed_with_children; - let mut fragment_block_size = fragment.padding.block_sum() + - fragment.border.block_sum() + - fragment.content_rect.size.block; + let mut fragment_block_size = fragment + .border_rect() + .to_logical(self.writing_mode) + .size + .block; // We use `last_in_flow_margin_collapses_with_parent_end_margin` to implement // this quote from https://drafts.csswg.org/css2/#collapsing-margins @@ -1737,8 +1770,12 @@ impl PlacementState { self.current_margin .adjoin_assign(&fragment_block_margins.start); } - fragment.content_rect.start_corner.block += - self.current_margin.solve() + self.current_block_direction_position; + + fragment.content_rect.origin += LogicalVec2 { + inline: Au::zero(), + block: self.current_margin.solve() + self.current_block_direction_position, + } + .to_physical_size(self.writing_mode); if fragment_block_margins.collapsed_through { // `fragment_block_size` is typically zero when collapsing through, @@ -1766,6 +1803,7 @@ impl PlacementState { self.current_block_direction_position + self.current_margin.solve(); sequential_layout_state.place_float_fragment( box_fragment, + self.writing_mode, self.start_margin, block_offset_from_containing_block_top, ); diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs index 0530de0b8f7..997392b29fd 100644 --- a/components/layout_2020/flow/root.rs +++ b/components/layout_2020/flow/root.rs @@ -353,9 +353,7 @@ impl BoxTree { let scrollable_overflow = root_fragments .iter() .fold(PhysicalRect::zero(), |acc, child| { - let child_overflow = child - .borrow() - .scrollable_overflow(&physical_containing_block); + let child_overflow = child.borrow().scrollable_overflow(); // https://drafts.csswg.org/css-overflow/#scrolling-direction // We want to clip scrollable overflow on box-start and inline-start 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, pub children: Vec>, - /// From the containing block’s start corner…? - /// This might be broken when the containing block is in a different writing mode: - /// - pub content_rect: LogicalRect, + /// 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, - pub padding: LogicalSides, - pub border: LogicalSides, - pub margin: LogicalSides, + pub padding: PhysicalSides, + pub border: PhysicalSides, + pub margin: PhysicalSides, /// 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, children: Vec, - content_rect: LogicalRect, - padding: LogicalSides, - border: LogicalSides, - margin: LogicalSides, + content_rect: PhysicalRect, + padding: PhysicalSides, + border: PhysicalSides, + margin: PhysicalSides, clearance: Option, block_margins_collapsed_with_children: CollapsedBlockMargins, ) -> BoxFragment { @@ -126,37 +126,19 @@ impl BoxFragment { base_fragment_info: BaseFragmentInfo, style: ServoArc, children: Vec, - content_rect: LogicalRect, - padding: LogicalSides, - border: LogicalSides, - margin: LogicalSides, + content_rect: PhysicalRect, + padding: PhysicalSides, + border: PhysicalSides, + margin: PhysicalSides, clearance: Option, block_margins_collapsed_with_children: CollapsedBlockMargins, overconstrained: PhysicalSize, ) -> 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) -> PhysicalRect { - 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 { + 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 { - self.content_rect.inflate(&self.padding) + pub(crate) fn padding_rect(&self) -> PhysicalRect { + self.content_rect.outer_rect(self.padding) } - pub(crate) fn border_rect(&self) -> LogicalRect { - self.padding_rect().inflate(&self.border) + pub(crate) fn border_rect(&self) -> PhysicalRect { + self.padding_rect().outer_rect(self.border) } - pub(crate) fn margin_rect(&self) -> LogicalRect { - self.border_rect().inflate(&self.margin) + pub(crate) fn margin_rect(&self) -> PhysicalRect { + 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, - ) -> PhysicalRect { - let mut overflow = self - .border_rect() - .to_physical(self.style.writing_mode, containing_block); - + pub fn scrollable_overflow_for_parent(&self) -> PhysicalRect { + 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; diff --git a/components/layout_2020/fragment_tree/fragment.rs b/components/layout_2020/fragment_tree/fragment.rs index 8456ef3eec6..111e8009b6c 100644 --- a/components/layout_2020/fragment_tree/fragment.rs +++ b/components/layout_2020/fragment_tree/fragment.rs @@ -20,7 +20,7 @@ use super::{ Tag, }; use crate::cell::ArcRefCell; -use crate::geom::{LogicalRect, LogicalSides, PhysicalRect}; +use crate::geom::{LogicalSides, PhysicalRect}; use crate::style_ext::ComputedValuesExt; #[derive(Serialize)] @@ -64,7 +64,7 @@ pub(crate) struct TextFragment { pub base: BaseFragment, #[serde(skip_serializing)] pub parent_style: ServoArc, - pub rect: LogicalRect, + pub rect: PhysicalRect, pub font_metrics: FontMetrics, #[serde(skip_serializing)] pub font_key: FontInstanceKey, @@ -82,7 +82,7 @@ pub(crate) struct ImageFragment { pub base: BaseFragment, #[serde(skip_serializing)] pub style: ServoArc, - pub rect: LogicalRect, + pub rect: PhysicalRect, #[serde(skip_serializing)] pub image_key: ImageKey, } @@ -92,7 +92,7 @@ pub(crate) struct IFrameFragment { pub base: BaseFragment, pub pipeline_id: PipelineId, pub browsing_context_id: BrowsingContextId, - pub rect: LogicalRect, + pub rect: PhysicalRect, #[serde(skip_serializing)] pub style: ServoArc, } @@ -135,28 +135,22 @@ impl Fragment { pub fn scrolling_area(&self, containing_block: &PhysicalRect) -> PhysicalRect { match self { Fragment::Box(fragment) | Fragment::Float(fragment) => fragment - .scrollable_overflow(containing_block) + .scrollable_overflow() .translate(containing_block.origin.to_vector()), - _ => self.scrollable_overflow(containing_block), + _ => self.scrollable_overflow(), } } - pub fn scrollable_overflow(&self, containing_block: &PhysicalRect) -> PhysicalRect { + pub fn scrollable_overflow(&self) -> PhysicalRect { match self { Fragment::Box(fragment) | Fragment::Float(fragment) => { - fragment.scrollable_overflow_for_parent(containing_block) + fragment.scrollable_overflow_for_parent() }, Fragment::AbsoluteOrFixedPositioned(_) => PhysicalRect::zero(), Fragment::Positioning(fragment) => fragment.scrollable_overflow, - Fragment::Text(fragment) => fragment - .rect - .to_physical(fragment.parent_style.writing_mode, containing_block), - Fragment::Image(fragment) => fragment - .rect - .to_physical(fragment.style.writing_mode, containing_block), - Fragment::IFrame(fragment) => fragment - .rect - .to_physical(fragment.style.writing_mode, containing_block), + Fragment::Text(fragment) => fragment.rect, + Fragment::Image(fragment) => fragment.rect, + Fragment::IFrame(fragment) => fragment.rect, } } @@ -175,11 +169,9 @@ impl Fragment { Fragment::Box(fragment) | Fragment::Float(fragment) => { let content_rect = fragment .content_rect - .to_physical(fragment.style.writing_mode, containing_block) .translate(containing_block.origin.to_vector()); let padding_rect = fragment .padding_rect() - .to_physical(fragment.style.writing_mode, containing_block) .translate(containing_block.origin.to_vector()); let new_manager = if fragment .style @@ -201,10 +193,7 @@ impl Fragment { .find_map(|child| child.borrow().find(&new_manager, level + 1, process_func)) }, Fragment::Positioning(fragment) => { - let content_rect = fragment - .rect - .to_physical(fragment.writing_mode, containing_block) - .translate(containing_block.origin.to_vector()); + let content_rect = fragment.rect.translate(containing_block.origin.to_vector()); let new_manager = manager.new_for_non_absolute_descendants(&content_rect); fragment .children diff --git a/components/layout_2020/fragment_tree/fragment_tree.rs b/components/layout_2020/fragment_tree/fragment_tree.rs index 107bd3e36da..5394f08cc33 100644 --- a/components/layout_2020/fragment_tree/fragment_tree.rs +++ b/components/layout_2020/fragment_tree/fragment_tree.rs @@ -110,15 +110,9 @@ impl FragmentTree { } let fragment_relative_rect = match fragment { - Fragment::Box(fragment) | Fragment::Float(fragment) => fragment - .border_rect() - .to_physical(fragment.style.writing_mode, containing_block), - Fragment::Positioning(fragment) => fragment - .rect - .to_physical(fragment.writing_mode, containing_block), - Fragment::Text(fragment) => fragment - .rect - .to_physical(fragment.parent_style.writing_mode, containing_block), + Fragment::Box(fragment) | Fragment::Float(fragment) => fragment.border_rect(), + Fragment::Positioning(fragment) => fragment.rect, + Fragment::Text(fragment) => fragment.rect, Fragment::AbsoluteOrFixedPositioned(_) | Fragment::Image(_) | Fragment::IFrame(_) => return None, @@ -134,7 +128,7 @@ impl FragmentTree { pub fn get_border_dimensions_for_node(&self, requested_node: OpaqueNode) -> Rect { let tag_to_find = Tag::new(requested_node); - self.find(|fragment, _, containing_block| { + self.find(|fragment, _, _containing_block| { if fragment.tag() != Some(tag_to_find) { return None; } @@ -151,18 +145,13 @@ impl FragmentTree { } let border = fragment.style.get_border(); - let padding_rect = fragment - .padding_rect() - .to_physical(fragment.style.writing_mode, containing_block); + let padding_rect = fragment.padding_rect(); Rect::new( Point2D::new(border.border_left_width, border.border_top_width), Size2D::new(padding_rect.size.width, padding_rect.size.height), ) }, - Fragment::Positioning(fragment) => fragment - .rect - .to_physical(fragment.writing_mode, containing_block) - .cast_unit(), + Fragment::Positioning(fragment) => fragment.rect.cast_unit(), _ => return None, }; diff --git a/components/layout_2020/fragment_tree/positioning_fragment.rs b/components/layout_2020/fragment_tree/positioning_fragment.rs index d9a1f46ec18..3d2238f748e 100644 --- a/components/layout_2020/fragment_tree/positioning_fragment.rs +++ b/components/layout_2020/fragment_tree/positioning_fragment.rs @@ -6,12 +6,11 @@ use app_units::Au; use base::print_tree::PrintTree; use serde::Serialize; use servo_arc::Arc as ServoArc; -use style::logical_geometry::WritingMode; use style::properties::ComputedValues; use super::{BaseFragment, BaseFragmentInfo, Fragment}; use crate::cell::ArcRefCell; -use crate::geom::{LogicalRect, PhysicalRect}; +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 @@ -19,10 +18,8 @@ use crate::geom::{LogicalRect, PhysicalRect}; #[derive(Serialize)] pub(crate) struct PositioningFragment { pub base: BaseFragment, - pub rect: LogicalRect, + pub rect: PhysicalRect, pub children: Vec>, - pub writing_mode: WritingMode, - /// The scrollable overflow of this anonymous fragment's children. pub scrollable_overflow: PhysicalRect, @@ -32,44 +29,29 @@ pub(crate) struct PositioningFragment { } impl PositioningFragment { - pub fn new_anonymous( - rect: LogicalRect, - children: Vec, - mode: WritingMode, - ) -> Self { - Self::new_with_base_fragment(BaseFragment::anonymous(), None, rect, children, mode) + pub fn new_anonymous(rect: PhysicalRect, children: Vec) -> Self { + Self::new_with_base_fragment(BaseFragment::anonymous(), None, rect, children) } pub fn new_empty( base_fragment_info: BaseFragmentInfo, - rect: LogicalRect, + rect: PhysicalRect, style: ServoArc, ) -> Self { - let writing_mode = style.writing_mode; - Self::new_with_base_fragment( - base_fragment_info.into(), - Some(style), - rect, - Vec::new(), - writing_mode, - ) + Self::new_with_base_fragment(base_fragment_info.into(), Some(style), rect, Vec::new()) } fn new_with_base_fragment( base: BaseFragment, style: Option>, - rect: LogicalRect, + rect: PhysicalRect, children: Vec, - mode: WritingMode, ) -> Self { - // 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 content_origin = rect.start_corner.to_physical(mode); + let content_origin = rect.origin; let scrollable_overflow = children.iter().fold(PhysicalRect::zero(), |acc, child| { acc.union( &child - .scrollable_overflow(&containing_block) + .scrollable_overflow() .translate(content_origin.to_vector()), ) }); @@ -78,7 +60,6 @@ impl PositioningFragment { style, rect, children: children.into_iter().map(ArcRefCell::new).collect(), - writing_mode: mode, scrollable_overflow, } } diff --git a/components/layout_2020/geom.rs b/components/layout_2020/geom.rs index 47a49c2b937..0b0aacbe249 100644 --- a/components/layout_2020/geom.rs +++ b/components/layout_2020/geom.rs @@ -71,6 +71,19 @@ impl LogicalVec2 { } } + pub fn from_physical_point(physical_point: &PhysicalPoint, mode: WritingMode) -> Self { + // https://drafts.csswg.org/css-writing-modes/#logical-to-physical + let (i, b) = if mode.is_horizontal() { + (&physical_point.x, &physical_point.y) + } else { + (&physical_point.y, &physical_point.x) + }; + LogicalVec2 { + inline: i.clone(), + block: b.clone(), + } + } + pub fn map(&self, f: impl Fn(&T) -> U) -> LogicalVec2 { LogicalVec2 { inline: f(&self.inline), @@ -195,7 +208,7 @@ impl fmt::Debug for LogicalRect { } impl LogicalVec2 { - pub fn to_physical(&self, mode: WritingMode) -> PhysicalSize { + pub fn to_physical_size(&self, mode: WritingMode) -> PhysicalSize { // https://drafts.csswg.org/css-writing-modes/#logical-to-physical let (x, y) = if mode.is_horizontal() { (&self.inline, &self.block) @@ -204,6 +217,16 @@ impl LogicalVec2 { }; PhysicalSize::new(x.clone(), y.clone()) } + + pub fn to_physical_point(&self, mode: WritingMode) -> PhysicalPoint { + // https://drafts.csswg.org/css-writing-modes/#logical-to-physical + let (x, y) = if mode.is_horizontal() { + (&self.inline, &self.block) + } else { + (&self.block, &self.inline) + }; + PhysicalPoint::new(x.clone(), y.clone()) + } } impl LogicalSides { @@ -464,14 +487,7 @@ impl LogicalRect { } } - pub fn to_physical( - &self, - mode: WritingMode, - // Will be needed for other writing modes - // FIXME: what if the containing block has a different mode? - // https://drafts.csswg.org/css-writing-modes/#orthogonal-flows - _containing_block: &PhysicalRect, - ) -> PhysicalRect + pub fn to_physical(&self, mode: WritingMode) -> PhysicalRect where T: Clone, { @@ -482,7 +498,7 @@ impl LogicalRect { }; PhysicalRect::new( PhysicalPoint::new(tl_x.clone(), tl_y.clone()), - self.size.to_physical(mode), + self.size.to_physical_size(mode), ) } } @@ -522,3 +538,37 @@ impl From> for LogicalRect { } } } + +pub(crate) trait ToLogical { + fn to_logical(&self, writing_mode: WritingMode) -> LogicalType; +} + +impl ToLogical> for PhysicalRect { + fn to_logical(&self, writing_mode: WritingMode) -> LogicalRect { + LogicalRect { + start_corner: LogicalVec2::from_physical_size( + &PhysicalSize::new(self.origin.x, self.origin.y), + writing_mode, + ), + size: LogicalVec2::from_physical_size(&self.size, writing_mode), + } + } +} + +impl ToLogical> for PhysicalSize { + fn to_logical(&self, writing_mode: WritingMode) -> LogicalVec2 { + LogicalVec2::from_physical_size(self, writing_mode) + } +} + +impl ToLogical> for PhysicalPoint { + fn to_logical(&self, writing_mode: WritingMode) -> LogicalVec2 { + LogicalVec2::from_physical_point(self, writing_mode) + } +} + +impl ToLogical> for PhysicalSides { + fn to_logical(&self, writing_mode: WritingMode) -> LogicalSides { + LogicalSides::from_physical(self, writing_mode) + } +} diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index b23f76db69b..9232766031e 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -7,6 +7,7 @@ use rayon::iter::IntoParallelRefMutIterator; use rayon::prelude::{IndexedParallelIterator, ParallelIterator}; use serde::Serialize; use style::computed_values::position::T as Position; +use style::logical_geometry::WritingMode; use style::properties::ComputedValues; use style::values::computed::Length; use style::values::specified::text::TextDecorationLine; @@ -23,6 +24,7 @@ use crate::fragment_tree::{ }; use crate::geom::{ AuOrAuto, LengthOrAuto, LengthPercentageOrAuto, LogicalRect, LogicalSides, LogicalVec2, + PhysicalPoint, PhysicalRect, ToLogical, }; use crate::style_ext::{ComputedValuesExt, DisplayInside}; use crate::{ContainingBlock, DefiniteContainingBlock}; @@ -176,15 +178,17 @@ impl PositioningContext { pub(crate) fn adjust_static_position_of_hoisted_fragments( &mut self, parent_fragment: &Fragment, + parent_fragment_writing_mode: WritingMode, index: PositioningContextLength, ) { let start_offset = match &parent_fragment { - Fragment::Box(b) | Fragment::Float(b) => &b.content_rect.start_corner, + Fragment::Box(fragment) | Fragment::Float(fragment) => &fragment.content_rect.origin, Fragment::AbsoluteOrFixedPositioned(_) => return, - Fragment::Positioning(a) => &a.rect.start_corner, + Fragment::Positioning(fragment) => &fragment.rect.origin, _ => unreachable!(), - }; - self.adjust_static_position_of_hoisted_fragments_with_offset(start_offset, index); + } + .to_logical(parent_fragment_writing_mode); + self.adjust_static_position_of_hoisted_fragments_with_offset(&start_offset, index); } /// See documentation for [PositioningContext::adjust_static_position_of_hoisted_fragments]. @@ -240,7 +244,8 @@ impl PositioningContext { self.append(new_context); if style.clone_position() == Position::Relative { - new_fragment.content_rect.start_corner += relative_adjustement(style, containing_block); + new_fragment.content_rect.origin += relative_adjustement(style, containing_block) + .to_physical_size(containing_block.style.writing_mode) } new_fragment @@ -253,14 +258,16 @@ impl PositioningContext { layout_context: &LayoutContext, new_fragment: &mut BoxFragment, ) { - let padding_rect = LogicalRect { - size: new_fragment.content_rect.size, + let padding_rect = PhysicalRect::new( // Ignore the content rect’s position in its own containing block: - start_corner: LogicalVec2::zero(), - } - .inflate(&new_fragment.padding); + PhysicalPoint::origin(), + new_fragment.content_rect.size, + ) + .outer_rect(new_fragment.padding); let containing_block = DefiniteContainingBlock { - size: padding_rect.size, + size: padding_rect + .size + .to_logical(new_fragment.style.writing_mode), style: &new_fragment.style, }; @@ -479,6 +486,7 @@ impl HoistedAbsolutelyPositionedBox { let cbis = containing_block.size.inline; let cbbs = containing_block.size.block; let mut absolutely_positioned_box = self.absolutely_positioned_box.borrow_mut(); + let containing_block_writing_mode = containing_block.style.writing_mode; let pbm = absolutely_positioned_box .context .style() @@ -543,7 +551,10 @@ impl HoistedAbsolutelyPositionedBox { // https://drafts.csswg.org/css2/visudet.html#abs-replaced-height let style = &replaced.style; content_size = computed_size.auto_is(|| unreachable!()).into(); - fragments = replaced.contents.make_fragments(style, content_size); + fragments = replaced.contents.make_fragments( + style, + content_size.to_physical_size(containing_block_writing_mode), + ); }, IndependentFormattingContext::NonReplaced(non_replaced) => { // https://drafts.csswg.org/css2/#min-max-widths @@ -711,16 +722,16 @@ impl HoistedAbsolutelyPositionedBox { }; let physical_overconstrained = - overconstrained.to_physical(containing_block.style.writing_mode); + overconstrained.to_physical_size(containing_block.style.writing_mode); BoxFragment::new_with_overconstrained( absolutely_positioned_box.context.base_fragment_info(), absolutely_positioned_box.context.style().clone(), fragments, - content_rect, - pbm.padding, - pbm.border, - margin, + content_rect.to_physical(containing_block_writing_mode), + pbm.padding.to_physical(containing_block_writing_mode), + pbm.border.to_physical(containing_block_writing_mode), + margin.to_physical(containing_block_writing_mode), None, /* clearance */ // We do not set the baseline offset, because absolutely positioned // elements are not inflow. @@ -736,7 +747,10 @@ impl HoistedAbsolutelyPositionedBox { // other elements. If any of them have a static start position though, we need to // adjust it to account for the start corner of this absolute. positioning_context.adjust_static_position_of_hoisted_fragments_with_offset( - &new_fragment.content_rect.start_corner, + &new_fragment + .content_rect + .origin + .to_logical(containing_block_writing_mode), PositioningContextLength::zero(), ); diff --git a/components/layout_2020/query.rs b/components/layout_2020/query.rs index 32b01154227..baad3cbb285 100644 --- a/components/layout_2020/query.rs +++ b/components/layout_2020/query.rs @@ -198,21 +198,13 @@ pub fn process_resolved_style_request<'dom>( _ => {}, } } - let content_rect = box_fragment - .content_rect - .to_physical(box_fragment.style.writing_mode, containing_block); - let margins = box_fragment - .margin - .to_physical(box_fragment.style.writing_mode); - let padding = box_fragment - .padding - .to_physical(box_fragment.style.writing_mode); + let content_rect = box_fragment.content_rect; + let margins = box_fragment.margin; + let padding = box_fragment.padding; (content_rect, margins, padding) }, Fragment::Positioning(positioning_fragment) => { - let content_rect = positioning_fragment - .rect - .to_physical(positioning_fragment.writing_mode, containing_block); + let content_rect = positioning_fragment.rect; (content_rect, SideOffsets2D::zero(), SideOffsets2D::zero()) }, _ => return None, @@ -370,15 +362,9 @@ fn process_offset_parent_query_inner( // // [1]: https://github.com/w3c/csswg-drafts/issues/4541 let fragment_relative_rect = match fragment { - Fragment::Box(fragment) | Fragment::Float(fragment) => fragment - .border_rect() - .to_physical(fragment.style.writing_mode, containing_block), - Fragment::Text(fragment) => fragment - .rect - .to_physical(fragment.parent_style.writing_mode, containing_block), - Fragment::Positioning(fragment) => fragment - .rect - .to_physical(fragment.writing_mode, containing_block), + Fragment::Box(fragment) | Fragment::Float(fragment) => fragment.border_rect(), + Fragment::Text(fragment) => fragment.rect, + Fragment::Positioning(fragment) => fragment.rect, Fragment::AbsoluteOrFixedPositioned(_) | Fragment::Image(_) | Fragment::IFrame(_) => unreachable!(), @@ -461,12 +447,9 @@ fn process_offset_parent_query_inner( Fragment::Box(fragment) | Fragment::Float(fragment) => { if fragment.base.tag == Some(offset_parent_node_tag) { // Again, take the *first* associated CSS layout box. - let padding_box_corner = fragment - .padding_rect() - .to_physical(fragment.style.writing_mode, containing_block) - .origin - .to_vector() + - containing_block.origin.to_vector(); + let padding_box_corner = + fragment.padding_rect().origin.to_vector() + + containing_block.origin.to_vector(); let padding_box_corner = padding_box_corner.to_untyped(); Some(padding_box_corner) } else { diff --git a/components/layout_2020/replaced.rs b/components/layout_2020/replaced.rs index fc07b6da746..72f58daf71a 100644 --- a/components/layout_2020/replaced.rs +++ b/components/layout_2020/replaced.rs @@ -27,7 +27,7 @@ use webrender_api::ImageKey; use crate::context::LayoutContext; use crate::dom::NodeExt; use crate::fragment_tree::{BaseFragmentInfo, Fragment, IFrameFragment, ImageFragment}; -use crate::geom::{LogicalRect, LogicalVec2, PhysicalSize}; +use crate::geom::{LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSize}; use crate::sizing::ContentSizes; use crate::style_ext::{Clamp, ComputedValuesExt, PaddingBorderMargin}; use crate::{AuOrAuto, ContainingBlock}; @@ -268,8 +268,9 @@ impl ReplacedContent { pub fn make_fragments( &self, style: &ServoArc, - size: LogicalVec2, + size: PhysicalSize, ) -> Vec { + let rect = PhysicalRect::new(PhysicalPoint::origin(), size); match &self.kind { ReplacedContentKind::Image(image) => image .as_ref() @@ -278,10 +279,7 @@ impl ReplacedContent { Fragment::Image(ImageFragment { base: self.base_fragment_info.into(), style: style.clone(), - rect: LogicalRect { - start_corner: LogicalVec2::zero(), - size, - }, + rect, image_key, }) }) @@ -290,10 +288,7 @@ impl ReplacedContent { ReplacedContentKind::Video(video) => vec![Fragment::Image(ImageFragment { base: self.base_fragment_info.into(), style: style.clone(), - rect: LogicalRect { - start_corner: LogicalVec2::zero(), - size, - }, + rect, image_key: video.image_key, })], ReplacedContentKind::IFrame(iframe) => { @@ -302,10 +297,7 @@ impl ReplacedContent { style: style.clone(), pipeline_id: iframe.pipeline_id, browsing_context_id: iframe.browsing_context_id, - rect: LogicalRect { - start_corner: LogicalVec2::zero(), - size, - }, + rect, })] }, ReplacedContentKind::Canvas(canvas_info) => { @@ -336,10 +328,7 @@ impl ReplacedContent { vec![Fragment::Image(ImageFragment { base: self.base_fragment_info.into(), style: style.clone(), - rect: LogicalRect { - start_corner: LogicalVec2::zero(), - size, - }, + rect, image_key, })] }, diff --git a/components/layout_2020/table/layout.rs b/components/layout_2020/table/layout.rs index 5e49e9e194e..8491e0e7301 100644 --- a/components/layout_2020/table/layout.rs +++ b/components/layout_2020/table/layout.rs @@ -27,7 +27,10 @@ use crate::fragment_tree::{ BaseFragmentInfo, BoxFragment, CollapsedBlockMargins, ExtraBackground, Fragment, FragmentFlags, PositioningFragment, }; -use crate::geom::{AuOrAuto, LengthPercentageOrAuto, LogicalRect, LogicalSides, LogicalVec2}; +use crate::geom::{ + AuOrAuto, LengthPercentageOrAuto, LogicalRect, LogicalSides, LogicalVec2, PhysicalSides, + ToLogical, +}; use crate::positioned::{relative_adjustement, PositioningContext, PositioningContextLength}; use crate::sizing::ContentSizes; use crate::style_ext::{Clamp, ComputedValuesExt, PaddingBorderMargin}; @@ -1539,10 +1542,15 @@ impl<'a> TableLayout<'a> { None, /* sequential_layout_state */ ); - box_fragment.content_rect.start_corner.block += box_fragment - .block_margins_collapsed_with_children - .start - .solve(); + let margin_offset = LogicalVec2 { + inline: Au::zero(), + block: box_fragment + .block_margins_collapsed_with_children + .start + .solve(), + } + .to_physical_size(containing_block.style.writing_mode); + box_fragment.content_rect.origin += margin_offset; if let Some(positioning_context) = positioning_context.take() { parent_positioning_context.append(positioning_context); @@ -1593,6 +1601,7 @@ impl<'a> TableLayout<'a> { content_inline_size_for_table: None, baselines: Baselines::default(), }; + let table_writing_mode = containing_block_for_children.style.writing_mode; table_layout .fragments @@ -1610,14 +1619,22 @@ impl<'a> TableLayout<'a> { positioning_context, ); - caption_fragment.content_rect.start_corner.inline += - offset_from_wrapper.inline_start; - caption_fragment.content_rect.start_corner.block += current_block_offset; - current_block_offset += caption_fragment.margin_rect().size.block; + let caption_offset = LogicalVec2 { + inline: offset_from_wrapper.inline_start, + block: current_block_offset, + } + .to_physical_size(table_writing_mode); + caption_fragment.content_rect.origin += caption_offset; + current_block_offset += caption_fragment + .margin_rect() + .size + .to_logical(table_writing_mode) + .block; let caption_fragment = Fragment::Box(caption_fragment); positioning_context.adjust_static_position_of_hoisted_fragments( &caption_fragment, + table_writing_mode, original_positioning_context_length, ); Some(caption_fragment) @@ -1634,18 +1651,27 @@ impl<'a> TableLayout<'a> { // Take the baseline of the grid fragment, after adjusting it to be in the coordinate system // of the table wrapper. + let logical_grid_content_rect = grid_fragment.content_rect.to_logical(table_writing_mode); table_layout.baselines = grid_fragment - .baselines - .offset(current_block_offset + grid_fragment.content_rect.start_corner.block); + .baselines(table_writing_mode) + .offset(current_block_offset + logical_grid_content_rect.start_corner.block); - grid_fragment.content_rect.start_corner.inline += offset_from_wrapper.inline_start; - grid_fragment.content_rect.start_corner.block += current_block_offset; - current_block_offset += grid_fragment.border_rect().size.block; - table_layout.content_inline_size_for_table = Some(grid_fragment.content_rect.size.inline); + grid_fragment.content_rect.origin += LogicalVec2 { + inline: offset_from_wrapper.inline_start, + block: current_block_offset, + } + .to_physical_size(table_writing_mode); + current_block_offset += grid_fragment + .border_rect() + .size + .to_logical(table_writing_mode) + .block; + table_layout.content_inline_size_for_table = Some(logical_grid_content_rect.size.inline); let grid_fragment = Fragment::Box(grid_fragment); positioning_context.adjust_static_position_of_hoisted_fragments( &grid_fragment, + table_writing_mode, original_positioning_context_length, ); table_layout.fragments.push(grid_fragment); @@ -1666,14 +1692,22 @@ impl<'a> TableLayout<'a> { positioning_context, ); - caption_fragment.content_rect.start_corner.inline += - offset_from_wrapper.inline_start; - caption_fragment.content_rect.start_corner.block += current_block_offset; - current_block_offset += caption_fragment.margin_rect().size.block; + let caption_offset = LogicalVec2 { + inline: offset_from_wrapper.inline_start, + block: current_block_offset, + } + .to_physical_size(containing_block_for_children.style.writing_mode); + caption_fragment.content_rect.origin += caption_offset; + current_block_offset += caption_fragment + .margin_rect() + .size + .to_logical(table_writing_mode) + .block; let caption_fragment = Fragment::Box(caption_fragment); positioning_context.adjust_static_position_of_hoisted_fragments( &caption_fragment, + table_writing_mode, original_positioning_context_length, ); Some(caption_fragment) @@ -1710,6 +1744,7 @@ impl<'a> TableLayout<'a> { assert_eq!(self.table.size.height, self.row_sizes.len()); assert_eq!(self.table.size.width, self.distributed_column_widths.len()); + let table_writing_mode = containing_block_for_children.style.writing_mode; if self.table.size.width == 0 && self.table.size.height == 0 { let content_rect = LogicalRect { start_corner: table_pbm.border_padding_start(), @@ -1717,15 +1752,16 @@ impl<'a> TableLayout<'a> { inline: self.table_width, block: self.final_table_height, }, - }; + } + .to_physical(table_writing_mode); return BoxFragment::new( self.table.grid_base_fragment_info, self.table.grid_style.clone(), Vec::new(), content_rect, - table_pbm.padding, - table_pbm.border, - LogicalSides::zero(), + table_pbm.padding.to_physical(table_writing_mode), + table_pbm.border.to_physical(table_writing_mode), + PhysicalSides::zero(), None, /* clearance */ CollapsedBlockMargins::zero(), ); @@ -1845,15 +1881,16 @@ impl<'a> TableLayout<'a> { inline: table_and_track_dimensions.table_rect.max_inline_position(), block: table_and_track_dimensions.table_rect.max_block_position(), }, - }; + } + .to_physical(table_writing_mode); BoxFragment::new( self.table.grid_base_fragment_info, self.table.grid_style.clone(), table_fragments, content_rect, - table_pbm.padding, - table_pbm.border, - LogicalSides::zero(), + table_pbm.padding.to_physical(table_writing_mode), + table_pbm.border.to_physical(table_writing_mode), + PhysicalSides::zero(), None, /* clearance */ CollapsedBlockMargins::zero(), ) @@ -1987,11 +2024,14 @@ impl<'a> TableLayout<'a> { dimensions: &TableAndTrackDimensions, fragments: &mut Vec, ) { + let table_writing_mode = self.table.style.writing_mode; for column_group in self.table.column_groups.iter() { if !column_group.is_empty() { fragments.push(Fragment::Positioning(PositioningFragment::new_empty( column_group.base_fragment_info, - dimensions.get_column_group_rect(column_group), + dimensions + .get_column_group_rect(column_group) + .to_physical(table_writing_mode), column_group.style.clone(), ))); } @@ -2000,7 +2040,9 @@ impl<'a> TableLayout<'a> { for (column_index, column) in self.table.columns.iter().enumerate() { fragments.push(Fragment::Positioning(PositioningFragment::new_empty( column.base_fragment_info, - dimensions.get_column_rect(column_index), + dimensions + .get_column_rect(column_index) + .to_physical(table_writing_mode), column.style.clone(), ))); } @@ -2105,11 +2147,11 @@ impl<'a> RowFragmentLayout<'a> { self.row.base_fragment_info, self.row.style.clone(), self.fragments, - self.rect, - LogicalSides::zero(), /* padding */ - LogicalSides::zero(), /* border */ - LogicalSides::zero(), /* margin */ - None, /* clearance */ + self.rect.to_physical(containing_block.style.writing_mode), + PhysicalSides::zero(), /* padding */ + PhysicalSides::zero(), /* border */ + PhysicalSides::zero(), /* margin */ + None, /* clearance */ CollapsedBlockMargins::zero(), ); row_fragment.set_does_not_paint_background(); @@ -2168,11 +2210,11 @@ impl RowGroupFragmentLayout { self.base_fragment_info, self.style, self.fragments, - self.rect, - LogicalSides::zero(), /* padding */ - LogicalSides::zero(), /* border */ - LogicalSides::zero(), /* margin */ - None, /* clearance */ + self.rect.to_physical(containing_block.style.writing_mode), + PhysicalSides::zero(), /* padding */ + PhysicalSides::zero(), /* border */ + PhysicalSides::zero(), /* margin */ + None, /* clearance */ CollapsedBlockMargins::zero(), ); row_group_fragment.set_does_not_paint_background(); @@ -2526,9 +2568,8 @@ impl TableSlotCell { block: vertical_align_offset, }; let vertical_align_fragment = PositioningFragment::new_anonymous( - vertical_align_fragment_rect, + vertical_align_fragment_rect.to_physical(table_style.writing_mode), layout.layout.fragments, - self.style.writing_mode, ); // Adjust the static position of all absolute children based on the @@ -2550,11 +2591,11 @@ impl TableSlotCell { base_fragment_info, self.style.clone(), vec![Fragment::Positioning(vertical_align_fragment)], - cell_content_rect, - layout.padding, - layout.border, - LogicalSides::zero(), /* margin */ - None, /* clearance */ + cell_content_rect.to_physical(table_style.writing_mode), + layout.padding.to_physical(table_style.writing_mode), + layout.border.to_physical(table_style.writing_mode), + PhysicalSides::zero(), /* margin */ + None, /* clearance */ CollapsedBlockMargins::zero(), ) .with_baselines(layout.layout.baselines)