servo: Merge #4400 - layout: Implement `empty-cells` per CSS 2.1 § 17.6.1.1 (from pcwalton:empty-cells); r=SimonSapin

r? @SimonSapin

Source-Repo: https://github.com/servo/servo
Source-Revision: 636641f90533c941a3580b5caee1ae1fef953841
This commit is contained in:
Patrick Walton 2014-12-17 22:33:51 -07:00
Родитель c6d8118a3f
Коммит 2ba8079a6a
5 изменённых файлов: 53 добавлений и 13 удалений

Просмотреть файл

@ -52,7 +52,7 @@ use std::collections::DList;
use std::mem;
use std::sync::atomic::Relaxed;
use style::ComputedValues;
use style::computed_values::{display, position, float, list_style_position};
use style::computed_values::{display, empty_cells, float, list_style_position, position};
use sync::Arc;
use url::Url;
@ -157,8 +157,8 @@ struct InlineFragmentsAccumulator {
/// The list of fragments.
fragments: DList<Fragment>,
/// Whether we've created a range to enclose all the fragments. This will be Some() if the outer node
/// is an inline and None otherwise.
/// Whether we've created a range to enclose all the fragments. This will be Some() if the
/// outer node is an inline and None otherwise.
enclosing_style: Option<Arc<ComputedValues>>,
}
@ -914,7 +914,18 @@ impl<'a> FlowConstructor<'a> {
/// possibly other `BlockFlow`s or `InlineFlow`s underneath it.
fn build_flow_for_table_cell(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
let fragment = Fragment::new_from_specific_info(node, SpecificFragmentInfo::TableCell);
let flow = box TableCellFlow::from_node_and_fragment(node, fragment) as Box<Flow>;
// Determine if the table cell should be hidden. Per CSS 2.1 § 17.6.1.1, this will be true
// if the cell has any in-flow elements (even empty ones!) and has `empty-cells` set to
// `hide`.
let hide = node.style().get_inheritedtable().empty_cells == empty_cells::hide &&
node.children().all(|kid| {
let position = kid.style().get_box().position;
!kid.is_content() || position == position::absolute || position == position::fixed
});
let flow = box TableCellFlow::from_node_fragment_and_visibility_flag(node, fragment, !hide)
as Box<Flow>;
self.build_flow_for_block(FlowRef::new(flow), node)
}

Просмотреть файл

@ -59,7 +59,7 @@ use std::iter::Zip;
use std::raw;
use std::sync::atomic::{AtomicUint, SeqCst};
use std::slice::MutItems;
use style::computed_values::{clear, float, position, text_align};
use style::computed_values::{clear, empty_cells, float, position, text_align};
use style::ComputedValues;
use sync::Arc;
@ -1067,12 +1067,18 @@ impl<'a> ImmutableFlowUtils for &'a Flow + 'a {
fn generate_missing_child_flow(self, node: &ThreadSafeLayoutNode) -> FlowRef {
let flow = match self.class() {
FlowClass::Table | FlowClass::TableRowGroup => {
let fragment = Fragment::new_anonymous_table_fragment(node, SpecificFragmentInfo::TableRow);
let fragment =
Fragment::new_anonymous_table_fragment(node,
SpecificFragmentInfo::TableRow);
box TableRowFlow::from_node_and_fragment(node, fragment) as Box<Flow>
},
FlowClass::TableRow => {
let fragment = Fragment::new_anonymous_table_fragment(node, SpecificFragmentInfo::TableCell);
box TableCellFlow::from_node_and_fragment(node, fragment) as Box<Flow>
let fragment =
Fragment::new_anonymous_table_fragment(node,
SpecificFragmentInfo::TableCell);
let hide = node.style().get_inheritedtable().empty_cells == empty_cells::hide;
box TableCellFlow::from_node_fragment_and_visibility_flag(node, fragment, !hide) as
Box<Flow>
},
_ => {
panic!("no need to generate a missing child")

Просмотреть файл

@ -8,7 +8,7 @@
use block::{BlockFlow, ISizeAndMarginsComputer, MarginsMayCollapseFlag};
use context::LayoutContext;
use flow::{FlowClass, Flow};
use flow::{Flow, FlowClass};
use fragment::{Fragment, FragmentBoundsIterator};
use model::{MaybeAuto};
use layout_debug;
@ -27,15 +27,21 @@ pub struct TableCellFlow {
pub block_flow: BlockFlow,
/// The column span of this cell.
pub column_span: u32,
/// Whether this cell is visible. If false, the value of `empty-cells` means that we must not
/// display this cell.
pub visible: bool,
}
impl TableCellFlow {
pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment)
-> TableCellFlow {
pub fn from_node_fragment_and_visibility_flag(node: &ThreadSafeLayoutNode,
fragment: Fragment,
visible: bool)
-> TableCellFlow {
TableCellFlow {
block_flow: BlockFlow::from_node_and_fragment(node, fragment),
column_span: node.get_unsigned_integer_attribute(UnsignedIntegerAttribute::ColSpanUnsignedIntegerAttribute)
.unwrap_or(1),
visible: visible,
}
}
@ -53,7 +59,9 @@ impl TableCellFlow {
/// methods.
#[inline(always)]
fn assign_block_size_table_cell_base<'a>(&mut self, layout_context: &'a LayoutContext<'a>) {
self.block_flow.assign_block_size_block_base(layout_context, MarginsMayCollapseFlag::MarginsMayNotCollapse)
self.block_flow.assign_block_size_block_base(
layout_context,
MarginsMayCollapseFlag::MarginsMayNotCollapse)
}
}
@ -145,7 +153,9 @@ impl Flow for TableCellFlow {
}
fn build_display_list(&mut self, layout_context: &LayoutContext) {
self.block_flow.build_display_list(layout_context)
if self.visible {
self.block_flow.build_display_list(layout_context)
}
}
fn repair_style(&mut self, new_style: &Arc<ComputedValues>) {

Просмотреть файл

@ -1000,6 +1000,15 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
_ => panic!("no layout data for this node"),
}
}
/// Returns true if this node contributes content. This is used in the implementation of
/// `empty_cells` per CSS 2.1 § 17.6.1.1.
pub fn is_content(&self) -> bool {
match self.type_id() {
Some(NodeTypeId::Element(..)) | Some(NodeTypeId::Text(..)) => true,
_ => false
}
}
}
pub struct ThreadSafeLayoutNodeChildrenIterator<'a> {

Просмотреть файл

@ -1326,6 +1326,10 @@ pub mod longhands {
${single_keyword("table-layout", "auto fixed")}
${new_style_struct("InheritedTable", is_inherited=True)}
${single_keyword("empty-cells", "show hide")}
// CSS 2.1, Section 18 - User interface