diff --git a/components/layout/block.rs b/components/layout/block.rs index 718155f495b..0df2bbe3f3a 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -1207,6 +1207,7 @@ impl BlockFlow { usize, Au, WritingMode, + &mut Au, &mut Au) { // Keep track of whether floats could impact each child. let mut inline_start_floats_impact_child = @@ -1259,6 +1260,7 @@ impl BlockFlow { // This value is used only for table cells. let mut inline_start_margin_edge = inline_start_content_edge; + let mut inline_end_margin_edge = inline_end_content_edge; let mut iterator = self.base.child_iter().enumerate().peekable(); while let Some((i, kid)) = iterator.next() { @@ -1332,7 +1334,8 @@ impl BlockFlow { i, content_inline_size, containing_block_mode, - &mut inline_start_margin_edge); + &mut inline_start_margin_edge, + &mut inline_end_margin_edge); // Per CSS 2.1 ยง 16.3.1, text alignment propagates to all children in flow. // @@ -1602,7 +1605,7 @@ impl Flow for BlockFlow { inline_start_content_edge, inline_end_content_edge, content_inline_size, - |_, _, _, _, _| {}); + |_, _, _, _, _, _| {}); } fn place_float_if_applicable<'a>(&mut self, _: &'a LayoutContext<'a>) { diff --git a/components/layout/table.rs b/components/layout/table.rs index 72af04817f2..3e73bc8329a 100644 --- a/components/layout/table.rs +++ b/components/layout/table.rs @@ -473,19 +473,16 @@ impl Flow for TableFlow { inline_end_content_edge, content_inline_size, |child_flow, - child_index, - content_inline_size, + _child_index, + _content_inline_size, writing_mode, - inline_start_margin_edge| { + _inline_start_margin_edge, + _inline_end_margin_edge| { table_row::propagate_column_inline_sizes_to_child( child_flow, - child_index, - content_inline_size, writing_mode, column_computed_inline_sizes, - &spacing_per_cell, - &None, - inline_start_margin_edge); + &spacing_per_cell); if child_flow.is_table_row() { let child_table_row = child_flow.as_table_row(); child_table_row.populate_collapsed_border_spacing( diff --git a/components/layout/table_cell.rs b/components/layout/table_cell.rs index 8de69f0608d..69455d4610f 100644 --- a/components/layout/table_cell.rs +++ b/components/layout/table_cell.rs @@ -157,7 +157,7 @@ impl Flow for TableCellFlow { inline_start_content_edge, inline_end_content_edge, content_inline_size, - |_, _, _, _, _| {}); + |_, _, _, _, _, _| {}); } fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) { diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs index a453003e19e..a18df59b377 100644 --- a/components/layout/table_row.rs +++ b/components/layout/table_row.rs @@ -9,7 +9,7 @@ use block::{BlockFlow, ISizeAndMarginsComputer}; use context::LayoutContext; use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode}; -use flow::{self, BaseFlow, FlowClass, Flow, ImmutableFlowUtils}; +use flow::{self, FlowClass, Flow, ImmutableFlowUtils}; use flow_list::MutFlowListIterator; use fragment::{Fragment, FragmentBorderBoxIterator}; use layout_debug; @@ -47,6 +47,10 @@ pub struct TableRowFlow { /// phase. pub spacing: border_spacing::T, + /// The direction of the columns, propagated down from the table during the inline-size + /// assignment phase. + pub table_writing_mode: WritingMode, + /// Information about the borders for each cell that we bubble up to our parent. This is only /// computed if `border-collapse` is `collapse`. pub preliminary_collapsed_borders: CollapsedBordersForRow, @@ -78,6 +82,7 @@ pub struct CellIntrinsicInlineSize { impl TableRowFlow { pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment) -> TableRowFlow { + let writing_mode = fragment.style().writing_mode; TableRowFlow { block_flow: BlockFlow::from_node_and_fragment(node, fragment, None), cell_intrinsic_inline_sizes: Vec::new(), @@ -86,6 +91,7 @@ impl TableRowFlow { horizontal: Au(0), vertical: Au(0), }, + table_writing_mode: writing_mode, preliminary_collapsed_borders: CollapsedBordersForRow::new(), final_collapsed_borders: CollapsedBordersForRow::new(), collapsed_border_spacing: CollapsedBorderSpacingForRow::new(), @@ -366,6 +372,8 @@ impl Flow for TableRowFlow { // Push those inline sizes down to the cells. let spacing = self.spacing; + let row_writing_mode = self.block_flow.base.writing_mode; + let table_writing_mode = self.table_writing_mode; self.block_flow.propagate_assigned_inline_size_to_children(layout_context, inline_start_content_edge, inline_end_content_edge, @@ -373,17 +381,20 @@ impl Flow for TableRowFlow { |child_flow, child_index, content_inline_size, - writing_mode, - inline_start_margin_edge| { - propagate_column_inline_sizes_to_child( + _writing_mode, + inline_start_margin_edge, + inline_end_margin_edge| { + set_inline_position_of_child_flow( child_flow, child_index, - content_inline_size, - writing_mode, + row_writing_mode, + table_writing_mode, &computed_inline_size_for_cells, &spacing, &border_collapse_info, - inline_start_margin_edge) + content_inline_size, + inline_start_margin_edge, + inline_end_margin_edge); }) } @@ -666,49 +677,54 @@ impl CollapsedBorder { /// Pushes column inline size and border collapse info down to a child. pub fn propagate_column_inline_sizes_to_child( child_flow: &mut Flow, - child_index: usize, - content_inline_size: Au, - writing_mode: WritingMode, + table_writing_mode: WritingMode, column_computed_inline_sizes: &[ColumnComputedInlineSize], - border_spacing: &border_spacing::T, - border_collapse_info: &Option, - inline_start_margin_edge: &mut Au) { + border_spacing: &border_spacing::T) { // If the child is a row group or a row, the column inline-size info should be copied from its // parent. // // FIXME(pcwalton): This seems inefficient. Reference count it instead? - let inline_size = match child_flow.class() { + match child_flow.class() { FlowClass::Table => { let child_table_flow = child_flow.as_table(); child_table_flow.column_computed_inline_sizes = column_computed_inline_sizes.to_vec(); - content_inline_size } FlowClass::TableRowGroup => { let child_table_rowgroup_flow = child_flow.as_table_rowgroup(); child_table_rowgroup_flow.column_computed_inline_sizes = column_computed_inline_sizes.to_vec(); child_table_rowgroup_flow.spacing = *border_spacing; - content_inline_size + child_table_rowgroup_flow.table_writing_mode = table_writing_mode; } FlowClass::TableRow => { let child_table_row_flow = child_flow.as_table_row(); child_table_row_flow.column_computed_inline_sizes = column_computed_inline_sizes.to_vec(); child_table_row_flow.spacing = *border_spacing; - content_inline_size + child_table_row_flow.table_writing_mode = table_writing_mode; } - FlowClass::TableCell => column_computed_inline_sizes[child_index].size, - _ => content_inline_size, - }; + c => warn!("unexpected flow in table {:?}", c) + } +} +/// Lay out table cells inline according to the computer column sizes. +fn set_inline_position_of_child_flow( + child_flow: &mut Flow, + child_index: usize, + row_writing_mode: WritingMode, + table_writing_mode: WritingMode, + column_computed_inline_sizes: &[ColumnComputedInlineSize], + border_spacing: &border_spacing::T, + border_collapse_info: &Option, + parent_content_inline_size: Au, + inline_start_margin_edge: &mut Au, + inline_end_margin_edge: &mut Au) { if !child_flow.is_table_cell() { - set_inline_position_of_child_flow(flow::mut_base(child_flow), - inline_start_margin_edge, - inline_size, - writing_mode); return } + let reverse_column_order = table_writing_mode.is_bidi_ltr() != row_writing_mode.is_bidi_ltr(); + // Handle border collapsing, if necessary. let child_table_cell = child_flow.as_table_cell(); match *border_collapse_info { @@ -751,21 +767,38 @@ pub fn propagate_column_inline_sizes_to_child( }; // Move over past the collapsed border. - *inline_start_margin_edge = *inline_start_margin_edge + - child_table_cell.collapsed_borders.inline_start_width + if reverse_column_order { + *inline_end_margin_edge = *inline_end_margin_edge + + child_table_cell.collapsed_borders.inline_start_width + } else { + *inline_start_margin_edge = *inline_start_margin_edge + + child_table_cell.collapsed_borders.inline_start_width + } } None => { // Take spacing into account. - *inline_start_margin_edge = *inline_start_margin_edge + border_spacing.horizontal + if reverse_column_order { + *inline_end_margin_edge = *inline_end_margin_edge + border_spacing.horizontal + } else { + *inline_start_margin_edge = *inline_start_margin_edge + border_spacing.horizontal + } } } - set_inline_position_of_child_flow(&mut child_table_cell.block_flow.base, - inline_start_margin_edge, - inline_size, - writing_mode); + let column_inline_size = column_computed_inline_sizes[child_index].size; + let kid_base = &mut child_table_cell.block_flow.base; + kid_base.block_container_inline_size = column_inline_size; - *inline_start_margin_edge = *inline_start_margin_edge + inline_size + if reverse_column_order { + // Columns begin from the inline-end edge. + kid_base.position.start.i = + parent_content_inline_size - *inline_end_margin_edge - column_inline_size; + *inline_end_margin_edge = *inline_end_margin_edge + column_inline_size; + } else { + // Columns begin from the inline-start edge. + kid_base.position.start.i = *inline_start_margin_edge; + *inline_start_margin_edge = *inline_start_margin_edge + column_inline_size; + } } #[derive(Copy, Clone)] @@ -774,15 +807,6 @@ pub struct BorderCollapseInfoForChildTableCell<'a> { collapsed_border_spacing_for_row: &'a CollapsedBorderSpacingForRow, } -fn set_inline_position_of_child_flow(child_flow: &mut BaseFlow, - inline_start_margin_edge: &mut Au, - inline_size: Au, - writing_mode: WritingMode) { - child_flow.position.start.i = *inline_start_margin_edge; - child_flow.block_container_inline_size = inline_size; - child_flow.block_container_writing_mode = writing_mode; -} - /// Performs border-collapse in the inline direction for all the cells' inside borders in the /// inline-direction cells and propagates the outside borders (the far left and right) up to the /// table row. This is done eagerly here so that at least the inline inside border collapse diff --git a/components/layout/table_rowgroup.rs b/components/layout/table_rowgroup.rs index 034597965bc..a7cff9dcaf1 100644 --- a/components/layout/table_rowgroup.rs +++ b/components/layout/table_rowgroup.rs @@ -23,7 +23,7 @@ use std::iter::{IntoIterator, Iterator, Peekable}; use std::sync::Arc; use style::properties::ComputedValues; use util::geometry::Au; -use util::logical_geometry::LogicalRect; +use util::logical_geometry::{LogicalRect, WritingMode}; /// A table formatting context. pub struct TableRowGroupFlow { @@ -39,6 +39,10 @@ pub struct TableRowGroupFlow { /// The spacing for this rowgroup. pub spacing: border_spacing::T, + /// The direction of the columns, propagated down from the table during the inline-size + /// assignment phase. + pub table_writing_mode: WritingMode, + /// Information about the borders for each cell that we bubble up to our parent. This is only /// computed if `border-collapse` is `collapse`. pub preliminary_collapsed_borders: CollapsedBordersForRow, @@ -61,6 +65,7 @@ impl Encodable for TableRowGroupFlow { impl TableRowGroupFlow { pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment) -> TableRowGroupFlow { + let writing_mode = fragment.style().writing_mode; TableRowGroupFlow { block_flow: BlockFlow::from_node_and_fragment(node, fragment, None), column_intrinsic_inline_sizes: Vec::new(), @@ -69,6 +74,7 @@ impl TableRowGroupFlow { horizontal: Au(0), vertical: Au(0), }, + table_writing_mode: writing_mode, preliminary_collapsed_borders: CollapsedBordersForRow::new(), collapsed_inline_direction_border_widths_for_table: Vec::new(), collapsed_block_direction_border_widths_for_table: Vec::new(), @@ -161,6 +167,7 @@ impl Flow for TableRowGroupFlow { let column_computed_inline_sizes = &self.column_computed_inline_sizes; let border_spacing = self.spacing; + let table_writing_mode = self.table_writing_mode; let collapsed_inline_direction_border_widths_for_table = &self.collapsed_inline_direction_border_widths_for_table; let mut collapsed_block_direction_border_widths_for_table = @@ -170,19 +177,16 @@ impl Flow for TableRowGroupFlow { inline_end_content_edge, content_inline_size, |child_flow, - child_index, - content_inline_size, - writing_mode, - inline_start_margin_edge| { + _child_index, + _content_inline_size, + _writing_mode, + _inline_start_margin_edge, + _inline_end_margin_edge| { table_row::propagate_column_inline_sizes_to_child( child_flow, - child_index, - content_inline_size, - writing_mode, + table_writing_mode, column_computed_inline_sizes, - &border_spacing, - &None, - inline_start_margin_edge); + &border_spacing); if border_collapse == border_collapse::T::collapse { let child_table_row = child_flow.as_table_row(); diff --git a/components/layout/table_wrapper.rs b/components/layout/table_wrapper.rs index 8a3e368d140..8e0701131c5 100644 --- a/components/layout/table_wrapper.rs +++ b/components/layout/table_wrapper.rs @@ -341,7 +341,7 @@ impl Flow for TableWrapperFlow { inline_start_content_edge, inline_end_content_edge, content_inline_size, - |_, _, _, _, _| {}) + |_, _, _, _, _, _| {}) } Some(ref assigned_column_inline_sizes) => { self.block_flow @@ -350,19 +350,16 @@ impl Flow for TableWrapperFlow { inline_end_content_edge, content_inline_size, |child_flow, - child_index, - content_inline_size, + _child_index, + _content_inline_size, writing_mode, - inline_start_margin_edge| { + _inline_start_margin_edge, + _inline_end_margin_edge| { table_row::propagate_column_inline_sizes_to_child( child_flow, - child_index, - content_inline_size, writing_mode, assigned_column_inline_sizes, - &border_spacing, - &None, - inline_start_margin_edge) + &border_spacing); }) } } diff --git a/tests/ref/basic.list b/tests/ref/basic.list index 7358b45532f..0627c8085c9 100644 --- a/tests/ref/basic.list +++ b/tests/ref/basic.list @@ -277,6 +277,7 @@ experimental == rtl_simple.html rtl_simple_ref.html == table_padding_a.html table_padding_ref.html == table_percentage_capping_a.html table_percentage_capping_ref.html == table_percentage_width_a.html table_percentage_width_ref.html +experimental == table_row_direction_a.html table_row_direction_ref.html == text_align_complex_a.html text_align_complex_ref.html == text_align_justify_a.html text_align_justify_ref.html experimental == text_align_rtl.html text_align_rtl_ref.html diff --git a/tests/ref/table_row_direction_a.html b/tests/ref/table_row_direction_a.html new file mode 100644 index 00000000000..6a5264d0d9c --- /dev/null +++ b/tests/ref/table_row_direction_a.html @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + +
ROY
+ + diff --git a/tests/ref/table_row_direction_ref.html b/tests/ref/table_row_direction_ref.html new file mode 100644 index 00000000000..03cdf991d02 --- /dev/null +++ b/tests/ref/table_row_direction_ref.html @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + +
ROY
+ +