mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
layout: Convert the FragmentTree to physical geometry (#33030)
This converts all geometry in the FragmentTree into physical geometry, doing conversions ahead of time instead of when traversing the fragment tree. This is necessary to properly implement BiDi in Servo as we need to know what side borders are on in mixed RTL and LTR contexts. In addition, fragments are laid out in a particular context and only that context knows its writing mode. There were issues where were using one writing mode to lay out and another to convert to phyisical coordinates. This isn't an issue now since we only use the default writing mode, but starts to be an issue with BiDi text. Closes #25564. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
65f90ff1fd
commit
d941d2fd67
17 changed files with 502 additions and 432 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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<CollapsibleWithParentStartMargin>,
|
||||
) -> 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<Au>,
|
||||
|
||||
/// 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,
|
||||
);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue