diff options
-rw-r--r-- | components/layout/wrapper.rs | 12 | ||||
-rw-r--r-- | components/script/dom/bindings/trace.rs | 3 | ||||
-rw-r--r-- | components/script/dom/element.rs | 41 | ||||
-rw-r--r-- | components/script/dom/htmlbodyelement.rs | 53 | ||||
-rw-r--r-- | components/script/dom/htmltablecellelement.rs | 14 | ||||
-rw-r--r-- | components/script/dom/htmltableelement.rs | 13 | ||||
-rw-r--r-- | components/servo/Cargo.lock | 3 | ||||
-rw-r--r-- | components/style/legacy.rs | 70 | ||||
-rw-r--r-- | components/style/lib.rs | 5 | ||||
-rw-r--r-- | components/style/node.rs | 5 | ||||
-rw-r--r-- | components/style/selector_matching.rs | 4 | ||||
-rw-r--r-- | components/util/Cargo.toml | 3 | ||||
-rw-r--r-- | components/util/lib.rs | 1 | ||||
-rw-r--r-- | components/util/str.rs | 133 | ||||
-rw-r--r-- | ports/cef/Cargo.lock | 2 | ||||
-rw-r--r-- | ports/gonk/Cargo.lock | 2 | ||||
-rw-r--r-- | tests/ref/basic.list | 1 | ||||
-rw-r--r-- | tests/ref/legacy_td_bgcolor_attribute_a.html | 20 | ||||
-rw-r--r-- | tests/ref/legacy_td_bgcolor_attribute_ref.html | 21 |
19 files changed, 370 insertions, 36 deletions
diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs index ba16eb885a9..41c05e1646c 100644 --- a/components/layout/wrapper.rs +++ b/components/layout/wrapper.rs @@ -53,14 +53,14 @@ use script::dom::node::{HAS_CHANGED, IS_DIRTY, HAS_DIRTY_SIBLINGS, HAS_DIRTY_DES use script::dom::text::Text; use script::layout_interface::LayoutChan; use servo_msg::constellation_msg::{PipelineId, SubpageId}; -use servo_util::str::{LengthOrPercentageOrAuto, is_whitespace}; +use servo_util::str::{LengthOrPercentageOrAuto, SimpleColor, is_whitespace}; use std::kinds::marker::ContravariantLifetime; use std::mem; use string_cache::{Atom, Namespace}; use style::computed_values::{content, display, white_space}; use style::{AnyNamespace, AttrSelector, BorderUnsignedIntegerAttribute, IntegerAttribute}; -use style::{LengthAttribute, PropertyDeclarationBlock, SpecificNamespace, TElement}; -use style::{TElementAttributes, TNode, UnsignedIntegerAttribute}; +use style::{LengthAttribute, PropertyDeclarationBlock, SimpleColorAttribute, SpecificNamespace}; +use style::{TElement, TElementAttributes, TNode, UnsignedIntegerAttribute}; use url::Url; use std::cell::{Ref, RefMut}; @@ -612,6 +612,12 @@ impl<'le> TElementAttributes for LayoutElement<'le> { self.element.get_unsigned_integer_attribute_for_layout(attribute) } } + + fn get_simple_color_attribute(self, attribute: SimpleColorAttribute) -> Option<SimpleColor> { + unsafe { + self.element.get_simple_color_attribute_for_layout(attribute) + } + } } fn get_content(content_list: &content::T) -> String { diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index afd329137c0..d5acb22ad7b 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -48,7 +48,7 @@ use script_traits::UntrustedNodeAddress; use servo_msg::compositor_msg::ScriptListener; use servo_msg::constellation_msg::ConstellationChan; use servo_util::smallvec::{SmallVec1, SmallVec}; -use servo_util::str::LengthOrPercentageOrAuto; +use servo_util::str::{LengthOrPercentageOrAuto, SimpleColor}; use std::cell::{Cell, RefCell}; use std::collections::HashMap; use std::comm::{Receiver, Sender}; @@ -214,6 +214,7 @@ no_jsmanaged_fields!(LayoutChan) no_jsmanaged_fields!(WindowProxyHandler) no_jsmanaged_fields!(UntrustedNodeAddress) no_jsmanaged_fields!(LengthOrPercentageOrAuto) +no_jsmanaged_fields!(SimpleColor) impl<'a> JSTraceable for &'a str { #[inline] diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index db2b8d3d096..0cdf78b697d 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -16,9 +16,10 @@ use dom::bindings::codegen::Bindings::EventBinding::EventMethods; use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods; use dom::bindings::codegen::Bindings::NamedNodeMapBinding::NamedNodeMapMethods; use dom::bindings::codegen::InheritTypes::{ElementCast, ElementDerived, EventTargetCast}; -use dom::bindings::codegen::InheritTypes::{HTMLInputElementCast, HTMLInputElementDerived}; -use dom::bindings::codegen::InheritTypes::{HTMLTableElementCast, HTMLTableElementDerived}; -use dom::bindings::codegen::InheritTypes::{HTMLTableCellElementDerived, NodeCast}; +use dom::bindings::codegen::InheritTypes::{HTMLBodyElementDerived, HTMLInputElementCast}; +use dom::bindings::codegen::InheritTypes::{HTMLInputElementDerived, HTMLTableElementCast}; +use dom::bindings::codegen::InheritTypes::{HTMLTableElementDerived, HTMLTableCellElementDerived}; +use dom::bindings::codegen::InheritTypes::{NodeCast}; use dom::bindings::js::{MutNullableJS, JS, JSRef, Temporary, TemporaryPushable}; use dom::bindings::js::{OptionalRootable, Root}; use dom::bindings::utils::{Reflectable, Reflector}; @@ -31,6 +32,7 @@ use dom::document::{Document, DocumentHelpers, LayoutDocumentHelpers}; use dom::domtokenlist::DOMTokenList; use dom::event::Event; use dom::eventtarget::{EventTarget, NodeTargetTypeId, EventTargetHelpers}; +use dom::htmlbodyelement::{HTMLBodyElement, HTMLBodyElementHelpers}; use dom::htmlcollection::HTMLCollection; use dom::htmlinputelement::{HTMLInputElement, RawLayoutHTMLInputElementHelpers}; use dom::htmlserializer::serialize; @@ -42,12 +44,11 @@ use dom::node::{window_from_node}; use dom::nodelist::NodeList; use dom::virtualmethods::{VirtualMethods, vtable_for}; use devtools_traits::AttrInfo; -use style::{BorderUnsignedIntegerAttribute, IntegerAttribute, LengthAttribute}; -use style::{SizeIntegerAttribute, UnsignedIntegerAttribute, WidthLengthAttribute}; -use style::{matches, parse_selector_list_from_str}; -use style; +use style::{mod, BgColorSimpleColorAttribute, BorderUnsignedIntegerAttribute, IntegerAttribute}; +use style::{LengthAttribute, SimpleColorAttribute, SizeIntegerAttribute, UnsignedIntegerAttribute}; +use style::{WidthLengthAttribute, matches, parse_selector_list_from_str}; use servo_util::namespace; -use servo_util::str::{DOMString, LengthOrPercentageOrAuto}; +use servo_util::str::{DOMString, LengthOrPercentageOrAuto, SimpleColor}; use std::ascii::AsciiExt; use std::cell::{Ref, RefMut}; @@ -207,6 +208,8 @@ pub trait RawLayoutElementHelpers { unsafe fn get_checked_state_for_layout(&self) -> bool; unsafe fn get_unsigned_integer_attribute_for_layout(&self, attribute: UnsignedIntegerAttribute) -> Option<u32>; + unsafe fn get_simple_color_attribute_for_layout(&self, attribute: SimpleColorAttribute) + -> Option<SimpleColor>; fn local_name<'a>(&'a self) -> &'a Atom; fn namespace<'a>(&'a self) -> &'a Namespace; fn style_attribute<'a>(&'a self) -> &'a DOMRefCell<Option<style::PropertyDeclarationBlock>>; @@ -349,6 +352,28 @@ impl RawLayoutElementHelpers for Element { } } + #[inline] + #[allow(unrooted_must_root)] + unsafe fn get_simple_color_attribute_for_layout(&self, attribute: SimpleColorAttribute) + -> Option<SimpleColor> { + match attribute { + BgColorSimpleColorAttribute => { + if self.is_htmlbodyelement() { + let this: &HTMLBodyElement = mem::transmute(self); + this.get_background_color() + } else if self.is_htmltableelement() { + let this: &HTMLTableElement = mem::transmute(self); + this.get_background_color() + } else if self.is_htmltablecellelement() { + let this: &HTMLTableCellElement = mem::transmute(self); + this.get_background_color() + } else { + panic!("I'm not a body, table, or table cell!") + } + } + } + } + // Getters used in components/layout/wrapper.rs fn local_name<'a>(&'a self) -> &'a Atom { diff --git a/components/script/dom/htmlbodyelement.rs b/components/script/dom/htmlbodyelement.rs index d088a6b8626..ebfe1e8025a 100644 --- a/components/script/dom/htmlbodyelement.rs +++ b/components/script/dom/htmlbodyelement.rs @@ -2,11 +2,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use dom::attr::Attr; -use dom::attr::AttrHelpers; +use dom::attr::{Attr, AttrHelpers}; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; -use dom::bindings::codegen::Bindings::HTMLBodyElementBinding; -use dom::bindings::codegen::Bindings::HTMLBodyElementBinding::HTMLBodyElementMethods; +use dom::bindings::codegen::Bindings::HTMLBodyElementBinding::{mod, HTMLBodyElementMethods}; use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::codegen::InheritTypes::EventTargetCast; use dom::bindings::codegen::InheritTypes::{HTMLBodyElementDerived, HTMLElementCast}; @@ -19,11 +17,13 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId, window_from_node}; use dom::virtualmethods::VirtualMethods; -use servo_util::str::DOMString; +use servo_util::str::{mod, DOMString, SimpleColor}; +use std::cell::Cell; #[dom_struct] pub struct HTMLBodyElement { - htmlelement: HTMLElement + htmlelement: HTMLElement, + background_color: Cell<Option<SimpleColor>>, } impl HTMLBodyElementDerived for EventTarget { @@ -33,14 +33,20 @@ impl HTMLBodyElementDerived for EventTarget { } impl HTMLBodyElement { - fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLBodyElement { + fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) + -> HTMLBodyElement { HTMLBodyElement { - htmlelement: HTMLElement::new_inherited(HTMLBodyElementTypeId, localName, prefix, document) + htmlelement: HTMLElement::new_inherited(HTMLBodyElementTypeId, + localName, + prefix, + document), + background_color: Cell::new(None), } } #[allow(unrooted_must_root)] - pub fn new(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> Temporary<HTMLBodyElement> { + pub fn new(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) + -> Temporary<HTMLBodyElement> { let element = HTMLBodyElement::new_inherited(localName, prefix, document); Node::reflect_node(box element, document, HTMLBodyElementBinding::Wrap) } @@ -58,6 +64,16 @@ impl<'a> HTMLBodyElementMethods for JSRef<'a, HTMLBodyElement> { } } +pub trait HTMLBodyElementHelpers { + fn get_background_color(&self) -> Option<SimpleColor>; +} + +impl HTMLBodyElementHelpers for HTMLBodyElement { + fn get_background_color(&self) -> Option<SimpleColor> { + self.background_color.get() + } +} + impl<'a> VirtualMethods for JSRef<'a, HTMLBodyElement> { fn super_type<'a>(&'a self) -> Option<&'a VirtualMethods> { let element: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self); @@ -91,6 +107,25 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLBodyElement> { name.slice_from(2), attr.value().as_slice().to_string()); } + + match attr.local_name() { + &atom!("bgcolor") => { + self.background_color.set(str::parse_legacy_color(attr.value().as_slice()).ok()) + } + _ => {} + } + } + + fn before_remove_attr(&self, attr: JSRef<Attr>) { + match self.super_type() { + Some(ref s) => s.before_remove_attr(attr), + _ => {} + } + + match attr.local_name() { + &atom!("bgcolor") => self.background_color.set(None), + _ => {} + } } } diff --git a/components/script/dom/htmltablecellelement.rs b/components/script/dom/htmltablecellelement.rs index 622389397e9..25a5e9e78b0 100644 --- a/components/script/dom/htmltablecellelement.rs +++ b/components/script/dom/htmltablecellelement.rs @@ -14,13 +14,13 @@ use dom::htmlelement::HTMLElement; use dom::node::ElementNodeTypeId; use dom::virtualmethods::VirtualMethods; -use servo_util::str::{AutoLpa, DOMString, LengthOrPercentageOrAuto}; -use servo_util::str; +use servo_util::str::{mod, AutoLpa, DOMString, LengthOrPercentageOrAuto, SimpleColor}; use std::cell::Cell; #[dom_struct] pub struct HTMLTableCellElement { htmlelement: HTMLElement, + background_color: Cell<Option<SimpleColor>>, border: Cell<Option<u32>>, width: Cell<LengthOrPercentageOrAuto>, } @@ -43,6 +43,7 @@ impl HTMLTableCellElement { -> HTMLTableCellElement { HTMLTableCellElement { htmlelement: HTMLElement::new_inherited(type_id, tag_name, prefix, document), + background_color: Cell::new(None), border: Cell::new(None), width: Cell::new(AutoLpa), } @@ -55,11 +56,16 @@ impl HTMLTableCellElement { } pub trait HTMLTableCellElementHelpers { + fn get_background_color(&self) -> Option<SimpleColor>; fn get_border(&self) -> Option<u32>; fn get_width(&self) -> LengthOrPercentageOrAuto; } impl HTMLTableCellElementHelpers for HTMLTableCellElement { + fn get_background_color(&self) -> Option<SimpleColor> { + self.background_color.get() + } + fn get_border(&self) -> Option<u32> { self.border.get() } @@ -82,6 +88,9 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLTableCellElement> { } match attr.local_name() { + &atom!("bgcolor") => { + self.background_color.set(str::parse_legacy_color(attr.value().as_slice()).ok()) + } &atom!("border") => { // According to HTML5 § 14.3.9, invalid values map to 1px. self.border.set(Some(str::parse_unsigned_integer(attr.value() @@ -100,6 +109,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!("width") => self.width.set(AutoLpa), _ => () diff --git a/components/script/dom/htmltableelement.rs b/components/script/dom/htmltableelement.rs index 9a7acd02559..4ece4c8b9f9 100644 --- a/components/script/dom/htmltableelement.rs +++ b/components/script/dom/htmltableelement.rs @@ -18,12 +18,13 @@ use dom::htmltablecaptionelement::HTMLTableCaptionElement; use dom::node::{Node, NodeHelpers, ElementNodeTypeId}; use dom::virtualmethods::VirtualMethods; -use servo_util::str::{mod, AutoLpa, DOMString, LengthOrPercentageOrAuto}; +use servo_util::str::{mod, AutoLpa, DOMString, LengthOrPercentageOrAuto, SimpleColor}; use std::cell::Cell; #[dom_struct] pub struct HTMLTableElement { htmlelement: HTMLElement, + background_color: Cell<Option<SimpleColor>>, border: Cell<Option<u32>>, width: Cell<LengthOrPercentageOrAuto>, } @@ -42,6 +43,7 @@ impl HTMLTableElement { localName, prefix, document), + background_color: Cell::new(None), border: Cell::new(None), width: Cell::new(AutoLpa), } @@ -93,11 +95,16 @@ impl<'a> HTMLTableElementMethods for JSRef<'a, HTMLTableElement> { } pub trait HTMLTableElementHelpers { + fn get_background_color(&self) -> Option<SimpleColor>; fn get_border(&self) -> Option<u32>; fn get_width(&self) -> LengthOrPercentageOrAuto; } impl HTMLTableElementHelpers for HTMLTableElement { + fn get_background_color(&self) -> Option<SimpleColor> { + self.background_color.get() + } + fn get_border(&self) -> Option<u32> { self.border.get() } @@ -119,6 +126,9 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLTableElement> { } match attr.local_name() { + &atom!("bgcolor") => { + self.background_color.set(str::parse_legacy_color(attr.value().as_slice()).ok()) + } &atom!("border") => { // According to HTML5 § 14.3.9, invalid values map to 1px. self.border.set(Some(str::parse_unsigned_integer(attr.value() @@ -136,6 +146,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), _ => () } diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index bb04bd528af..6c4b2708b9e 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -121,7 +121,7 @@ dependencies = [ [[package]] name = "cssparser" version = "0.1.0" -source = "git+https://github.com/servo/rust-cssparser#cbbfd66f794bd019bbdeaefc88b29eff455b62e5" +source = "git+https://github.com/servo/rust-cssparser#3f98f1308b769b5d61efc6c133ac520df2b074ac" dependencies = [ "encoding 0.2.0 (git+https://github.com/lifthrasiir/rust-encoding)", ] @@ -672,6 +672,7 @@ dependencies = [ name = "util" version = "0.0.1" dependencies = [ + "cssparser 0.1.0 (git+https://github.com/servo/rust-cssparser)", "geom 0.1.0 (git+https://github.com/servo/rust-geom)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "string_cache 0.0.0 (git+https://github.com/servo/string-cache)", diff --git a/components/style/legacy.rs b/components/style/legacy.rs index 8eb9a7d1e56..f818fb02480 100644 --- a/components/style/legacy.rs +++ b/components/style/legacy.rs @@ -6,11 +6,12 @@ //! `<input size>`, and so forth. use node::{TElement, TElementAttributes, TNode}; -use properties::{BorderBottomWidthDeclaration, BorderLeftWidthDeclaration}; -use properties::{BorderRightWidthDeclaration, BorderTopWidthDeclaration, SpecifiedValue}; -use properties::{WidthDeclaration, specified}; +use properties::{BackgroundColorDeclaration, BorderBottomWidthDeclaration}; +use properties::{BorderLeftWidthDeclaration, BorderRightWidthDeclaration}; +use properties::{BorderTopWidthDeclaration, SpecifiedValue, WidthDeclaration, specified}; use selector_matching::{DeclarationBlock, Stylist}; +use cssparser::{RGBA, RGBAColor}; use servo_util::geometry::Au; use servo_util::smallvec::VecLike; use servo_util::str::{AutoLpa, LengthLpa, PercentageLpa}; @@ -33,11 +34,22 @@ pub enum UnsignedIntegerAttribute { BorderUnsignedIntegerAttribute, } +/// Legacy presentational attributes that take a simple color as defined in HTML5 § 2.4.6. +pub enum SimpleColorAttribute { + /// `<body bgcolor>` + BgColorSimpleColorAttribute, +} + /// Extension methods for `Stylist` that cause rules to be synthesized for legacy attributes. pub trait PresentationalHintSynthesis { /// Synthesizes rules from various HTML attributes (mostly legacy junk from HTML4) that confer /// *presentational hints* as defined in the HTML5 specification. This handles stuff like /// `<body bgcolor>`, `<input size>`, `<td width>`, and so forth. + /// + /// NB: Beware! If you add an attribute to this list, be sure to add it to + /// `common_style_affecting_attributes` or `rare_style_affecting_attributes` as appropriate. If + /// you don't, you risk strange random nondeterministic failures due to false positives in + /// style sharing. fn synthesize_presentational_hints_for_legacy_attributes<'a,E,N,V>( &self, node: &N, @@ -47,6 +59,18 @@ pub trait PresentationalHintSynthesis { TElementAttributes, N: TNode<'a,E>, V: VecLike<DeclarationBlock>; + /// Synthesizes rules for the legacy `bgcolor` attribute. + fn synthesize_presentational_hint_for_legacy_background_color_attribute<'a,E,V>( + &self, + element: E, + matching_rules_list: + &mut V, + shareable: &mut bool) + where + E: TElement<'a> + + TElementAttributes, + V: VecLike< + DeclarationBlock>; /// Synthesizes rules for the legacy `border` attribute. fn synthesize_presentational_hint_for_legacy_border_attribute<'a,E,V>( &self, @@ -87,17 +111,31 @@ impl PresentationalHintSynthesis for Stylist { *shareable = false } } + self.synthesize_presentational_hint_for_legacy_background_color_attribute( + element, + matching_rules_list, + shareable); self.synthesize_presentational_hint_for_legacy_border_attribute( element, matching_rules_list, shareable); } name if *name == atom!("table") => { + self.synthesize_presentational_hint_for_legacy_background_color_attribute( + element, + matching_rules_list, + shareable); self.synthesize_presentational_hint_for_legacy_border_attribute( element, matching_rules_list, shareable); } + name if *name == atom!("body") => { + self.synthesize_presentational_hint_for_legacy_background_color_attribute( + element, + matching_rules_list, + shareable); + } name if *name == atom!("input") => { match element.get_integer_attribute(SizeIntegerAttribute) { Some(value) if value != 0 => { @@ -123,6 +161,32 @@ impl PresentationalHintSynthesis for Stylist { } } + fn synthesize_presentational_hint_for_legacy_background_color_attribute<'a,E,V>( + &self, + element: E, + matching_rules_list: + &mut V, + shareable: &mut bool) + where + E: TElement<'a> + + TElementAttributes, + V: VecLike< + DeclarationBlock> { + match element.get_simple_color_attribute(BgColorSimpleColorAttribute) { + None => {} + Some(color) => { + matching_rules_list.vec_push(DeclarationBlock::from_declaration( + BackgroundColorDeclaration(SpecifiedValue(RGBAColor(RGBA { + red: color.red as f32 / 255.0, + green: color.green as f32 / 255.0, + blue: color.blue as f32 / 255.0, + alpha: 1.0, + }))))); + *shareable = false + } + } + } + fn synthesize_presentational_hint_for_legacy_border_attribute<'a,E,V>( &self, element: E, diff --git a/components/style/lib.rs b/components/style/lib.rs index 23a674151b4..f2344e3e807 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -54,8 +54,9 @@ 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::{BorderUnsignedIntegerAttribute, IntegerAttribute, LengthAttribute}; -pub use legacy::{SizeIntegerAttribute, UnsignedIntegerAttribute, WidthLengthAttribute}; +pub use legacy::{BgColorSimpleColorAttribute, BorderUnsignedIntegerAttribute, IntegerAttribute}; +pub use legacy::{LengthAttribute, SimpleColorAttribute, SizeIntegerAttribute}; +pub use legacy::{UnsignedIntegerAttribute, WidthLengthAttribute}; pub use font_face::{Source, LocalSource, UrlSource_}; mod stylesheets; diff --git a/components/style/node.rs b/components/style/node.rs index 3d9ad18e623..4866f27e6c5 100644 --- a/components/style/node.rs +++ b/components/style/node.rs @@ -5,9 +5,9 @@ //! Traits that nodes must implement. Breaks the otherwise-cyclic dependency between layout and //! style. -use legacy::{IntegerAttribute, LengthAttribute, UnsignedIntegerAttribute}; +use legacy::{IntegerAttribute, LengthAttribute, SimpleColorAttribute, UnsignedIntegerAttribute}; use selectors::AttrSelector; -use servo_util::str::LengthOrPercentageOrAuto; +use servo_util::str::{LengthOrPercentageOrAuto, SimpleColor}; use string_cache::{Atom, Namespace}; pub trait TNode<'a, E: TElement<'a>> : Clone + Copy { @@ -60,4 +60,5 @@ pub trait TElementAttributes : Copy { fn get_length_attribute(self, attribute: LengthAttribute) -> LengthOrPercentageOrAuto; fn get_integer_attribute(self, attribute: IntegerAttribute) -> Option<i32>; fn get_unsigned_integer_attribute(self, attribute: UnsignedIntegerAttribute) -> Option<u32>; + fn get_simple_color_attribute(self, attribute: SimpleColorAttribute) -> Option<SimpleColor>; } diff --git a/components/style/selector_matching.rs b/components/style/selector_matching.rs index b1fbd5042e8..12df5e2f35c 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, ..1] { - [ atom!("border") ] +pub fn rare_style_affecting_attributes() -> [Atom, ..2] { + [ atom!("bgcolor"), atom!("border") ] } /// Determines whether the given element matches the given single selector. diff --git a/components/util/Cargo.toml b/components/util/Cargo.toml index 29fc71d25a5..331fd2fb840 100644 --- a/components/util/Cargo.toml +++ b/components/util/Cargo.toml @@ -7,6 +7,9 @@ authors = ["The Servo Project Developers"] name = "util" path = "lib.rs" +[dependencies.cssparser] +git = "https://github.com/servo/rust-cssparser" + [dependencies.geom] git = "https://github.com/servo/rust-geom" diff --git a/components/util/lib.rs b/components/util/lib.rs index f556dda6eb9..b0e4cff8c62 100644 --- a/components/util/lib.rs +++ b/components/util/lib.rs @@ -13,6 +13,7 @@ extern crate log; extern crate alloc; extern crate collections; +extern crate cssparser; extern crate geom; extern crate getopts; extern crate layers; diff --git a/components/util/str.rs b/components/util/str.rs index 0428d0db5b2..ebc494c2642 100644 --- a/components/util/str.rs +++ b/components/util/str.rs @@ -4,6 +4,8 @@ use geometry::Au; +use cssparser::{mod, RGBAColor}; +use std::ascii::AsciiExt; use std::from_str::FromStr; use std::iter::Filter; use std::str::{CharEq, CharSplits}; @@ -184,6 +186,137 @@ pub fn parse_length(mut value: &str) -> LengthOrPercentageOrAuto { } } +/// A "simple color" per HTML5 § 2.4.6. +#[deriving(Show)] +pub struct SimpleColor { + /// The red component of the color, [0, 255]. + pub red: u8, + /// The green component of the color, [0, 255]. + pub green: u8, + /// The blue component of the color, [0, 255]. + pub blue: u8, +} + +/// Parses a legacy color per HTML5 § 2.4.6. If unparseable, `Err` is returned. +pub fn parse_legacy_color(mut input: &str) -> Result<SimpleColor,()> { + // Steps 1 and 2. + if input.len() == 0 { + return Err(()) + } + + // Step 3. + input = input.trim_left_chars(Whitespace).trim_right_chars(Whitespace); + + // Step 4. + if input.eq_ignore_ascii_case("transparent") { + return Err(()) + } + + // Step 5. + match cssparser::parse_color_keyword(input) { + Ok(RGBAColor(rgba)) => { + return Ok(SimpleColor { + red: (rgba.red * 255.0) as u8, + green: (rgba.green * 255.0) as u8, + blue: (rgba.blue * 255.0) as u8, + }) + } + _ => {} + } + + // Step 6. + if input.len() == 4 { + match (input.char_at(0), + hex(input.char_at(1)), + hex(input.char_at(2)), + hex(input.char_at(3))) { + ('#', Ok(r), Ok(g), Ok(b)) => { + return Ok(SimpleColor { + red: r * 17, + green: g * 17, + blue: b * 17, + }) + } + _ => {} + } + } + + // Step 7. + let mut new_input = String::new(); + for ch in input.chars() { + if ch as u32 > 0xffff { + new_input.push_str("00") + } else { + new_input.push(ch) + } + } + let mut input = new_input.as_slice(); + + // Step 8. + if input.len() > 128 { + input = input.slice_to(128) + } + + // Step 9. + if input.char_at(0) == '#' { + input = input.slice_from(1) + } + + // Step 10. + let mut new_input = Vec::new(); + for ch in input.chars() { + if hex(ch).is_ok() { + new_input.push(ch as u8) + } else { + new_input.push(b'0') + } + } + let mut input = new_input; + + // Step 11. + while input.len() == 0 || (input.len() % 3) != 0 { + input.push(b'0') + } + + // Step 12. + let mut length = input.len() / 3; + let (mut red, mut green, mut blue) = (input.slice_to(length), + input.slice(length, length * 2), + input.slice_from(length * 2)); + + // Step 13. + if length > 8 { + red = red.slice_from(length - 8); + green = green.slice_from(length - 8); + blue = blue.slice_from(length - 8); + length = 8 + } + + // Step 14. + while length > 2 && red[0] == b'0' && green[0] == b'0' && blue[0] == b'0' { + red = red.slice_from(1); + green = green.slice_from(1); + blue = blue.slice_from(1); + length -= 1 + } + + // Steps 15-20. + return Ok(SimpleColor { + red: (hex(red[0] as char).unwrap() << 4) | hex(red[1] as char).unwrap(), + green: (hex(green[0] as char).unwrap() << 4) | hex(green[1] as char).unwrap(), + blue: (hex(blue[0] as char).unwrap() << 4) | hex(blue[1] as char).unwrap(), + }); + + fn hex(ch: char) -> Result<u8,()> { + match ch { + '0'...'9' => Ok((ch as u8) - b'0'), + 'a'...'f' => Ok((ch as u8) - b'a' + 10), + 'A'...'F' => Ok((ch as u8) - b'A' + 10), + _ => Err(()), + } + } +} + #[deriving(Clone, Eq, PartialEq, Hash, Show)] pub struct LowercaseString { diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index 442926ffa84..460ffbd04df 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -118,7 +118,7 @@ dependencies = [ [[package]] name = "cssparser" version = "0.1.0" -source = "git+https://github.com/servo/rust-cssparser#cbbfd66f794bd019bbdeaefc88b29eff455b62e5" +source = "git+https://github.com/servo/rust-cssparser#3f98f1308b769b5d61efc6c133ac520df2b074ac" dependencies = [ "encoding 0.2.0 (git+https://github.com/lifthrasiir/rust-encoding)", ] diff --git a/ports/gonk/Cargo.lock b/ports/gonk/Cargo.lock index 2641812ade7..9a81bc9a406 100644 --- a/ports/gonk/Cargo.lock +++ b/ports/gonk/Cargo.lock @@ -101,7 +101,7 @@ dependencies = [ [[package]] name = "cssparser" version = "0.1.0" -source = "git+https://github.com/servo/rust-cssparser#cbbfd66f794bd019bbdeaefc88b29eff455b62e5" +source = "git+https://github.com/servo/rust-cssparser#3f98f1308b769b5d61efc6c133ac520df2b074ac" dependencies = [ "encoding 0.2.0 (git+https://github.com/lifthrasiir/rust-encoding)", ] diff --git a/tests/ref/basic.list b/tests/ref/basic.list index 980350b5d9a..a31d6009b74 100644 --- a/tests/ref/basic.list +++ b/tests/ref/basic.list @@ -209,4 +209,5 @@ 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 +== 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/legacy_td_bgcolor_attribute_a.html b/tests/ref/legacy_td_bgcolor_attribute_a.html new file mode 100644 index 00000000000..d565feadacd --- /dev/null +++ b/tests/ref/legacy_td_bgcolor_attribute_a.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<html> +<body> +<table border=0 cellspacing=0 cellpadding=0> + <tr><td bgcolor=chucknorris width=100> </td></tr> + <tr><td bgcolor=ChuckNorris width=100> </td></tr> + <tr><td bgcolor=sick width=100> </td></tr> + <tr><td bgcolor=crap width=100> </td></tr> + <tr><td bgcolor=LuckBeALadyTonight width=100> </td></tr> + <tr><td bgcolor=#abc width=100> </td></tr> + <tr><td bgcolor=#123456 width=100> </td></tr> + <tr><td bgcolor=#abacab width=100> </td></tr> + <tr><td bgcolor=#AbaCab width=100> </td></tr> + <tr><td bgcolor=#ABACAB width=100> </td></tr> + <tr><td bgcolor=transparent width=100> </td></tr> + <tr><td bgcolor=gold width=100> </td></tr> +</table> +</body> +</html> + diff --git a/tests/ref/legacy_td_bgcolor_attribute_ref.html b/tests/ref/legacy_td_bgcolor_attribute_ref.html new file mode 100644 index 00000000000..88038dd685b --- /dev/null +++ b/tests/ref/legacy_td_bgcolor_attribute_ref.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html> +<body> +<table border=0 cellspacing=0 cellpadding=0> + <tr><td style="background: #c00000" width=100> </td></tr> + <tr><td style="background: #c00000" width=100> </td></tr> + <tr><td style="background: #00c000" width=100> </td></tr> + <tr><td style="background: #c0a000" width=100> </td></tr> + <tr><td style="background: #00a000" width=100> </td></tr> + <tr><td style="background: #aabbcc" width=100> </td></tr> + <tr><td style="background: #123456" width=100> </td></tr> + <tr><td style="background: #abacab" width=100> </td></tr> + <tr><td style="background: #abacab" width=100> </td></tr> + <tr><td style="background: #abacab" width=100> </td></tr> + <tr><td width=100> </td></tr> + <tr><td style="background: gold" width=100> </td></tr> +</table> +</body> +</html> + + |