mirror of
https://github.com/servo/servo.git
synced 2025-08-07 14:35:33 +01:00
layout: Implement most of border-collapse
per CSS 2.1 § 17.6.2.
Known issues: * Collapsed borders do not correctly affect the border-box of the table itself. * The content widths of all cells in a column and the content height of all cells in a row is the same in this patch, but not in Gecko and WebKit. * Corners are not painted well. The spec does not say what to do here. * Column spans are not handled well. The spec does not say what to do here either.
This commit is contained in:
parent
92359c7b9a
commit
48299a53cb
22 changed files with 1975 additions and 520 deletions
|
@ -11,20 +11,21 @@ use context::LayoutContext;
|
|||
use flow::{FlowClass, Flow};
|
||||
use fragment::{Fragment, FragmentBorderBoxIterator};
|
||||
use layout_debug;
|
||||
use style::computed_values::border_spacing;
|
||||
use table::{ChildInlineSizeInfo, ColumnComputedInlineSize, ColumnIntrinsicInlineSize};
|
||||
use table::{InternalTable, TableLikeFlow};
|
||||
use style::computed_values::{border_collapse, border_spacing};
|
||||
use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable, TableLikeFlow};
|
||||
use table_row::{self, CollapsedBordersForRow};
|
||||
use wrapper::ThreadSafeLayoutNode;
|
||||
|
||||
use geom::{Point2D, Rect};
|
||||
use rustc_serialize::{Encoder, Encodable};
|
||||
use std::fmt;
|
||||
use std::iter::{IntoIterator, Iterator, Peekable};
|
||||
use std::sync::Arc;
|
||||
use style::properties::ComputedValues;
|
||||
use util::geometry::Au;
|
||||
use util::logical_geometry::LogicalRect;
|
||||
use std::fmt;
|
||||
use style::properties::ComputedValues;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// A table formatting context.
|
||||
#[derive(RustcEncodable)]
|
||||
pub struct TableRowGroupFlow {
|
||||
/// Fields common to all block flows.
|
||||
pub block_flow: BlockFlow,
|
||||
|
@ -37,6 +38,24 @@ pub struct TableRowGroupFlow {
|
|||
|
||||
/// The spacing for this rowgroup.
|
||||
pub spacing: border_spacing::T,
|
||||
|
||||
/// 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,
|
||||
|
||||
/// The final width of the borders in the inline direction for each cell, computed by the
|
||||
/// entire table and pushed down into each row during inline size computation.
|
||||
pub collapsed_inline_direction_border_widths_for_table: Vec<Au>,
|
||||
|
||||
/// The final width of the borders in the block direction for each cell, computed by the
|
||||
/// entire table and pushed down into each row during inline size computation.
|
||||
pub collapsed_block_direction_border_widths_for_table: Vec<Au>,
|
||||
}
|
||||
|
||||
impl Encodable for TableRowGroupFlow {
|
||||
fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
|
||||
self.block_flow.encode(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl TableRowGroupFlow {
|
||||
|
@ -50,12 +69,38 @@ impl TableRowGroupFlow {
|
|||
horizontal: Au(0),
|
||||
vertical: Au(0),
|
||||
},
|
||||
preliminary_collapsed_borders: CollapsedBordersForRow::new(),
|
||||
collapsed_inline_direction_border_widths_for_table: Vec::new(),
|
||||
collapsed_block_direction_border_widths_for_table: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fragment<'a>(&'a mut self) -> &'a Fragment {
|
||||
&self.block_flow.fragment
|
||||
}
|
||||
|
||||
pub fn populate_collapsed_border_spacing<'a,I>(
|
||||
&mut self,
|
||||
collapsed_inline_direction_border_widths_for_table: &[Au],
|
||||
collapsed_block_direction_border_widths_for_table: &mut Peekable<I>)
|
||||
where I: Iterator<Item=&'a Au> {
|
||||
self.collapsed_inline_direction_border_widths_for_table.clear();
|
||||
self.collapsed_inline_direction_border_widths_for_table
|
||||
.extend(collapsed_inline_direction_border_widths_for_table.into_iter().map(|x| *x));
|
||||
|
||||
for _ in range(0, self.block_flow.base.children.len()) {
|
||||
if let Some(collapsed_block_direction_border_width_for_table) =
|
||||
collapsed_block_direction_border_widths_for_table.next() {
|
||||
self.collapsed_block_direction_border_widths_for_table
|
||||
.push(*collapsed_block_direction_border_width_for_table)
|
||||
}
|
||||
}
|
||||
if let Some(collapsed_block_direction_border_width_for_table) =
|
||||
collapsed_block_direction_border_widths_for_table.peek() {
|
||||
self.collapsed_block_direction_border_widths_for_table
|
||||
.push(**collapsed_block_direction_border_width_for_table)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Flow for TableRowGroupFlow {
|
||||
|
@ -75,6 +120,10 @@ impl Flow for TableRowGroupFlow {
|
|||
&mut self.block_flow
|
||||
}
|
||||
|
||||
fn as_immutable_block(&self) -> &BlockFlow {
|
||||
&self.block_flow
|
||||
}
|
||||
|
||||
fn column_intrinsic_inline_sizes<'a>(&'a mut self) -> &'a mut Vec<ColumnIntrinsicInlineSize> {
|
||||
&mut self.column_intrinsic_inline_sizes
|
||||
}
|
||||
|
@ -99,26 +148,48 @@ impl Flow for TableRowGroupFlow {
|
|||
|
||||
// The position was set to the containing block by the flow's parent.
|
||||
let containing_block_inline_size = self.block_flow.base.block_container_inline_size;
|
||||
// FIXME: In case of border-collapse: collapse, inline-start_content_edge should be
|
||||
// the border width on the inline-start side.
|
||||
let inline_start_content_edge = Au::new(0);
|
||||
let inline_end_content_edge = Au::new(0);
|
||||
let (inline_start_content_edge, inline_end_content_edge) = (Au(0), Au(0));
|
||||
let content_inline_size = containing_block_inline_size;
|
||||
|
||||
let inline_size_computer = InternalTable;
|
||||
let border_collapse = self.block_flow.fragment.style.get_inheritedtable().border_collapse;
|
||||
inline_size_computer.compute_used_inline_size(&mut self.block_flow,
|
||||
layout_context,
|
||||
containing_block_inline_size);
|
||||
containing_block_inline_size,
|
||||
border_collapse);
|
||||
|
||||
let info = ChildInlineSizeInfo {
|
||||
column_computed_inline_sizes: &self.column_computed_inline_sizes,
|
||||
spacing: self.spacing,
|
||||
};
|
||||
let column_computed_inline_sizes = self.column_computed_inline_sizes.as_slice();
|
||||
let border_spacing = self.spacing;
|
||||
let collapsed_inline_direction_border_widths_for_table =
|
||||
self.collapsed_inline_direction_border_widths_for_table.as_slice();
|
||||
let mut collapsed_block_direction_border_widths_for_table =
|
||||
self.collapsed_block_direction_border_widths_for_table.iter().peekable();
|
||||
self.block_flow.propagate_assigned_inline_size_to_children(layout_context,
|
||||
inline_start_content_edge,
|
||||
inline_end_content_edge,
|
||||
content_inline_size,
|
||||
Some(info));
|
||||
|child_flow,
|
||||
child_index,
|
||||
content_inline_size,
|
||||
writing_mode,
|
||||
inline_start_margin_edge| {
|
||||
table_row::propagate_column_inline_sizes_to_child(
|
||||
child_flow,
|
||||
child_index,
|
||||
content_inline_size,
|
||||
writing_mode,
|
||||
column_computed_inline_sizes,
|
||||
&border_spacing,
|
||||
&None,
|
||||
inline_start_margin_edge);
|
||||
|
||||
if border_collapse == border_collapse::T::collapse {
|
||||
let child_table_row = child_flow.as_table_row();
|
||||
child_table_row.populate_collapsed_border_spacing(
|
||||
collapsed_inline_direction_border_widths_for_table.as_slice(),
|
||||
&mut collapsed_block_direction_border_widths_for_table);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn assign_block_size<'a>(&mut self, layout_context: &'a LayoutContext<'a>) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue