layout: Prepare for bidi by guarding all access to writing-mode (#33082)

We want to selectively enable right-to-left writing modes per layout
context. This change makes that possible by allowing access to
`writing-mode` though an interface that always returns the default
horizontal top-to-bottom (implicitly left-to-right) writing mode.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Rakhi Sharma <atbrakhi@igalia.com>
This commit is contained in:
Martin Robinson 2024-08-16 13:38:04 +02:00 committed by GitHub
parent 3d3621b652
commit 0d94a8acd2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 129 additions and 88 deletions

View file

@ -710,7 +710,7 @@ impl<'a> BuilderForBoxFragment<'a> {
painting_area_override: None, painting_area_override: None,
positioning_area_override: Some( positioning_area_override: Some(
positioning_area positioning_area
.to_physical(self.fragment.style.writing_mode) .to_physical(self.fragment.style.effective_writing_mode())
.translate(self.containing_block.origin.to_vector()) .translate(self.containing_block.origin.to_vector())
.to_webrender(), .to_webrender(),
), ),

View file

@ -266,7 +266,7 @@ impl FlexContainer {
let mut sum_of_flex_shrink_factors = 0.0; let mut sum_of_flex_shrink_factors = 0.0;
let mut item_infos = vec![]; let mut item_infos = vec![];
let container_is_horizontal = self.style.writing_mode.is_horizontal(); let container_is_horizontal = self.style.effective_writing_mode().is_horizontal();
let flex_direction = used_flex_direction(&self.style); let flex_direction = used_flex_direction(&self.style);
let flex_axis = FlexAxis::from(flex_direction); let flex_axis = FlexAxis::from(flex_direction);
let flex_wrap = self.style.get_position().flex_wrap; let flex_wrap = self.style.get_position().flex_wrap;
@ -723,8 +723,8 @@ impl FlexContainer {
all_baselines.last = line_all_baselines.last; all_baselines.last = line_all_baselines.last;
} }
let physical_line_position = let physical_line_position = flow_relative_line_position
flow_relative_line_position.to_physical_size(self.style.writing_mode); .to_physical_size(self.style.effective_writing_mode());
for (fragment, _) in &mut final_line_layout.item_fragments { for (fragment, _) in &mut final_line_layout.item_fragments {
fragment.content_rect.origin += physical_line_position; fragment.content_rect.origin += physical_line_position;
} }
@ -754,7 +754,7 @@ impl FlexContainer {
let fragment = Fragment::Box(fragment); let fragment = Fragment::Box(fragment);
child_positioning_context.adjust_static_position_of_hoisted_fragments( child_positioning_context.adjust_static_position_of_hoisted_fragments(
&fragment, &fragment,
self.style.writing_mode, self.style.effective_writing_mode(),
PositioningContextLength::zero(), PositioningContextLength::zero(),
); );
positioning_context.append(child_positioning_context); positioning_context.append(child_positioning_context);
@ -857,13 +857,13 @@ impl<'a> FlexItem<'a> {
// https://drafts.csswg.org/css-writing-modes/#orthogonal-flows // https://drafts.csswg.org/css-writing-modes/#orthogonal-flows
assert_eq!( assert_eq!(
containing_block.style.writing_mode, containing_block.effective_writing_mode(),
box_.style().writing_mode, box_.style().effective_writing_mode(),
"Mixed writing modes are not supported yet" "Mixed writing modes are not supported yet"
); );
let container_is_horizontal = containing_block.style.writing_mode.is_horizontal(); let container_is_horizontal = containing_block.effective_writing_mode().is_horizontal();
let item_is_horizontal = box_.style().writing_mode.is_horizontal(); let item_is_horizontal = box_.style().effective_writing_mode().is_horizontal();
let cross_axis_is_item_block_axis = cross_axis_is_item_block_axis( let cross_axis_is_item_block_axis = cross_axis_is_item_block_axis(
container_is_horizontal, container_is_horizontal,
item_is_horizontal, item_is_horizontal,
@ -1592,7 +1592,7 @@ impl InitialFlexLineLayout<'_> {
let mut fragment_info = item.box_.base_fragment_info(); let mut fragment_info = item.box_.base_fragment_info();
fragment_info.flags.insert(FragmentFlags::IS_FLEX_ITEM); fragment_info.flags.insert(FragmentFlags::IS_FLEX_ITEM);
let container_writing_mode = flex_context.containing_block.style.writing_mode; let container_writing_mode = flex_context.containing_block.effective_writing_mode();
( (
BoxFragment::new( BoxFragment::new(
fragment_info, fragment_info,
@ -1642,10 +1642,10 @@ impl FlexItem<'_> {
); );
// https://drafts.csswg.org/css-writing-modes/#orthogonal-flows // https://drafts.csswg.org/css-writing-modes/#orthogonal-flows
let container_writing_mode = flex_context.containing_block.style.writing_mode; let container_writing_mode = flex_context.containing_block.effective_writing_mode();
assert_eq!( assert_eq!(
container_writing_mode, container_writing_mode,
self.box_.style().writing_mode, self.box_.style().effective_writing_mode(),
"Mixed writing modes are not supported yet" "Mixed writing modes are not supported yet"
); );
// … and also the items inline axis. // … and also the items inline axis.
@ -1670,7 +1670,7 @@ impl FlexItem<'_> {
&pbm, &pbm,
); );
let cross_size = flex_context.vec2_to_flex_relative(size).cross; let cross_size = flex_context.vec2_to_flex_relative(size).cross;
let container_writing_mode = flex_context.containing_block.style.writing_mode; let container_writing_mode = flex_context.containing_block.effective_writing_mode();
let fragments = replaced.contents.make_fragments( let fragments = replaced.contents.make_fragments(
&replaced.style, &replaced.style,
size.to_physical_size(container_writing_mode), size.to_physical_size(container_writing_mode),
@ -1693,13 +1693,13 @@ impl FlexItem<'_> {
None => self.content_box_size.cross.map(|t| t), None => self.content_box_size.cross.map(|t| t),
}; };
let item_writing_mode = non_replaced.style.writing_mode; let item_writing_mode = non_replaced.style.effective_writing_mode();
let item_is_horizontal = item_writing_mode.is_horizontal(); let item_is_horizontal = item_writing_mode.is_horizontal();
let cross_axis_is_item_block_axis = cross_axis_is_item_block_axis( let cross_axis_is_item_block_axis = cross_axis_is_item_block_axis(
flex_context flex_context
.containing_block .containing_block
.style .style
.writing_mode .effective_writing_mode()
.is_horizontal(), .is_horizontal(),
item_is_horizontal, item_is_horizontal,
flex_context.flex_axis, flex_context.flex_axis,
@ -1932,7 +1932,7 @@ impl FlexItemBox {
main_start_cross_start: MainStartCrossStart, main_start_cross_start: MainStartCrossStart,
) -> FlexItemBoxInlineContentSizesInfo { ) -> FlexItemBoxInlineContentSizesInfo {
let style = self.style().clone(); let style = self.style().clone();
let item_writing_mode = style.writing_mode; let item_writing_mode = style.effective_writing_mode();
let item_is_horizontal = item_writing_mode.is_horizontal(); let item_is_horizontal = item_writing_mode.is_horizontal();
let cross_axis_is_item_block_axis = let cross_axis_is_item_block_axis =
cross_axis_is_item_block_axis(container_is_horizontal, item_is_horizontal, flex_axis); cross_axis_is_item_block_axis(container_is_horizontal, item_is_horizontal, flex_axis);

View file

@ -976,7 +976,8 @@ impl FloatBox {
); );
children = replaced.contents.make_fragments( children = replaced.contents.make_fragments(
&replaced.style, &replaced.style,
content_size.to_physical_size(containing_block.style.writing_mode), content_size
.to_physical_size(containing_block.effective_writing_mode()),
) )
}, },
}; };
@ -986,7 +987,7 @@ impl FloatBox {
size: content_size, size: content_size,
}; };
let containing_block_writing_mode = containing_block.style.writing_mode; let containing_block_writing_mode = containing_block.effective_writing_mode();
BoxFragment::new( BoxFragment::new(
self.contents.base_fragment_info(), self.contents.base_fragment_info(),
style.clone(), style.clone(),

View file

@ -360,7 +360,7 @@ impl<'a> LineItemLayout<'a> {
}, },
}; };
let ifc_writing_mode = self.ifc_containing_block.style.writing_mode; let ifc_writing_mode = self.ifc_containing_block.effective_writing_mode();
if inner_state if inner_state
.flags .flags
.contains(LineLayoutInlineContainerFlags::HAD_ANY_FLOATS) .contains(LineLayoutInlineContainerFlags::HAD_ANY_FLOATS)
@ -486,7 +486,7 @@ impl<'a> LineItemLayout<'a> {
self.state.fragments.push(Fragment::Text(TextFragment { self.state.fragments.push(Fragment::Text(TextFragment {
base: text_item.base_fragment_info.into(), base: text_item.base_fragment_info.into(),
parent_style: text_item.parent_style, parent_style: text_item.parent_style,
rect: rect.to_physical(self.ifc_containing_block.style.writing_mode), rect: rect.to_physical(self.ifc_containing_block.effective_writing_mode()),
font_metrics: text_item.font_metrics, font_metrics: text_item.font_metrics,
font_key: text_item.font_key, font_key: text_item.font_key,
glyphs: text_item.text, glyphs: text_item.text,
@ -511,7 +511,7 @@ impl<'a> LineItemLayout<'a> {
relative_adjustement(&atomic.fragment.style, self.ifc_containing_block); relative_adjustement(&atomic.fragment.style, self.ifc_containing_block);
} }
let ifc_writing_mode = self.ifc_containing_block.style.writing_mode; let ifc_writing_mode = self.ifc_containing_block.effective_writing_mode();
atomic.fragment.content_rect.origin += atomic_offset.to_physical_size(ifc_writing_mode); atomic.fragment.content_rect.origin += atomic_offset.to_physical_size(ifc_writing_mode);
if let Some(mut positioning_context) = atomic.positioning_context { if let Some(mut positioning_context) = atomic.positioning_context {
@ -589,7 +589,7 @@ impl<'a> LineItemLayout<'a> {
block: self.line_metrics.block_offset + self.state.parent_offset.block, block: self.line_metrics.block_offset + self.state.parent_offset.block,
}; };
float.fragment.content_rect.origin -= 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); .to_physical_size(self.ifc_containing_block.effective_writing_mode());
self.state.fragments.push(Fragment::Float(float.fragment)); self.state.fragments.push(Fragment::Float(float.fragment));
} }
} }

View file

@ -890,7 +890,7 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> {
start_positioning_context_length, start_positioning_context_length,
); );
let line_rect = line_rect.to_physical(self.containing_block.style.writing_mode); let line_rect = line_rect.to_physical(self.containing_block.effective_writing_mode());
self.fragments self.fragments
.push(Fragment::Positioning(PositioningFragment::new_anonymous( .push(Fragment::Positioning(PositioningFragment::new_anonymous(
line_rect, fragments, line_rect, fragments,
@ -934,14 +934,14 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> {
TextAlignKeyword::Center | TextAlignKeyword::MozCenter => TextAlign::Center, TextAlignKeyword::Center | TextAlignKeyword::MozCenter => TextAlign::Center,
TextAlignKeyword::End => TextAlign::End, TextAlignKeyword::End => TextAlign::End,
TextAlignKeyword::Left | TextAlignKeyword::MozLeft => { TextAlignKeyword::Left | TextAlignKeyword::MozLeft => {
if style.writing_mode.line_left_is_inline_start() { if style.effective_writing_mode().line_left_is_inline_start() {
TextAlign::Start TextAlign::Start
} else { } else {
TextAlign::End TextAlign::End
} }
}, },
TextAlignKeyword::Right | TextAlignKeyword::MozRight => { TextAlignKeyword::Right | TextAlignKeyword::MozRight => {
if style.writing_mode.line_left_is_inline_start() { if style.effective_writing_mode().line_left_is_inline_start() {
TextAlign::End TextAlign::End
} else { } else {
TextAlign::Start TextAlign::Start
@ -1013,7 +1013,7 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> {
state.current_containing_block_offset(); state.current_containing_block_offset();
state.place_float_fragment( state.place_float_fragment(
fragment, fragment,
self.containing_block.style.writing_mode, self.containing_block.effective_writing_mode(),
CollapsedMargin::zero(), CollapsedMargin::zero(),
block_offset_from_containining_block_top, block_offset_from_containining_block_top,
); );
@ -1035,7 +1035,7 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> {
let margin_box = float_item let margin_box = float_item
.fragment .fragment
.margin_rect() .margin_rect()
.to_logical(self.containing_block.style.writing_mode); .to_logical(self.containing_block.effective_writing_mode());
let inline_size = margin_box.size.inline.max(Au::zero()); let inline_size = margin_box.size.inline.max(Au::zero());
let available_inline_size = match self.current_line.placement_among_floats.get() { let available_inline_size = match self.current_line.placement_among_floats.get() {
@ -1912,7 +1912,7 @@ impl IndependentFormattingContext {
let container_writing_mode = inline_formatting_context_state let container_writing_mode = inline_formatting_context_state
.containing_block .containing_block
.style .style
.writing_mode; .effective_writing_mode();
let pbm = style.padding_border_margin(inline_formatting_context_state.containing_block); let pbm = style.padding_border_margin(inline_formatting_context_state.containing_block);
let margin = pbm.margin.auto_is(Au::zero); let margin = pbm.margin.auto_is(Au::zero);
let pbm_sums = pbm.padding + pbm.border + margin; let pbm_sums = pbm.padding + pbm.border + margin;
@ -1986,8 +1986,8 @@ impl IndependentFormattingContext {
inline_formatting_context_state inline_formatting_context_state
.containing_block .containing_block
.style .style
.writing_mode, .effective_writing_mode(),
containing_block_for_children.style.writing_mode, containing_block_for_children.effective_writing_mode(),
"Mixed writing modes are not supported yet" "Mixed writing modes are not supported yet"
); );

View file

@ -227,7 +227,7 @@ impl OutsideMarker {
sequential_layout_state: Option<&mut SequentialLayoutState>, sequential_layout_state: Option<&mut SequentialLayoutState>,
collapsible_with_parent_start_margin: Option<CollapsibleWithParentStartMargin>, collapsible_with_parent_start_margin: Option<CollapsibleWithParentStartMargin>,
) -> Fragment { ) -> Fragment {
let containing_block_writing_mode = containing_block.style.writing_mode; let containing_block_writing_mode = containing_block.effective_writing_mode();
let content_sizes = self let content_sizes = self
.block_container .block_container
.inline_content_sizes(layout_context, containing_block_writing_mode); .inline_content_sizes(layout_context, containing_block_writing_mode);
@ -377,7 +377,10 @@ fn calculate_inline_content_size_for_block_level_boxes(
let size = sizing::outer_inline( let size = sizing::outer_inline(
style, style,
writing_mode, writing_mode,
|| contents.inline_content_sizes(layout_context, style.writing_mode), || {
contents
.inline_content_sizes(layout_context, style.effective_writing_mode())
},
Au::zero, Au::zero,
) )
.max(ContentSizes::zero()); .max(ContentSizes::zero());
@ -579,7 +582,7 @@ fn layout_block_level_children_in_parallel(
placement_state.place_fragment_and_update_baseline(&mut fragment, None); placement_state.place_fragment_and_update_baseline(&mut fragment, None);
child_positioning_context.adjust_static_position_of_hoisted_fragments( child_positioning_context.adjust_static_position_of_hoisted_fragments(
&fragment, &fragment,
containing_block.style.writing_mode, containing_block.effective_writing_mode(),
PositioningContextLength::zero(), PositioningContextLength::zero(),
); );
positioning_context.append(child_positioning_context); positioning_context.append(child_positioning_context);
@ -617,7 +620,7 @@ fn layout_block_level_children_sequentially(
.place_fragment_and_update_baseline(&mut fragment, Some(sequential_layout_state)); .place_fragment_and_update_baseline(&mut fragment, Some(sequential_layout_state));
positioning_context.adjust_static_position_of_hoisted_fragments( positioning_context.adjust_static_position_of_hoisted_fragments(
&fragment, &fragment,
containing_block.style.writing_mode, containing_block.effective_writing_mode(),
positioning_context_length_before_layout, positioning_context_length_before_layout,
); );
@ -920,7 +923,7 @@ fn layout_in_flow_non_replaced_block_level_same_formatting_context(
}, },
}; };
let containing_block_writing_mode = containing_block.style.writing_mode; let containing_block_writing_mode = containing_block.effective_writing_mode();
BoxFragment::new( BoxFragment::new(
base_fragment_info, base_fragment_info,
style.clone(), style.clone(),
@ -1006,7 +1009,7 @@ impl NonReplacedFormattingContext {
}; };
let block_margins_collapsed_with_children = CollapsedBlockMargins::from_margin(&margin); let block_margins_collapsed_with_children = CollapsedBlockMargins::from_margin(&margin);
let containing_block_writing_mode = containing_block.style.writing_mode; let containing_block_writing_mode = containing_block.effective_writing_mode();
BoxFragment::new( BoxFragment::new(
self.base_fragment_info, self.base_fragment_info,
self.style.clone(), self.style.clone(),
@ -1257,7 +1260,7 @@ impl NonReplacedFormattingContext {
}; };
let block_margins_collapsed_with_children = CollapsedBlockMargins::from_margin(&margin); let block_margins_collapsed_with_children = CollapsedBlockMargins::from_margin(&margin);
let containing_block_writing_mode = containing_block.style.writing_mode; let containing_block_writing_mode = containing_block.effective_writing_mode();
BoxFragment::new( BoxFragment::new(
self.base_fragment_info, self.base_fragment_info,
self.style.clone(), self.style.clone(),
@ -1291,7 +1294,7 @@ fn layout_in_flow_replaced_block_level(
let effective_margin_inline_start; let effective_margin_inline_start;
let (margin_block_start, margin_block_end) = solve_block_margins_for_in_flow_block_level(&pbm); let (margin_block_start, margin_block_end) = solve_block_margins_for_in_flow_block_level(&pbm);
let containing_block_writing_mode = containing_block.style.writing_mode; let containing_block_writing_mode = containing_block.effective_writing_mode();
let physical_content_size = content_size.to_physical_size(containing_block_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 fragments = replaced.make_fragments(style, physical_content_size);
@ -1444,7 +1447,8 @@ fn solve_containing_block_padding_and_border_for_in_flow_box<'a>(
}; };
// https://drafts.csswg.org/css-writing-modes/#orthogonal-flows // https://drafts.csswg.org/css-writing-modes/#orthogonal-flows
assert_eq!( assert_eq!(
containing_block.style.writing_mode, containing_block_for_children.style.writing_mode, containing_block.effective_writing_mode(),
containing_block_for_children.effective_writing_mode(),
"Mixed writing modes are not supported yet" "Mixed writing modes are not supported yet"
); );
ContainingBlockPaddingAndBorder { ContainingBlockPaddingAndBorder {
@ -1498,8 +1502,16 @@ fn justify_self_alignment(containing_block: &ContainingBlock, free_space: Au) ->
debug_assert!(free_space >= Au::zero()); debug_assert!(free_space >= Au::zero());
match style.clone_text_align() { match style.clone_text_align() {
TextAlignKeyword::MozCenter => free_space / 2, TextAlignKeyword::MozCenter => free_space / 2,
TextAlignKeyword::MozLeft if !style.writing_mode.line_left_is_inline_start() => free_space, TextAlignKeyword::MozLeft
TextAlignKeyword::MozRight if style.writing_mode.line_left_is_inline_start() => free_space, if !style.effective_writing_mode().line_left_is_inline_start() =>
{
free_space
},
TextAlignKeyword::MozRight
if style.effective_writing_mode().line_left_is_inline_start() =>
{
free_space
},
_ => Au::zero(), _ => Au::zero(),
} }
} }
@ -1659,7 +1671,7 @@ impl PlacementState {
inflow_baselines: Baselines::default(), inflow_baselines: Baselines::default(),
is_inline_block_context, is_inline_block_context,
marker_block_size: None, marker_block_size: None,
writing_mode: containing_block_style.writing_mode, writing_mode: containing_block_style.effective_writing_mode(),
} }
} }

View file

@ -19,7 +19,7 @@ use crate::fragment_tree::{BaseFragmentInfo, Fragment, FragmentFlags};
use crate::positioned::PositioningContext; use crate::positioned::PositioningContext;
use crate::replaced::ReplacedContent; use crate::replaced::ReplacedContent;
use crate::sizing::{self, ContentSizes}; use crate::sizing::{self, ContentSizes};
use crate::style_ext::DisplayInside; use crate::style_ext::{ComputedValuesExt, DisplayInside};
use crate::table::Table; use crate::table::Table;
use crate::ContainingBlock; use crate::ContainingBlock;
@ -180,7 +180,7 @@ impl IndependentFormattingContext {
match self { match self {
Self::NonReplaced(inner) => inner Self::NonReplaced(inner) => inner
.contents .contents
.inline_content_sizes(layout_context, inner.style.writing_mode), .inline_content_sizes(layout_context, inner.style.effective_writing_mode()),
Self::Replaced(inner) => inner.contents.inline_content_sizes(&inner.style), Self::Replaced(inner) => inner.contents.inline_content_sizes(&inner.style),
} }
} }
@ -237,7 +237,7 @@ impl NonReplacedFormattingContext {
} }
pub fn inline_content_sizes(&mut self, layout_context: &LayoutContext) -> ContentSizes { pub fn inline_content_sizes(&mut self, layout_context: &LayoutContext) -> ContentSizes {
let writing_mode = self.style.writing_mode; let writing_mode = self.style.effective_writing_mode();
let contents = &mut self.contents; let contents = &mut self.contents;
*self *self
.content_sizes .content_sizes
@ -256,7 +256,7 @@ impl NonReplacedFormattingContext {
|| { || {
*self.content_sizes.get_or_insert_with(|| { *self.content_sizes.get_or_insert_with(|| {
self.contents self.contents
.inline_content_sizes(layout_context, self.style.writing_mode) .inline_content_sizes(layout_context, self.style.effective_writing_mode())
}) })
}, },
get_auto_minimum, get_auto_minimum,

View file

@ -165,15 +165,16 @@ impl BoxFragment {
/// Get the baselines for this [`BoxFragment`] if they are compatible with the given [`WritingMode`]. /// Get the baselines for this [`BoxFragment`] if they are compatible with the given [`WritingMode`].
/// If they are not compatible, [`Baselines::default()`] is returned. /// If they are not compatible, [`Baselines::default()`] is returned.
pub fn baselines(&self, writing_mode: WritingMode) -> Baselines { pub fn baselines(&self, writing_mode: WritingMode) -> Baselines {
let mut baselines = let mut baselines = if writing_mode.is_horizontal() ==
if writing_mode.is_horizontal() == self.style.writing_mode.is_horizontal() { self.style.effective_writing_mode().is_horizontal()
self.baselines {
} else { self.baselines
// If the writing mode of the container requesting baselines is not } else {
// compatible, ensure that the baselines established by this fragment are // If the writing mode of the container requesting baselines is not
// not used. // compatible, ensure that the baselines established by this fragment are
Baselines::default() // not used.
}; Baselines::default()
};
// From the https://drafts.csswg.org/css-align-3/#baseline-export section on "block containers": // 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 // > However, for legacy reasons if its baseline-source is auto (the initial

View file

@ -29,7 +29,9 @@ use app_units::Au;
pub use flow::BoxTree; pub use flow::BoxTree;
pub use fragment_tree::FragmentTree; pub use fragment_tree::FragmentTree;
use geom::AuOrAuto; use geom::AuOrAuto;
use style::logical_geometry::WritingMode;
use style::properties::ComputedValues; use style::properties::ComputedValues;
use style_ext::ComputedValuesExt;
use crate::geom::LogicalVec2; use crate::geom::LogicalVec2;
@ -39,11 +41,23 @@ pub struct ContainingBlock<'a> {
style: &'a ComputedValues, style: &'a ComputedValues,
} }
impl<'a> ContainingBlock<'a> {
pub(crate) fn effective_writing_mode(&self) -> WritingMode {
self.style.effective_writing_mode()
}
}
struct DefiniteContainingBlock<'a> { struct DefiniteContainingBlock<'a> {
size: LogicalVec2<Au>, size: LogicalVec2<Au>,
style: &'a ComputedValues, style: &'a ComputedValues,
} }
impl<'a> DefiniteContainingBlock<'a> {
pub(crate) fn effective_writing_mode(&self) -> WritingMode {
self.style.effective_writing_mode()
}
}
impl<'a> From<&'_ DefiniteContainingBlock<'a>> for ContainingBlock<'a> { impl<'a> From<&'_ DefiniteContainingBlock<'a>> for ContainingBlock<'a> {
fn from(definite: &DefiniteContainingBlock<'a>) -> Self { fn from(definite: &DefiniteContainingBlock<'a>) -> Self {
ContainingBlock { ContainingBlock {

View file

@ -245,7 +245,7 @@ impl PositioningContext {
if style.clone_position() == Position::Relative { if style.clone_position() == Position::Relative {
new_fragment.content_rect.origin += relative_adjustement(style, containing_block) new_fragment.content_rect.origin += relative_adjustement(style, containing_block)
.to_physical_size(containing_block.style.writing_mode) .to_physical_size(containing_block.effective_writing_mode())
} }
new_fragment new_fragment
@ -267,7 +267,7 @@ impl PositioningContext {
let containing_block = DefiniteContainingBlock { let containing_block = DefiniteContainingBlock {
size: padding_rect size: padding_rect
.size .size
.to_logical(new_fragment.style.writing_mode), .to_logical(new_fragment.style.effective_writing_mode()),
style: &new_fragment.style, style: &new_fragment.style,
}; };
@ -486,7 +486,7 @@ impl HoistedAbsolutelyPositionedBox {
let cbis = containing_block.size.inline; let cbis = containing_block.size.inline;
let cbbs = containing_block.size.block; let cbbs = containing_block.size.block;
let mut absolutely_positioned_box = self.absolutely_positioned_box.borrow_mut(); let mut absolutely_positioned_box = self.absolutely_positioned_box.borrow_mut();
let containing_block_writing_mode = containing_block.style.writing_mode; let containing_block_writing_mode = containing_block.effective_writing_mode();
let pbm = absolutely_positioned_box let pbm = absolutely_positioned_box
.context .context
.style() .style()
@ -623,8 +623,8 @@ impl HoistedAbsolutelyPositionedBox {
}; };
// https://drafts.csswg.org/css-writing-modes/#orthogonal-flows // https://drafts.csswg.org/css-writing-modes/#orthogonal-flows
assert_eq!( assert_eq!(
containing_block.style.writing_mode, containing_block.effective_writing_mode(),
containing_block_for_children.style.writing_mode, containing_block_for_children.effective_writing_mode(),
"Mixed writing modes are not supported yet" "Mixed writing modes are not supported yet"
); );
@ -722,7 +722,7 @@ impl HoistedAbsolutelyPositionedBox {
}; };
let physical_overconstrained = let physical_overconstrained =
overconstrained.to_physical_size(containing_block.style.writing_mode); overconstrained.to_physical_size(containing_block.effective_writing_mode());
BoxFragment::new_with_overconstrained( BoxFragment::new_with_overconstrained(
absolutely_positioned_box.context.base_fragment_info(), absolutely_positioned_box.context.base_fragment_info(),

View file

@ -32,6 +32,7 @@ use style::values::generics::font::LineHeight;
use style_traits::{ParsingMode, ToCss}; use style_traits::{ParsingMode, ToCss};
use crate::fragment_tree::{BoxFragment, Fragment, FragmentFlags, FragmentTree, Tag}; use crate::fragment_tree::{BoxFragment, Fragment, FragmentFlags, FragmentTree, Tag};
use crate::style_ext::ComputedValuesExt;
pub fn process_content_box_request( pub fn process_content_box_request(
requested_node: OpaqueNode, requested_node: OpaqueNode,
@ -135,7 +136,7 @@ pub fn process_resolved_style_request<'dom>(
return style.computed_value_to_string(PropertyDeclarationId::Custom(name)); return style.computed_value_to_string(PropertyDeclarationId::Custom(name));
}, },
} }
.to_physical(style.writing_mode); .to_physical(style.effective_writing_mode());
let computed_style = let computed_style =
|| style.computed_value_to_string(PropertyDeclarationId::Longhand(longhand_id)); || style.computed_value_to_string(PropertyDeclarationId::Longhand(longhand_id));

View file

@ -235,7 +235,7 @@ impl ReplacedContent {
fn flow_relative_intrinsic_size(&self, style: &ComputedValues) -> LogicalVec2<Option<Au>> { fn flow_relative_intrinsic_size(&self, style: &ComputedValues) -> LogicalVec2<Option<Au>> {
let intrinsic_size = PhysicalSize::new(self.intrinsic.width, self.intrinsic.height); let intrinsic_size = PhysicalSize::new(self.intrinsic.width, self.intrinsic.height);
LogicalVec2::from_physical_size(&intrinsic_size, style.writing_mode) LogicalVec2::from_physical_size(&intrinsic_size, style.effective_writing_mode())
} }
pub fn inline_size_over_block_size_intrinsic_ratio( pub fn inline_size_over_block_size_intrinsic_ratio(
@ -243,7 +243,7 @@ impl ReplacedContent {
style: &ComputedValues, style: &ComputedValues,
) -> Option<CSSFloat> { ) -> Option<CSSFloat> {
self.intrinsic.ratio.map(|width_over_height| { self.intrinsic.ratio.map(|width_over_height| {
if style.writing_mode.is_vertical() { if style.effective_writing_mode().is_vertical() {
1. / width_over_height 1. / width_over_height
} else { } else {
width_over_height width_over_height
@ -347,7 +347,7 @@ impl ReplacedContent {
box_size: Option<LogicalVec2<AuOrAuto>>, box_size: Option<LogicalVec2<AuOrAuto>>,
pbm: &PaddingBorderMargin, pbm: &PaddingBorderMargin,
) -> LogicalVec2<Au> { ) -> LogicalVec2<Au> {
let mode = style.writing_mode; let mode = style.effective_writing_mode();
let intrinsic_size = self.flow_relative_intrinsic_size(style); let intrinsic_size = self.flow_relative_intrinsic_size(style);
let intrinsic_ratio = style.preferred_aspect_ratio( let intrinsic_ratio = style.preferred_aspect_ratio(
self.inline_size_over_block_size_intrinsic_ratio(style), self.inline_size_over_block_size_intrinsic_ratio(style),

View file

@ -183,6 +183,7 @@ impl AspectRatio {
} }
pub(crate) trait ComputedValuesExt { pub(crate) trait ComputedValuesExt {
fn effective_writing_mode(&self) -> WritingMode;
fn box_offsets( fn box_offsets(
&self, &self,
containing_block: &ContainingBlock, containing_block: &ContainingBlock,
@ -266,6 +267,10 @@ pub(crate) trait ComputedValuesExt {
} }
impl ComputedValuesExt for ComputedValues { impl ComputedValuesExt for ComputedValues {
fn effective_writing_mode(&self) -> WritingMode {
WritingMode::horizontal_tb()
}
fn box_offsets( fn box_offsets(
&self, &self,
containing_block: &ContainingBlock, containing_block: &ContainingBlock,
@ -278,7 +283,7 @@ impl ComputedValuesExt for ComputedValues {
position.bottom.as_ref(), position.bottom.as_ref(),
position.left.as_ref(), position.left.as_ref(),
), ),
containing_block.style.writing_mode, containing_block.effective_writing_mode(),
) )
} }
@ -333,7 +338,7 @@ impl ComputedValuesExt for ComputedValues {
pbm: &PaddingBorderMargin, pbm: &PaddingBorderMargin,
) -> LogicalVec2<LengthOrAuto> { ) -> LogicalVec2<LengthOrAuto> {
let box_size = self let box_size = self
.box_size(containing_block.style.writing_mode) .box_size(containing_block.effective_writing_mode())
.percentages_relative_to(containing_block); .percentages_relative_to(containing_block);
self.content_box_size_for_box_size(box_size, pbm) self.content_box_size_for_box_size(box_size, pbm)
} }
@ -364,7 +369,7 @@ impl ComputedValuesExt for ComputedValues {
pbm: &PaddingBorderMargin, pbm: &PaddingBorderMargin,
) -> LogicalVec2<LengthOrAuto> { ) -> LogicalVec2<LengthOrAuto> {
let box_size = self let box_size = self
.min_box_size(containing_block.style.writing_mode) .min_box_size(containing_block.effective_writing_mode())
.percentages_relative_to(containing_block); .percentages_relative_to(containing_block);
self.content_min_box_size_for_min_size(box_size, pbm) self.content_min_box_size_for_min_size(box_size, pbm)
} }
@ -394,7 +399,7 @@ impl ComputedValuesExt for ComputedValues {
pbm: &PaddingBorderMargin, pbm: &PaddingBorderMargin,
) -> LogicalVec2<Option<Length>> { ) -> LogicalVec2<Option<Length>> {
let max_box_size = self let max_box_size = self
.max_box_size(containing_block.style.writing_mode) .max_box_size(containing_block.effective_writing_mode())
.percentages_relative_to(containing_block); .percentages_relative_to(containing_block);
self.content_max_box_size_for_max_size(max_box_size, pbm) self.content_max_box_size_for_max_size(max_box_size, pbm)
@ -425,11 +430,11 @@ impl ComputedValuesExt for ComputedValues {
fn padding_border_margin(&self, containing_block: &ContainingBlock) -> PaddingBorderMargin { fn padding_border_margin(&self, containing_block: &ContainingBlock) -> PaddingBorderMargin {
let cbis = containing_block.inline_size; let cbis = containing_block.inline_size;
let padding = self let padding = self
.padding(containing_block.style.writing_mode) .padding(containing_block.effective_writing_mode())
.percentages_relative_to(cbis.into()); .percentages_relative_to(cbis.into());
let border = self.border_width(containing_block.style.writing_mode); let border = self.border_width(containing_block.effective_writing_mode());
let margin = self let margin = self
.margin(containing_block.style.writing_mode) .margin(containing_block.effective_writing_mode())
.percentages_relative_to(cbis.into()); .percentages_relative_to(cbis.into());
PaddingBorderMargin { PaddingBorderMargin {
padding_border_sums: LogicalVec2 { padding_border_sums: LogicalVec2 {

View file

@ -1122,14 +1122,15 @@ impl<'a> TableLayout<'a> {
let border: LogicalSides<Au> = self let border: LogicalSides<Au> = self
.get_collapsed_borders_for_cell(cell, coordinates) .get_collapsed_borders_for_cell(cell, coordinates)
.unwrap_or_else(|| { .unwrap_or_else(|| {
cell.style cell.style.border_width(
.border_width(containing_block_for_table.style.writing_mode) containing_block_for_table.effective_writing_mode(),
)
}) })
.into(); .into();
let padding: LogicalSides<Au> = cell let padding: LogicalSides<Au> = cell
.style .style
.padding(containing_block_for_table.style.writing_mode) .padding(containing_block_for_table.effective_writing_mode())
.percentages_relative_to(self.basis_for_cell_padding_percentage.into()) .percentages_relative_to(self.basis_for_cell_padding_percentage.into())
.into(); .into();
let inline_border_padding_sum = border.inline_sum() + padding.inline_sum(); let inline_border_padding_sum = border.inline_sum() + padding.inline_sum();
@ -1549,7 +1550,7 @@ impl<'a> TableLayout<'a> {
.start .start
.solve(), .solve(),
} }
.to_physical_size(containing_block.style.writing_mode); .to_physical_size(containing_block.effective_writing_mode());
box_fragment.content_rect.origin += margin_offset; box_fragment.content_rect.origin += margin_offset;
if let Some(positioning_context) = positioning_context.take() { if let Some(positioning_context) = positioning_context.take() {
@ -1568,7 +1569,7 @@ impl<'a> TableLayout<'a> {
containing_block_for_children: &ContainingBlock, containing_block_for_children: &ContainingBlock,
containing_block_for_table: &ContainingBlock, containing_block_for_table: &ContainingBlock,
) -> IndependentLayout { ) -> IndependentLayout {
let writing_mode = containing_block_for_children.style.writing_mode; let writing_mode = containing_block_for_children.effective_writing_mode();
let grid_min_max = self.compute_grid_min_max(layout_context, writing_mode); let grid_min_max = self.compute_grid_min_max(layout_context, writing_mode);
let caption_minimum_inline_size = let caption_minimum_inline_size =
self.compute_caption_minimum_inline_size(layout_context, writing_mode); self.compute_caption_minimum_inline_size(layout_context, writing_mode);
@ -1601,7 +1602,7 @@ impl<'a> TableLayout<'a> {
content_inline_size_for_table: None, content_inline_size_for_table: None,
baselines: Baselines::default(), baselines: Baselines::default(),
}; };
let table_writing_mode = containing_block_for_children.style.writing_mode; let table_writing_mode = containing_block_for_children.effective_writing_mode();
table_layout table_layout
.fragments .fragments
@ -1696,7 +1697,7 @@ impl<'a> TableLayout<'a> {
inline: offset_from_wrapper.inline_start, inline: offset_from_wrapper.inline_start,
block: current_block_offset, block: current_block_offset,
} }
.to_physical_size(containing_block_for_children.style.writing_mode); .to_physical_size(containing_block_for_children.effective_writing_mode());
caption_fragment.content_rect.origin += caption_offset; caption_fragment.content_rect.origin += caption_offset;
current_block_offset += caption_fragment current_block_offset += caption_fragment
.margin_rect() .margin_rect()
@ -1733,7 +1734,7 @@ impl<'a> TableLayout<'a> {
containing_block_for_children, containing_block_for_children,
positioning_context, positioning_context,
); );
let writing_mode = containing_block_for_children.style.writing_mode; let writing_mode = containing_block_for_children.effective_writing_mode();
let first_layout_row_heights = self.do_first_row_layout(writing_mode); let first_layout_row_heights = self.do_first_row_layout(writing_mode);
self.compute_table_height_and_final_row_heights( self.compute_table_height_and_final_row_heights(
first_layout_row_heights, first_layout_row_heights,
@ -1744,7 +1745,7 @@ impl<'a> TableLayout<'a> {
assert_eq!(self.table.size.height, self.row_sizes.len()); assert_eq!(self.table.size.height, self.row_sizes.len());
assert_eq!(self.table.size.width, self.distributed_column_widths.len()); assert_eq!(self.table.size.width, self.distributed_column_widths.len());
let table_writing_mode = containing_block_for_children.style.writing_mode; let table_writing_mode = containing_block_for_children.effective_writing_mode();
if self.table.size.width == 0 && self.table.size.height == 0 { if self.table.size.width == 0 && self.table.size.height == 0 {
let content_rect = LogicalRect { let content_rect = LogicalRect {
start_corner: table_pbm.border_padding_start(), start_corner: table_pbm.border_padding_start(),
@ -2024,7 +2025,7 @@ impl<'a> TableLayout<'a> {
dimensions: &TableAndTrackDimensions, dimensions: &TableAndTrackDimensions,
fragments: &mut Vec<Fragment>, fragments: &mut Vec<Fragment>,
) { ) {
let table_writing_mode = self.table.style.writing_mode; let table_writing_mode = self.table.style.effective_writing_mode();
for column_group in self.table.column_groups.iter() { for column_group in self.table.column_groups.iter() {
if !column_group.is_empty() { if !column_group.is_empty() {
fragments.push(Fragment::Positioning(PositioningFragment::new_empty( fragments.push(Fragment::Positioning(PositioningFragment::new_empty(
@ -2147,7 +2148,8 @@ impl<'a> RowFragmentLayout<'a> {
self.row.base_fragment_info, self.row.base_fragment_info,
self.row.style.clone(), self.row.style.clone(),
self.fragments, self.fragments,
self.rect.to_physical(containing_block.style.writing_mode), self.rect
.to_physical(containing_block.effective_writing_mode()),
PhysicalSides::zero(), /* padding */ PhysicalSides::zero(), /* padding */
PhysicalSides::zero(), /* border */ PhysicalSides::zero(), /* border */
PhysicalSides::zero(), /* margin */ PhysicalSides::zero(), /* margin */
@ -2210,7 +2212,8 @@ impl RowGroupFragmentLayout {
self.base_fragment_info, self.base_fragment_info,
self.style, self.style,
self.fragments, self.fragments,
self.rect.to_physical(containing_block.style.writing_mode), self.rect
.to_physical(containing_block.effective_writing_mode()),
PhysicalSides::zero(), /* padding */ PhysicalSides::zero(), /* padding */
PhysicalSides::zero(), /* border */ PhysicalSides::zero(), /* border */
PhysicalSides::zero(), /* margin */ PhysicalSides::zero(), /* margin */
@ -2568,7 +2571,7 @@ impl TableSlotCell {
block: vertical_align_offset, block: vertical_align_offset,
}; };
let vertical_align_fragment = PositioningFragment::new_anonymous( let vertical_align_fragment = PositioningFragment::new_anonymous(
vertical_align_fragment_rect.to_physical(table_style.writing_mode), vertical_align_fragment_rect.to_physical(table_style.effective_writing_mode()),
layout.layout.fragments, layout.layout.fragments,
); );
@ -2591,9 +2594,13 @@ impl TableSlotCell {
base_fragment_info, base_fragment_info,
self.style.clone(), self.style.clone(),
vec![Fragment::Positioning(vertical_align_fragment)], vec![Fragment::Positioning(vertical_align_fragment)],
cell_content_rect.to_physical(table_style.writing_mode), cell_content_rect.to_physical(table_style.effective_writing_mode()),
layout.padding.to_physical(table_style.writing_mode), layout
layout.border.to_physical(table_style.writing_mode), .padding
.to_physical(table_style.effective_writing_mode()),
layout
.border
.to_physical(table_style.effective_writing_mode()),
PhysicalSides::zero(), /* margin */ PhysicalSides::zero(), /* margin */
None, /* clearance */ None, /* clearance */
CollapsedBlockMargins::zero(), CollapsedBlockMargins::zero(),