From 8953207f83d480853226acdc518707ab621fb75e Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 19 Apr 2016 14:47:55 -0700 Subject: [PATCH] Add support for vertical alignment within table cells. Fixes #10621 --- components/layout/flow_list.rs | 8 ++++ components/layout/model.rs | 8 ++++ components/layout/table_cell.rs | 41 +++++++++++++++- .../vertical-align-applies-to-007.htm.ini | 3 -- tests/wpt/mozilla/meta/MANIFEST.json | 48 +++++++++++++++++++ .../tests/mozilla/table_valign_bottom.html | 17 +++++++ .../mozilla/table_valign_bottom_ref.html | 25 ++++++++++ .../tests/mozilla/table_valign_middle.html | 16 +++++++ .../mozilla/table_valign_middle_ref.html | 23 +++++++++ 9 files changed, 184 insertions(+), 5 deletions(-) delete mode 100644 tests/wpt/metadata-css/css21_dev/html4/vertical-align-applies-to-007.htm.ini create mode 100644 tests/wpt/mozilla/tests/mozilla/table_valign_bottom.html create mode 100644 tests/wpt/mozilla/tests/mozilla/table_valign_bottom_ref.html create mode 100644 tests/wpt/mozilla/tests/mozilla/table_valign_middle.html create mode 100644 tests/wpt/mozilla/tests/mozilla/table_valign_middle_ref.html diff --git a/components/layout/flow_list.rs b/components/layout/flow_list.rs index 96f4d5ba7ef..85657db8acd 100644 --- a/components/layout/flow_list.rs +++ b/components/layout/flow_list.rs @@ -29,6 +29,10 @@ impl FlowList { self.flows.push_back(new_tail); } + pub fn back(&self) -> Option<&Flow> { + self.flows.back().map(|x| &**x) + } + /// Add an element first in the list /// /// O(1) @@ -40,6 +44,10 @@ impl FlowList { self.flows.pop_front() } + pub fn front(&self) -> Option<&Flow> { + self.flows.front().map(|x| &**x) + } + /// Create an empty list #[inline] pub fn new() -> FlowList { diff --git a/components/layout/model.rs b/components/layout/model.rs index 2550f300e90..152fa10b532 100644 --- a/components/layout/model.rs +++ b/components/layout/model.rs @@ -90,6 +90,14 @@ impl CollapsibleMargins { CollapsibleMargins::CollapseThrough(ref block_start) => block_start.collapse(), } } + + pub fn block_end_margin_for_noncollapsible_context(&self) -> Au { + match *self { + CollapsibleMargins::None(_, block_end) => block_end, + CollapsibleMargins::Collapse(_, ref block_end) | + CollapsibleMargins::CollapseThrough(ref block_end) => block_end.collapse(), + } + } } enum FinalMarginState { diff --git a/components/layout/table_cell.rs b/components/layout/table_cell.rs index 2e7b96464d5..37a916a920a 100644 --- a/components/layout/table_cell.rs +++ b/components/layout/table_cell.rs @@ -12,14 +12,15 @@ use context::LayoutContext; use cssparser::Color; use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode, DisplayListBuildState}; use euclid::{Point2D, Rect, SideOffsets2D, Size2D}; -use flow::{Flow, FlowClass, OpaqueFlow}; +use flow::{self, Flow, FlowClass, OpaqueFlow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use gfx::display_list::{StackingContext, StackingContextId}; +use incremental::REFLOW; use layout_debug; use model::MaybeAuto; use std::fmt; use std::sync::Arc; -use style::computed_values::{border_collapse, border_top_style}; +use style::computed_values::{border_collapse, border_top_style, vertical_align}; use style::logical_geometry::{LogicalMargin, LogicalRect, LogicalSize, WritingMode}; use style::properties::{ComputedValues, ServoComputedValues}; use table::InternalTable; @@ -74,6 +75,42 @@ impl TableCellFlow { None, MarginsMayCollapseFlag::MarginsMayNotCollapse); debug_assert!(remaining.is_none()); + if !flow::base(self).restyle_damage.contains(REFLOW) { + return; + } + let first_start = flow::base(self).children.front().map(|kid| { + flow::base(kid).position.start.b + }); + if let Some(mut first_start) = first_start { + let mut last_end = first_start; + for kid in flow::base(self).children.iter() { + let kid_base = flow::base(kid); + let start = kid_base.position.start.b + - kid_base.collapsible_margins.block_start_margin_for_noncollapsible_context(); + let end = kid_base.position.start.b + kid_base.position.size.block + + kid_base.collapsible_margins.block_end_margin_for_noncollapsible_context(); + if start < first_start { + first_start = start; + } + if end > last_end { + last_end = end; + } + } + let kids_size = last_end - first_start; + let self_size = flow::base(self).position.size.block - + self.block_flow.fragment.border_padding.block_start_end(); + let kids_self_gap = self_size - kids_size; + let offset = match self.block_flow.fragment.style().get_box().vertical_align { + vertical_align::T::middle => kids_self_gap / 2, + vertical_align::T::bottom => kids_self_gap, + _ => Au(0), + }; + if offset != Au(0) { + for kid in flow::mut_base(self).children.iter_mut() { + flow::mut_base(kid).position.start.b = flow::mut_base(kid).position.start.b + offset; + } + } + } } } diff --git a/tests/wpt/metadata-css/css21_dev/html4/vertical-align-applies-to-007.htm.ini b/tests/wpt/metadata-css/css21_dev/html4/vertical-align-applies-to-007.htm.ini deleted file mode 100644 index 9576ad56a91..00000000000 --- a/tests/wpt/metadata-css/css21_dev/html4/vertical-align-applies-to-007.htm.ini +++ /dev/null @@ -1,3 +0,0 @@ -[vertical-align-applies-to-007.htm] - type: reftest - expected: FAIL diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index 0c5279fc574..c7fa2b2fccf 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -5791,6 +5791,30 @@ "url": "/_mozilla/mozilla/sslfail.html" } ], + "mozilla/table_valign_bottom.html": [ + { + "path": "mozilla/table_valign_bottom.html", + "references": [ + [ + "/_mozilla/mozilla/table_valign_bottom_ref.html", + "==" + ] + ], + "url": "/_mozilla/mozilla/table_valign_bottom.html" + } + ], + "mozilla/table_valign_middle.html": [ + { + "path": "mozilla/table_valign_middle.html", + "references": [ + [ + "/_mozilla/mozilla/table_valign_middle_ref.html", + "==" + ] + ], + "url": "/_mozilla/mozilla/table_valign_middle.html" + } + ], "mozilla/webgl/clearcolor.html": [ { "path": "mozilla/webgl/clearcolor.html", @@ -12465,6 +12489,30 @@ "url": "/_mozilla/mozilla/sslfail.html" } ], + "mozilla/table_valign_bottom.html": [ + { + "path": "mozilla/table_valign_bottom.html", + "references": [ + [ + "/_mozilla/mozilla/table_valign_bottom_ref.html", + "==" + ] + ], + "url": "/_mozilla/mozilla/table_valign_bottom.html" + } + ], + "mozilla/table_valign_middle.html": [ + { + "path": "mozilla/table_valign_middle.html", + "references": [ + [ + "/_mozilla/mozilla/table_valign_middle_ref.html", + "==" + ] + ], + "url": "/_mozilla/mozilla/table_valign_middle.html" + } + ], "mozilla/webgl/clearcolor.html": [ { "path": "mozilla/webgl/clearcolor.html", diff --git a/tests/wpt/mozilla/tests/mozilla/table_valign_bottom.html b/tests/wpt/mozilla/tests/mozilla/table_valign_bottom.html new file mode 100644 index 00000000000..5e75318062e --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/table_valign_bottom.html @@ -0,0 +1,17 @@ + + +Table align bottom + + + + + + +
Foo
diff --git a/tests/wpt/mozilla/tests/mozilla/table_valign_bottom_ref.html b/tests/wpt/mozilla/tests/mozilla/table_valign_bottom_ref.html new file mode 100644 index 00000000000..577a311df51 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/table_valign_bottom_ref.html @@ -0,0 +1,25 @@ + + +Reference: table align bottom + + + + + +
Foo
+ diff --git a/tests/wpt/mozilla/tests/mozilla/table_valign_middle.html b/tests/wpt/mozilla/tests/mozilla/table_valign_middle.html new file mode 100644 index 00000000000..4ec6fa8d85b --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/table_valign_middle.html @@ -0,0 +1,16 @@ + + +Middle alignment in tables + + + + + + +
Foo
diff --git a/tests/wpt/mozilla/tests/mozilla/table_valign_middle_ref.html b/tests/wpt/mozilla/tests/mozilla/table_valign_middle_ref.html new file mode 100644 index 00000000000..2946b8a929e --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/table_valign_middle_ref.html @@ -0,0 +1,23 @@ + + +Reference: middle alignment in tables + + + + + +
Foo
+