diff --git a/components/layout/table.rs b/components/layout/table.rs index 37f589917a2..1bab26d06a9 100644 --- a/components/layout/table.rs +++ b/components/layout/table.rs @@ -11,11 +11,12 @@ use block::{ISizeConstraintInput, ISizeConstraintSolution}; use construct::FlowConstructor; use context::LayoutContext; use floats::FloatKind; -use flow::{Flow, FlowClass, IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS, ImmutableFlowUtils}; -use flow::{TableFlowClass}; +use flow::{mod, Flow, FlowClass, IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS}; +use flow::{ImmutableFlowUtils, TableFlowClass}; use fragment::{Fragment, FragmentBoundsIterator}; use layout_debug; use model::{IntrinsicISizes, IntrinsicISizesContribution}; +use table_row::CellIntrinsicInlineSize; use table_wrapper::{TableLayout, FixedLayout, AutoLayout}; use wrapper::ThreadSafeLayoutNode; @@ -105,24 +106,52 @@ impl TableFlow { /// Update the corresponding value of `self_inline_sizes` if a value of `kid_inline_sizes` has /// a larger value than one of `self_inline_sizes`. Returns the minimum and preferred inline /// sizes. - pub fn update_column_inline_sizes(parent_inline_sizes: &mut Vec, - child_inline_sizes: &Vec) - -> IntrinsicISizes { + fn update_automatic_column_inline_sizes(parent_inline_sizes: &mut Vec, + child_cell_inline_sizes: &[CellIntrinsicInlineSize]) + -> IntrinsicISizes { let mut total_inline_sizes = IntrinsicISizes::new(); - for (parent_sizes, child_sizes) in parent_inline_sizes.iter_mut() - .zip(child_inline_sizes.iter()) { - *parent_sizes = ColumnIntrinsicInlineSize { - minimum_length: max(parent_sizes.minimum_length, child_sizes.minimum_length), - percentage: parent_sizes.greatest_percentage(child_sizes), - preferred: max(parent_sizes.preferred, child_sizes.preferred), - constrained: parent_sizes.constrained || child_sizes.constrained - }; + let mut column_index = 0; + for child_cell_inline_size in child_cell_inline_sizes.iter() { + for _ in range(0, child_cell_inline_size.column_span) { + if column_index < parent_inline_sizes.len() { + // We already have some intrinsic size information for this column. Merge it in + // according to the rules specified in INTRINSIC § 4. + let parent_sizes = &mut parent_inline_sizes[column_index]; + if child_cell_inline_size.column_span > 1 { + // TODO(pcwalton): Perform the recursive algorithm specified in INTRINSIC § + // 4. For now we make this column contribute no width. + } else { + let column_size = &child_cell_inline_size.column_size; + *parent_sizes = ColumnInlineSize { + minimum_length: max(parent_sizes.minimum_length, + column_size.minimum_length), + percentage: parent_sizes.greatest_percentage(column_size), + preferred: max(parent_sizes.preferred, column_size.preferred), + constrained: parent_sizes.constrained || column_size.constrained, + } + } + } else { + // We discovered a new column. Initialize its data. + debug_assert!(column_index == parent_inline_sizes.len()); + if child_cell_inline_size.column_span > 1 { + // TODO(pcwalton): Perform the recursive algorithm specified in INTRINSIC § + // 4. For now we make this column contribute no width. + parent_inline_sizes.push(ColumnInlineSize::new()) + } else { + parent_inline_sizes.push(child_cell_inline_size.column_size) + } + } - total_inline_sizes.minimum_inline_size = total_inline_sizes.minimum_inline_size + - parent_sizes.minimum_length; - total_inline_sizes.preferred_inline_size = total_inline_sizes.preferred_inline_size + - parent_sizes.preferred; + total_inline_sizes.minimum_inline_size = total_inline_sizes.minimum_inline_size + + parent_inline_sizes[column_index].minimum_length; + total_inline_sizes.preferred_inline_size = + total_inline_sizes.preferred_inline_size + + parent_inline_sizes[column_index].preferred; + + column_index += 1 + } } + total_inline_sizes } @@ -136,6 +165,39 @@ impl TableFlow { fn assign_block_size_table_base<'a>(&mut self, layout_context: &'a LayoutContext<'a>) { self.block_flow.assign_block_size_block_base(layout_context, MarginsMayNotCollapse); } + + /// Updates the minimum and preferred inline-size calculation for a single row. This is + /// factored out into a separate function because we process children of rowgroups too. + fn update_column_inline_sizes_for_row(child: &mut Flow, + column_inline_sizes: &mut Vec, + computation: &mut IntrinsicISizesContribution, + did_first_row: &mut bool, + table_layout: TableLayout) { + // Read column inline-sizes from the table-row, and assign inline-size=0 for the columns + // not defined in the column group. + // + // FIXME: Need to read inline-sizes from either table-header-group OR the first table-row. + debug_assert!(child.is_table_row()); + let row = child.as_table_row(); + match table_layout { + FixedLayout => { + // Fixed table layout only looks at the first row. + // + // FIXME(pcwalton): This is really inefficient. We should stop after the first row! + if !*did_first_row { + *did_first_row = true; + for cell_inline_size in row.cell_intrinsic_inline_sizes.iter() { + column_inline_sizes.push(cell_inline_size.column_size); + } + } + } + AutoLayout => { + computation.union_block(&TableFlow::update_automatic_column_inline_sizes( + column_inline_sizes, + row.cell_intrinsic_inline_sizes.as_slice())) + } + } + } } impl Flow for TableFlow { @@ -190,50 +252,20 @@ impl Flow for TableFlow { constrained: false, }) } - } else if kid.is_table_rowgroup() || kid.is_table_row() { - // Read column inline-sizes from the table-row-group/table-row, and assign - // inline-size=0 for the columns not defined in the column group. - // FIXME: Need to read inline-sizes from either table-header-group OR the first - // table-row. - match self.table_layout { - FixedLayout => { - // Fixed table layout only looks at the first row. - if !did_first_row { - did_first_row = true; - for child_column_inline_size in kid.column_intrinsic_inline_sizes() - .iter() { - self.column_intrinsic_inline_sizes.push(*child_column_inline_size); - } - } - } - AutoLayout => { - let child_column_inline_sizes = kid.column_intrinsic_inline_sizes(); - let mut child_intrinsic_sizes = TableFlow::update_column_inline_sizes( - &mut self.column_intrinsic_inline_sizes, - child_column_inline_sizes); - - // Add new columns if processing this row caused us to discover them. - let child_column_count = child_column_inline_sizes.len(); - let parent_column_count = self.column_intrinsic_inline_sizes.len(); - debug!("table until the previous row has {} column(s) and this row has {} \ - column(s)", - parent_column_count, - child_column_count); - self.column_intrinsic_inline_sizes.reserve(child_column_count); - for i in range(parent_column_count, child_column_count) { - let inline_size_for_new_column = (*child_column_inline_sizes)[i]; - child_intrinsic_sizes.minimum_inline_size = - child_intrinsic_sizes.minimum_inline_size + - inline_size_for_new_column.minimum_length; - child_intrinsic_sizes.preferred_inline_size = - child_intrinsic_sizes.preferred_inline_size + - inline_size_for_new_column.preferred; - self.column_intrinsic_inline_sizes.push(inline_size_for_new_column); - } - - computation.union_block(&child_intrinsic_sizes) - } + } else if kid.is_table_rowgroup() { + for grandkid in flow::mut_base(kid).child_iter() { + TableFlow::update_column_inline_sizes_for_row(grandkid, + &mut self.column_inline_sizes, + &mut computation, + &mut did_first_row, + self.table_layout) } + } else if kid.is_table_row() { + TableFlow::update_column_inline_sizes_for_row(kid, + &mut self.column_inline_sizes, + &mut computation, + &mut did_first_row, + self.table_layout) } } diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs index 307892635a0..3489cb9c6ff 100644 --- a/components/layout/table_row.rs +++ b/components/layout/table_row.rs @@ -30,20 +30,29 @@ use sync::Arc; pub struct TableRowFlow { pub block_flow: BlockFlow, - /// Information about the intrinsic inline-sizes of each column. - pub column_intrinsic_inline_sizes: Vec, + /// Information about the intrinsic inline-sizes of each cell. + pub cell_intrinsic_inline_sizes: Vec, /// Information about the computed inline-sizes of each column. pub column_computed_inline_sizes: Vec, } +/// Information about the column inline size and span for each cell. +#[deriving(Encodable)] +pub struct CellIntrinsicInlineSize { + /// Inline sizes that this cell contributes to the column. + pub column_size: ColumnInlineSize, + /// The column span of this cell. + pub column_span: u32, +} + impl TableRowFlow { pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment) -> TableRowFlow { TableRowFlow { block_flow: BlockFlow::from_node_and_fragment(node, fragment), - column_intrinsic_inline_sizes: Vec::new(), + cell_intrinsic_inline_sizes: Vec::new(), column_computed_inline_sizes: Vec::new(), } } @@ -53,8 +62,8 @@ impl TableRowFlow { -> TableRowFlow { TableRowFlow { block_flow: BlockFlow::from_node(constructor, node), - column_intrinsic_inline_sizes: Vec::new(), - column_computed_inline_sizes: Vec::new(), + cell_intrinsic_inline_sizes: Vec::new(), + column_computed_inline_sizes: Vec::new() } } @@ -181,10 +190,13 @@ impl Flow for TableRowFlow { // Collect the specified column inline-size of the cell. This is used in both fixed and // automatic table layout calculation. - let child_specified_inline_size = kid.as_table_cell() - .fragment() - .style() - .content_inline_size(); + let child_specified_inline_size; + let child_column_span; + { + let child_style = kid.as_table_cell().fragment().style(); + child_specified_inline_size = child_style.content_inline_size(); + child_column_span = child_style.get_table()._servo_column_span + } // Collect minimum and preferred inline-sizes of the cell for automatic table layout // calculation. @@ -208,15 +220,16 @@ impl Flow for TableRowFlow { }; min_inline_size = min_inline_size + child_column_inline_size.minimum_length; pref_inline_size = pref_inline_size + child_column_inline_size.preferred; - self.column_intrinsic_inline_sizes.push(child_column_inline_size); + self.cell_intrinsic_inline_sizes.push(CellIntrinsicInlineSize { + column_size: child_column_inline_size, + column_span: child_column_span, + }); } self.block_flow.base.intrinsic_inline_sizes.minimum_inline_size = min_inline_size; self.block_flow.base.intrinsic_inline_sizes.preferred_inline_size = max(min_inline_size, pref_inline_size); } - /// Recursively (top-down) determines the actual inline-size of child contexts and fragments. - /// When called on this context, the context has had its inline-size set by the parent context. fn assign_inline_sizes(&mut self, layout_context: &LayoutContext) { let _scope = layout_debug_scope!("table_row::assign_inline_sizes {:x}", self.block_flow.base.debug_id()); @@ -233,11 +246,41 @@ impl Flow for TableRowFlow { layout_context, containing_block_inline_size); + // Spread out the completed inline sizes among columns with spans > 1. + let mut computed_inline_size_for_cells = Vec::new(); + let mut column_inline_size_iterator = self.column_inline_sizes.iter(); + for cell_intrinsic_inline_size in self.cell_intrinsic_inline_sizes.iter() { + //(intrinsic_inline_size_for_column, computed_inline_size_for_column) in + // Start with the computed inline size for the first column in the span. + let mut column_inline_size = match column_inline_size_iterator.next() { + Some(column_inline_size) => *column_inline_size, + None => { + // This could happen if there are too few cells in this row. Don't crash. + break + } + }; + + // Add in computed inline sizes for any extra columns in the span. + for _ in range(1, cell_intrinsic_inline_size.column_span) { + let extra_column_inline_size = match column_inline_size_iterator.next() { + Some(column_inline_size) => column_inline_size, + None => break, + }; + column_inline_size.minimum_length = column_inline_size.minimum_length + + extra_column_inline_size.minimum_length; + column_inline_size.preferred = column_inline_size.preferred + + extra_column_inline_size.preferred; + } + + computed_inline_size_for_cells.push(column_inline_size) + } + + // Push those inline sizes down to the cells. self.block_flow.propagate_assigned_inline_size_to_children( layout_context, inline_start_content_edge, containing_block_inline_size, - Some(self.column_computed_inline_sizes.as_slice())); + Some(computed_inline_size_for_cells.as_slice())); } fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) { diff --git a/components/layout/table_rowgroup.rs b/components/layout/table_rowgroup.rs index c3837185a47..dd5ca85465d 100644 --- a/components/layout/table_rowgroup.rs +++ b/components/layout/table_rowgroup.rs @@ -6,13 +6,12 @@ #![deny(unsafe_blocks)] -use block::{BlockFlow, ISizeAndMarginsComputer, MarginsMayNotCollapse}; +use block::{BlockFlow, ISizeAndMarginsComputer}; use construct::FlowConstructor; use context::LayoutContext; -use flow::{TableRowGroupFlowClass, FlowClass, Flow, ImmutableFlowUtils}; +use flow::{mod, Flow, FlowClass, TableRowGroupFlowClass}; use fragment::{Fragment, FragmentBoundsIterator}; use layout_debug; -use model::IntrinsicISizesContribution; use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable, TableFlow}; use wrapper::ThreadSafeLayoutNode; @@ -24,6 +23,7 @@ use sync::Arc; /// A table formatting context. #[deriving(Encodable)] pub struct TableRowGroupFlow { + /// Fields common to all block flows. pub block_flow: BlockFlow, /// Information about the intrinsic inline-sizes of each column. @@ -91,54 +91,11 @@ impl Flow for TableRowGroupFlow { &mut self.column_computed_inline_sizes } - - /// Recursively (bottom-up) determines the context's preferred and minimum inline-sizes. When - /// called on this context, all child contexts have had their min/pref inline-sizes set. This - /// function must decide min/pref inline-sizes based on child context inline-sizes and - /// dimensions of any fragments it is responsible for flowing. - /// - /// Min/pref inline-sizes set by this function are used in automatic table layout calculation. - /// - /// Also, this function finds the specified column inline-sizes from the first row. These are - /// used in fixed table layout calculation. fn bubble_inline_sizes(&mut self) { let _scope = layout_debug_scope!("table_rowgroup::bubble_inline_sizes {:x}", self.block_flow.base.debug_id()); - - let mut computation = IntrinsicISizesContribution::new(); - for kid in self.block_flow.base.child_iter() { - assert!(kid.is_table_row()); - - // Calculate minimum and preferred inline sizes for automatic table layout. - if self.column_intrinsic_inline_sizes.is_empty() { - // We're the first row. - self.column_intrinsic_inline_sizes = kid.column_intrinsic_inline_sizes().clone(); - } else { - let mut child_intrinsic_sizes = - TableFlow::update_column_inline_sizes(&mut self.column_intrinsic_inline_sizes, - kid.column_intrinsic_inline_sizes()); - - // update the number of column inline-sizes from table-rows. - let column_count = self.column_intrinsic_inline_sizes.len(); - let child_column_count = kid.column_intrinsic_inline_sizes().len(); - for i in range(column_count, child_column_count) { - let this_column_inline_size = (*kid.column_intrinsic_inline_sizes())[i]; - - // FIXME(pcwalton): Ignoring the percentage here seems dubious. - child_intrinsic_sizes.minimum_inline_size = - child_intrinsic_sizes.minimum_inline_size + - this_column_inline_size.minimum_length; - child_intrinsic_sizes.preferred_inline_size = - child_intrinsic_sizes.preferred_inline_size + - this_column_inline_size.preferred; - self.column_intrinsic_inline_sizes.push(this_column_inline_size); - } - - computation.union_block(&child_intrinsic_sizes) - } - } - - self.block_flow.base.intrinsic_inline_sizes = computation.finish() + // Proper calculation of intrinsic sizes in table layout requires access to the entire + // table, which we don't have yet. Defer to our parent. } /// Recursively (top-down) determines the actual inline-size of child contexts and fragments. diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 0cdf78b697d..6795511a3d0 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -44,8 +44,9 @@ use dom::node::{window_from_node}; use dom::nodelist::NodeList; use dom::virtualmethods::{VirtualMethods, vtable_for}; use devtools_traits::AttrInfo; -use style::{mod, BgColorSimpleColorAttribute, BorderUnsignedIntegerAttribute, IntegerAttribute}; -use style::{LengthAttribute, SimpleColorAttribute, SizeIntegerAttribute, UnsignedIntegerAttribute}; +use style::{mod, BgColorSimpleColorAttribute, BorderUnsignedIntegerAttribute}; +use style::{ColSpanUnsignedIntegerAttribute, IntegerAttribute, LengthAttribute}; +use style::{SimpleColorAttribute, SizeIntegerAttribute, UnsignedIntegerAttribute}; use style::{WidthLengthAttribute, matches, parse_selector_list_from_str}; use servo_util::namespace; use servo_util::str::{DOMString, LengthOrPercentageOrAuto, SimpleColor}; @@ -349,6 +350,14 @@ impl RawLayoutElementHelpers for Element { None } } + ColSpanUnsignedIntegerAttribute => { + if self.is_htmltablecellelement() { + let this: &HTMLTableCellElement = mem::transmute(self); + this.get_colspan() + } else { + panic!("I'm not a table cell!") + } + } } } diff --git a/components/script/dom/htmltablecellelement.rs b/components/script/dom/htmltablecellelement.rs index 25a5e9e78b0..81a6ba3f9f0 100644 --- a/components/script/dom/htmltablecellelement.rs +++ b/components/script/dom/htmltablecellelement.rs @@ -22,6 +22,7 @@ pub struct HTMLTableCellElement { htmlelement: HTMLElement, background_color: Cell>, border: Cell>, + colspan: Cell>, width: Cell, } @@ -45,6 +46,7 @@ impl HTMLTableCellElement { htmlelement: HTMLElement::new_inherited(type_id, tag_name, prefix, document), background_color: Cell::new(None), border: Cell::new(None), + colspan: Cell::new(None), width: Cell::new(AutoLpa), } } @@ -58,6 +60,7 @@ impl HTMLTableCellElement { pub trait HTMLTableCellElementHelpers { fn get_background_color(&self) -> Option; fn get_border(&self) -> Option; + fn get_colspan(&self) -> Option; fn get_width(&self) -> LengthOrPercentageOrAuto; } @@ -70,6 +73,10 @@ impl HTMLTableCellElementHelpers for HTMLTableCellElement { self.border.get() } + fn get_colspan(&self) -> Option { + self.colspan.get() + } + fn get_width(&self) -> LengthOrPercentageOrAuto { self.width.get() } @@ -97,6 +104,9 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLTableCellElement> { .as_slice() .chars()).unwrap_or(1))) } + &atom!("colspan") => { + self.colspan.set(str::parse_unsigned_integer(attr.value().as_slice().chars())); + } &atom!("width") => self.width.set(str::parse_length(attr.value().as_slice())), _ => () } @@ -111,6 +121,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLTableCellElement> { match attr.local_name() { &atom!("bgcolor") => self.background_color.set(None), &atom!("border") => self.border.set(None), + &atom!("colspan") => self.colspan.set(None), &atom!("width") => self.width.set(AutoLpa), _ => () } diff --git a/components/script/dom/htmltableelement.rs b/components/script/dom/htmltableelement.rs index 4ece4c8b9f9..d88017fe151 100644 --- a/components/script/dom/htmltableelement.rs +++ b/components/script/dom/htmltableelement.rs @@ -108,6 +108,7 @@ impl HTMLTableElementHelpers for HTMLTableElement { fn get_border(&self) -> Option { self.border.get() } + fn get_width(&self) -> LengthOrPercentageOrAuto { self.width.get() } @@ -135,6 +136,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLTableElement> { .as_slice() .chars()).unwrap_or(1))) } + &atom!("width") => self.width.set(str::parse_length(attr.value().as_slice())), _ => () } } @@ -148,6 +150,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLTableElement> { match attr.local_name() { &atom!("bgcolor") => self.background_color.set(None), &atom!("border") => self.border.set(None), + &atom!("width") => self.width.set(AutoLpa), _ => () } } diff --git a/components/style/legacy.rs b/components/style/legacy.rs index f818fb02480..81c83a02fc4 100644 --- a/components/style/legacy.rs +++ b/components/style/legacy.rs @@ -8,7 +8,8 @@ use node::{TElement, TElementAttributes, TNode}; use properties::{BackgroundColorDeclaration, BorderBottomWidthDeclaration}; use properties::{BorderLeftWidthDeclaration, BorderRightWidthDeclaration}; -use properties::{BorderTopWidthDeclaration, SpecifiedValue, WidthDeclaration, specified}; +use properties::{BorderTopWidthDeclaration, ServoColumnSpanDeclaration, SpecifiedValue}; +use properties::{WidthDeclaration, specified}; use selector_matching::{DeclarationBlock, Stylist}; use cssparser::{RGBA, RGBAColor}; @@ -32,6 +33,8 @@ pub enum IntegerAttribute { pub enum UnsignedIntegerAttribute { /// `` BorderUnsignedIntegerAttribute, + /// `` + ColSpanUnsignedIntegerAttribute, } /// Legacy presentational attributes that take a simple color as defined in HTML5 § 2.4.6. @@ -111,6 +114,14 @@ impl PresentationalHintSynthesis for Stylist { *shareable = false } } + match element.get_unsigned_integer_attribute(ColSpanUnsignedIntegerAttribute) { + None => {} + Some(value) => { + matching_rules_list.vec_push(DeclarationBlock::from_declaration( + ServoColumnSpanDeclaration(SpecifiedValue(value)))); + *shareable = false + } + } self.synthesize_presentational_hint_for_legacy_background_color_attribute( element, matching_rules_list, diff --git a/components/style/lib.rs b/components/style/lib.rs index f2344e3e807..2c88995d521 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -54,9 +54,10 @@ pub use selectors::{PseudoElement, Before, After, SelectorList, parse_selector_l pub use selectors::{AttrSelector, NamespaceConstraint, SpecificNamespace, AnyNamespace}; pub use selectors::{SimpleSelector, LocalNameSelector}; pub use cssparser::{Color, RGBA}; -pub use legacy::{BgColorSimpleColorAttribute, BorderUnsignedIntegerAttribute, IntegerAttribute}; -pub use legacy::{LengthAttribute, SimpleColorAttribute, SizeIntegerAttribute}; -pub use legacy::{UnsignedIntegerAttribute, WidthLengthAttribute}; +pub use legacy::{BgColorSimpleColorAttribute, BorderUnsignedIntegerAttribute}; +pub use legacy::{ColSpanUnsignedIntegerAttribute, IntegerAttribute, LengthAttribute}; +pub use legacy::{SimpleColorAttribute, SizeIntegerAttribute, UnsignedIntegerAttribute}; +pub use legacy::{WidthLengthAttribute}; pub use font_face::{Source, LocalSource, UrlSource_}; mod stylesheets; diff --git a/components/style/properties/mod.rs.mako b/components/style/properties/mod.rs.mako index 2107ac86c7b..f199fa62fb1 100644 --- a/components/style/properties/mod.rs.mako +++ b/components/style/properties/mod.rs.mako @@ -1316,6 +1316,34 @@ pub mod longhands { ${single_keyword("table-layout", "auto fixed")} + <%self:single_component_value name="-servo-column-span"> + // The handling of this property is not well-specified by INTRINSIC, but its presence is + // assumed. HTML5 14.3.9 specifies that the `colspan` attribute is to be a nonnegative + // integer. + pub use super::computed_as_specified as to_computed_value; + pub mod computed_value { + pub type T = u32; + } + pub type SpecifiedValue = computed_value::T; + + #[inline] + pub fn get_initial_value() -> computed_value::T { + 1 + } + + pub fn from_component_value(input: &ComponentValue, _: &Url) -> Result { + match input { + &Number(ref value) => { + match value.int_value { + None => Err(()), + Some(n) => Ok(n as SpecifiedValue), + } + } + _ => Err(()), + } + } + + // CSS 2.1, Section 18 - User interface diff --git a/components/style/selector_matching.rs b/components/style/selector_matching.rs index 12df5e2f35c..6d868028894 100644 --- a/components/style/selector_matching.rs +++ b/components/style/selector_matching.rs @@ -802,8 +802,8 @@ pub fn common_style_affecting_attributes() -> [CommonStyleAffectingAttributeInfo /// Attributes that, if present, disable style sharing. All legacy HTML attributes must be in /// either this list or `common_style_affecting_attributes`. See the comment in /// `synthesize_presentational_hints_for_legacy_attributes`. -pub fn rare_style_affecting_attributes() -> [Atom, ..2] { - [ atom!("bgcolor"), atom!("border") ] +pub fn rare_style_affecting_attributes() -> [Atom, ..3] { + [ atom!("bgcolor"), atom!("border"), atom!("colspan") ] } /// Determines whether the given element matches the given single selector. diff --git a/tests/ref/basic.list b/tests/ref/basic.list index a31d6009b74..d522369e4c3 100644 --- a/tests/ref/basic.list +++ b/tests/ref/basic.list @@ -209,5 +209,6 @@ fragment=top != ../html/acid2.html acid2_ref.html == box_shadow_inset_parsing_a.html box_shadow_inset_parsing_ref.html != list_style_type_a.html list_style_type_ref.html == list_style_position_a.html list_style_position_ref.html +== table_colspan_simple_a.html table_colspan_simple_ref.html == legacy_td_bgcolor_attribute_a.html legacy_td_bgcolor_attribute_ref.html == legacy_table_border_attribute_a.html legacy_table_border_attribute_ref.html diff --git a/tests/ref/table_colspan_simple_a.html b/tests/ref/table_colspan_simple_a.html new file mode 100644 index 00000000000..41993cc01f5 --- /dev/null +++ b/tests/ref/table_colspan_simple_a.html @@ -0,0 +1,22 @@ + + + + + + + + + +
   
  
  
 
+ + + diff --git a/tests/ref/table_colspan_simple_ref.html b/tests/ref/table_colspan_simple_ref.html new file mode 100644 index 00000000000..7758b688985 --- /dev/null +++ b/tests/ref/table_colspan_simple_ref.html @@ -0,0 +1,22 @@ + + + + + + + + + +
   
  
  
 
+ + +