style: Parse the legacy bgcolor attribute per the HTML5 specification.

Additionally, this patch cleans up some miscellaneous formatting issues.
This commit is contained in:
Patrick Walton 2014-12-07 22:59:38 -08:00
parent 10f1ed5e31
commit 14bafb11be
19 changed files with 370 additions and 36 deletions

View file

@ -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::dom::text::Text;
use script::layout_interface::LayoutChan; use script::layout_interface::LayoutChan;
use servo_msg::constellation_msg::{PipelineId, SubpageId}; 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::kinds::marker::ContravariantLifetime;
use std::mem; use std::mem;
use string_cache::{Atom, Namespace}; use string_cache::{Atom, Namespace};
use style::computed_values::{content, display, white_space}; use style::computed_values::{content, display, white_space};
use style::{AnyNamespace, AttrSelector, BorderUnsignedIntegerAttribute, IntegerAttribute}; use style::{AnyNamespace, AttrSelector, BorderUnsignedIntegerAttribute, IntegerAttribute};
use style::{LengthAttribute, PropertyDeclarationBlock, SpecificNamespace, TElement}; use style::{LengthAttribute, PropertyDeclarationBlock, SimpleColorAttribute, SpecificNamespace};
use style::{TElementAttributes, TNode, UnsignedIntegerAttribute}; use style::{TElement, TElementAttributes, TNode, UnsignedIntegerAttribute};
use url::Url; use url::Url;
use std::cell::{Ref, RefMut}; use std::cell::{Ref, RefMut};
@ -612,6 +612,12 @@ impl<'le> TElementAttributes for LayoutElement<'le> {
self.element.get_unsigned_integer_attribute_for_layout(attribute) 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 { fn get_content(content_list: &content::T) -> String {

View file

@ -48,7 +48,7 @@ use script_traits::UntrustedNodeAddress;
use servo_msg::compositor_msg::ScriptListener; use servo_msg::compositor_msg::ScriptListener;
use servo_msg::constellation_msg::ConstellationChan; use servo_msg::constellation_msg::ConstellationChan;
use servo_util::smallvec::{SmallVec1, SmallVec}; use servo_util::smallvec::{SmallVec1, SmallVec};
use servo_util::str::LengthOrPercentageOrAuto; use servo_util::str::{LengthOrPercentageOrAuto, SimpleColor};
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::collections::HashMap; use std::collections::HashMap;
use std::comm::{Receiver, Sender}; use std::comm::{Receiver, Sender};
@ -214,6 +214,7 @@ no_jsmanaged_fields!(LayoutChan)
no_jsmanaged_fields!(WindowProxyHandler) no_jsmanaged_fields!(WindowProxyHandler)
no_jsmanaged_fields!(UntrustedNodeAddress) no_jsmanaged_fields!(UntrustedNodeAddress)
no_jsmanaged_fields!(LengthOrPercentageOrAuto) no_jsmanaged_fields!(LengthOrPercentageOrAuto)
no_jsmanaged_fields!(SimpleColor)
impl<'a> JSTraceable for &'a str { impl<'a> JSTraceable for &'a str {
#[inline] #[inline]

View file

@ -16,9 +16,10 @@ use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods; use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods;
use dom::bindings::codegen::Bindings::NamedNodeMapBinding::NamedNodeMapMethods; use dom::bindings::codegen::Bindings::NamedNodeMapBinding::NamedNodeMapMethods;
use dom::bindings::codegen::InheritTypes::{ElementCast, ElementDerived, EventTargetCast}; use dom::bindings::codegen::InheritTypes::{ElementCast, ElementDerived, EventTargetCast};
use dom::bindings::codegen::InheritTypes::{HTMLInputElementCast, HTMLInputElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLBodyElementDerived, HTMLInputElementCast};
use dom::bindings::codegen::InheritTypes::{HTMLTableElementCast, HTMLTableElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLInputElementDerived, HTMLTableElementCast};
use dom::bindings::codegen::InheritTypes::{HTMLTableCellElementDerived, NodeCast}; 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::{MutNullableJS, JS, JSRef, Temporary, TemporaryPushable};
use dom::bindings::js::{OptionalRootable, Root}; use dom::bindings::js::{OptionalRootable, Root};
use dom::bindings::utils::{Reflectable, Reflector}; use dom::bindings::utils::{Reflectable, Reflector};
@ -31,6 +32,7 @@ use dom::document::{Document, DocumentHelpers, LayoutDocumentHelpers};
use dom::domtokenlist::DOMTokenList; use dom::domtokenlist::DOMTokenList;
use dom::event::Event; use dom::event::Event;
use dom::eventtarget::{EventTarget, NodeTargetTypeId, EventTargetHelpers}; use dom::eventtarget::{EventTarget, NodeTargetTypeId, EventTargetHelpers};
use dom::htmlbodyelement::{HTMLBodyElement, HTMLBodyElementHelpers};
use dom::htmlcollection::HTMLCollection; use dom::htmlcollection::HTMLCollection;
use dom::htmlinputelement::{HTMLInputElement, RawLayoutHTMLInputElementHelpers}; use dom::htmlinputelement::{HTMLInputElement, RawLayoutHTMLInputElementHelpers};
use dom::htmlserializer::serialize; use dom::htmlserializer::serialize;
@ -42,12 +44,11 @@ use dom::node::{window_from_node};
use dom::nodelist::NodeList; use dom::nodelist::NodeList;
use dom::virtualmethods::{VirtualMethods, vtable_for}; use dom::virtualmethods::{VirtualMethods, vtable_for};
use devtools_traits::AttrInfo; use devtools_traits::AttrInfo;
use style::{BorderUnsignedIntegerAttribute, IntegerAttribute, LengthAttribute}; use style::{mod, BgColorSimpleColorAttribute, BorderUnsignedIntegerAttribute, IntegerAttribute};
use style::{SizeIntegerAttribute, UnsignedIntegerAttribute, WidthLengthAttribute}; use style::{LengthAttribute, SimpleColorAttribute, SizeIntegerAttribute, UnsignedIntegerAttribute};
use style::{matches, parse_selector_list_from_str}; use style::{WidthLengthAttribute, matches, parse_selector_list_from_str};
use style;
use servo_util::namespace; use servo_util::namespace;
use servo_util::str::{DOMString, LengthOrPercentageOrAuto}; use servo_util::str::{DOMString, LengthOrPercentageOrAuto, SimpleColor};
use std::ascii::AsciiExt; use std::ascii::AsciiExt;
use std::cell::{Ref, RefMut}; use std::cell::{Ref, RefMut};
@ -207,6 +208,8 @@ pub trait RawLayoutElementHelpers {
unsafe fn get_checked_state_for_layout(&self) -> bool; unsafe fn get_checked_state_for_layout(&self) -> bool;
unsafe fn get_unsigned_integer_attribute_for_layout(&self, attribute: UnsignedIntegerAttribute) unsafe fn get_unsigned_integer_attribute_for_layout(&self, attribute: UnsignedIntegerAttribute)
-> Option<u32>; -> Option<u32>;
unsafe fn get_simple_color_attribute_for_layout(&self, attribute: SimpleColorAttribute)
-> Option<SimpleColor>;
fn local_name<'a>(&'a self) -> &'a Atom; fn local_name<'a>(&'a self) -> &'a Atom;
fn namespace<'a>(&'a self) -> &'a Namespace; fn namespace<'a>(&'a self) -> &'a Namespace;
fn style_attribute<'a>(&'a self) -> &'a DOMRefCell<Option<style::PropertyDeclarationBlock>>; 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 // Getters used in components/layout/wrapper.rs
fn local_name<'a>(&'a self) -> &'a Atom { fn local_name<'a>(&'a self) -> &'a Atom {

View file

@ -2,11 +2,9 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::attr::Attr; use dom::attr::{Attr, AttrHelpers};
use dom::attr::AttrHelpers;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::HTMLBodyElementBinding; use dom::bindings::codegen::Bindings::HTMLBodyElementBinding::{mod, HTMLBodyElementMethods};
use dom::bindings::codegen::Bindings::HTMLBodyElementBinding::HTMLBodyElementMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::InheritTypes::EventTargetCast; use dom::bindings::codegen::InheritTypes::EventTargetCast;
use dom::bindings::codegen::InheritTypes::{HTMLBodyElementDerived, HTMLElementCast}; 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::node::{Node, ElementNodeTypeId, window_from_node};
use dom::virtualmethods::VirtualMethods; use dom::virtualmethods::VirtualMethods;
use servo_util::str::DOMString; use servo_util::str::{mod, DOMString, SimpleColor};
use std::cell::Cell;
#[dom_struct] #[dom_struct]
pub struct HTMLBodyElement { pub struct HTMLBodyElement {
htmlelement: HTMLElement htmlelement: HTMLElement,
background_color: Cell<Option<SimpleColor>>,
} }
impl HTMLBodyElementDerived for EventTarget { impl HTMLBodyElementDerived for EventTarget {
@ -33,14 +33,20 @@ impl HTMLBodyElementDerived for EventTarget {
} }
impl HTMLBodyElement { 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 { 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)] #[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); let element = HTMLBodyElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLBodyElementBinding::Wrap) 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> { impl<'a> VirtualMethods for JSRef<'a, HTMLBodyElement> {
fn super_type<'a>(&'a self) -> Option<&'a VirtualMethods> { fn super_type<'a>(&'a self) -> Option<&'a VirtualMethods> {
let element: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self); let element: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
@ -91,6 +107,25 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLBodyElement> {
name.slice_from(2), name.slice_from(2),
attr.value().as_slice().to_string()); 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),
_ => {}
}
} }
} }

View file

@ -14,13 +14,13 @@ use dom::htmlelement::HTMLElement;
use dom::node::ElementNodeTypeId; use dom::node::ElementNodeTypeId;
use dom::virtualmethods::VirtualMethods; use dom::virtualmethods::VirtualMethods;
use servo_util::str::{AutoLpa, DOMString, LengthOrPercentageOrAuto}; use servo_util::str::{mod, AutoLpa, DOMString, LengthOrPercentageOrAuto, SimpleColor};
use servo_util::str;
use std::cell::Cell; use std::cell::Cell;
#[dom_struct] #[dom_struct]
pub struct HTMLTableCellElement { pub struct HTMLTableCellElement {
htmlelement: HTMLElement, htmlelement: HTMLElement,
background_color: Cell<Option<SimpleColor>>,
border: Cell<Option<u32>>, border: Cell<Option<u32>>,
width: Cell<LengthOrPercentageOrAuto>, width: Cell<LengthOrPercentageOrAuto>,
} }
@ -43,6 +43,7 @@ impl HTMLTableCellElement {
-> HTMLTableCellElement { -> HTMLTableCellElement {
HTMLTableCellElement { HTMLTableCellElement {
htmlelement: HTMLElement::new_inherited(type_id, tag_name, prefix, document), htmlelement: HTMLElement::new_inherited(type_id, tag_name, prefix, document),
background_color: Cell::new(None),
border: Cell::new(None), border: Cell::new(None),
width: Cell::new(AutoLpa), width: Cell::new(AutoLpa),
} }
@ -55,11 +56,16 @@ impl HTMLTableCellElement {
} }
pub trait HTMLTableCellElementHelpers { pub trait HTMLTableCellElementHelpers {
fn get_background_color(&self) -> Option<SimpleColor>;
fn get_border(&self) -> Option<u32>; fn get_border(&self) -> Option<u32>;
fn get_width(&self) -> LengthOrPercentageOrAuto; fn get_width(&self) -> LengthOrPercentageOrAuto;
} }
impl HTMLTableCellElementHelpers for HTMLTableCellElement { impl HTMLTableCellElementHelpers for HTMLTableCellElement {
fn get_background_color(&self) -> Option<SimpleColor> {
self.background_color.get()
}
fn get_border(&self) -> Option<u32> { fn get_border(&self) -> Option<u32> {
self.border.get() self.border.get()
} }
@ -82,6 +88,9 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLTableCellElement> {
} }
match attr.local_name() { match attr.local_name() {
&atom!("bgcolor") => {
self.background_color.set(str::parse_legacy_color(attr.value().as_slice()).ok())
}
&atom!("border") => { &atom!("border") => {
// According to HTML5 § 14.3.9, invalid values map to 1px. // According to HTML5 § 14.3.9, invalid values map to 1px.
self.border.set(Some(str::parse_unsigned_integer(attr.value() 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() { match attr.local_name() {
&atom!("bgcolor") => self.background_color.set(None),
&atom!("border") => self.border.set(None), &atom!("border") => self.border.set(None),
&atom!("width") => self.width.set(AutoLpa), &atom!("width") => self.width.set(AutoLpa),
_ => () _ => ()

View file

@ -18,12 +18,13 @@ use dom::htmltablecaptionelement::HTMLTableCaptionElement;
use dom::node::{Node, NodeHelpers, ElementNodeTypeId}; use dom::node::{Node, NodeHelpers, ElementNodeTypeId};
use dom::virtualmethods::VirtualMethods; 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; use std::cell::Cell;
#[dom_struct] #[dom_struct]
pub struct HTMLTableElement { pub struct HTMLTableElement {
htmlelement: HTMLElement, htmlelement: HTMLElement,
background_color: Cell<Option<SimpleColor>>,
border: Cell<Option<u32>>, border: Cell<Option<u32>>,
width: Cell<LengthOrPercentageOrAuto>, width: Cell<LengthOrPercentageOrAuto>,
} }
@ -42,6 +43,7 @@ impl HTMLTableElement {
localName, localName,
prefix, prefix,
document), document),
background_color: Cell::new(None),
border: Cell::new(None), border: Cell::new(None),
width: Cell::new(AutoLpa), width: Cell::new(AutoLpa),
} }
@ -93,11 +95,16 @@ impl<'a> HTMLTableElementMethods for JSRef<'a, HTMLTableElement> {
} }
pub trait HTMLTableElementHelpers { pub trait HTMLTableElementHelpers {
fn get_background_color(&self) -> Option<SimpleColor>;
fn get_border(&self) -> Option<u32>; fn get_border(&self) -> Option<u32>;
fn get_width(&self) -> LengthOrPercentageOrAuto; fn get_width(&self) -> LengthOrPercentageOrAuto;
} }
impl HTMLTableElementHelpers for HTMLTableElement { impl HTMLTableElementHelpers for HTMLTableElement {
fn get_background_color(&self) -> Option<SimpleColor> {
self.background_color.get()
}
fn get_border(&self) -> Option<u32> { fn get_border(&self) -> Option<u32> {
self.border.get() self.border.get()
} }
@ -119,6 +126,9 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLTableElement> {
} }
match attr.local_name() { match attr.local_name() {
&atom!("bgcolor") => {
self.background_color.set(str::parse_legacy_color(attr.value().as_slice()).ok())
}
&atom!("border") => { &atom!("border") => {
// According to HTML5 § 14.3.9, invalid values map to 1px. // According to HTML5 § 14.3.9, invalid values map to 1px.
self.border.set(Some(str::parse_unsigned_integer(attr.value() 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() { match attr.local_name() {
&atom!("bgcolor") => self.background_color.set(None),
&atom!("border") => self.border.set(None), &atom!("border") => self.border.set(None),
_ => () _ => ()
} }

View file

@ -121,7 +121,7 @@ dependencies = [
[[package]] [[package]]
name = "cssparser" name = "cssparser"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/servo/rust-cssparser#cbbfd66f794bd019bbdeaefc88b29eff455b62e5" source = "git+https://github.com/servo/rust-cssparser#3f98f1308b769b5d61efc6c133ac520df2b074ac"
dependencies = [ dependencies = [
"encoding 0.2.0 (git+https://github.com/lifthrasiir/rust-encoding)", "encoding 0.2.0 (git+https://github.com/lifthrasiir/rust-encoding)",
] ]
@ -672,6 +672,7 @@ dependencies = [
name = "util" name = "util"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"cssparser 0.1.0 (git+https://github.com/servo/rust-cssparser)",
"geom 0.1.0 (git+https://github.com/servo/rust-geom)", "geom 0.1.0 (git+https://github.com/servo/rust-geom)",
"layers 0.1.0 (git+https://github.com/servo/rust-layers)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)",
"string_cache 0.0.0 (git+https://github.com/servo/string-cache)", "string_cache 0.0.0 (git+https://github.com/servo/string-cache)",

View file

@ -6,11 +6,12 @@
//! `<input size>`, and so forth. //! `<input size>`, and so forth.
use node::{TElement, TElementAttributes, TNode}; use node::{TElement, TElementAttributes, TNode};
use properties::{BorderBottomWidthDeclaration, BorderLeftWidthDeclaration}; use properties::{BackgroundColorDeclaration, BorderBottomWidthDeclaration};
use properties::{BorderRightWidthDeclaration, BorderTopWidthDeclaration, SpecifiedValue}; use properties::{BorderLeftWidthDeclaration, BorderRightWidthDeclaration};
use properties::{WidthDeclaration, specified}; use properties::{BorderTopWidthDeclaration, SpecifiedValue, WidthDeclaration, specified};
use selector_matching::{DeclarationBlock, Stylist}; use selector_matching::{DeclarationBlock, Stylist};
use cssparser::{RGBA, RGBAColor};
use servo_util::geometry::Au; use servo_util::geometry::Au;
use servo_util::smallvec::VecLike; use servo_util::smallvec::VecLike;
use servo_util::str::{AutoLpa, LengthLpa, PercentageLpa}; use servo_util::str::{AutoLpa, LengthLpa, PercentageLpa};
@ -33,11 +34,22 @@ pub enum UnsignedIntegerAttribute {
BorderUnsignedIntegerAttribute, 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. /// Extension methods for `Stylist` that cause rules to be synthesized for legacy attributes.
pub trait PresentationalHintSynthesis { pub trait PresentationalHintSynthesis {
/// Synthesizes rules from various HTML attributes (mostly legacy junk from HTML4) that confer /// 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 /// *presentational hints* as defined in the HTML5 specification. This handles stuff like
/// `<body bgcolor>`, `<input size>`, `<td width>`, and so forth. /// `<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>( fn synthesize_presentational_hints_for_legacy_attributes<'a,E,N,V>(
&self, &self,
node: &N, node: &N,
@ -47,6 +59,18 @@ pub trait PresentationalHintSynthesis {
TElementAttributes, TElementAttributes,
N: TNode<'a,E>, N: TNode<'a,E>,
V: VecLike<DeclarationBlock>; 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. /// Synthesizes rules for the legacy `border` attribute.
fn synthesize_presentational_hint_for_legacy_border_attribute<'a,E,V>( fn synthesize_presentational_hint_for_legacy_border_attribute<'a,E,V>(
&self, &self,
@ -87,17 +111,31 @@ impl PresentationalHintSynthesis for Stylist {
*shareable = false *shareable = false
} }
} }
self.synthesize_presentational_hint_for_legacy_background_color_attribute(
element,
matching_rules_list,
shareable);
self.synthesize_presentational_hint_for_legacy_border_attribute( self.synthesize_presentational_hint_for_legacy_border_attribute(
element, element,
matching_rules_list, matching_rules_list,
shareable); shareable);
} }
name if *name == atom!("table") => { 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( self.synthesize_presentational_hint_for_legacy_border_attribute(
element, element,
matching_rules_list, matching_rules_list,
shareable); 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") => { name if *name == atom!("input") => {
match element.get_integer_attribute(SizeIntegerAttribute) { match element.get_integer_attribute(SizeIntegerAttribute) {
Some(value) if value != 0 => { 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>( fn synthesize_presentational_hint_for_legacy_border_attribute<'a,E,V>(
&self, &self,
element: E, element: E,

View file

@ -54,8 +54,9 @@ pub use selectors::{PseudoElement, Before, After, SelectorList, parse_selector_l
pub use selectors::{AttrSelector, NamespaceConstraint, SpecificNamespace, AnyNamespace}; pub use selectors::{AttrSelector, NamespaceConstraint, SpecificNamespace, AnyNamespace};
pub use selectors::{SimpleSelector, LocalNameSelector}; pub use selectors::{SimpleSelector, LocalNameSelector};
pub use cssparser::{Color, RGBA}; pub use cssparser::{Color, RGBA};
pub use legacy::{BorderUnsignedIntegerAttribute, IntegerAttribute, LengthAttribute}; pub use legacy::{BgColorSimpleColorAttribute, BorderUnsignedIntegerAttribute, IntegerAttribute};
pub use legacy::{SizeIntegerAttribute, UnsignedIntegerAttribute, WidthLengthAttribute}; pub use legacy::{LengthAttribute, SimpleColorAttribute, SizeIntegerAttribute};
pub use legacy::{UnsignedIntegerAttribute, WidthLengthAttribute};
pub use font_face::{Source, LocalSource, UrlSource_}; pub use font_face::{Source, LocalSource, UrlSource_};
mod stylesheets; mod stylesheets;

View file

@ -5,9 +5,9 @@
//! Traits that nodes must implement. Breaks the otherwise-cyclic dependency between layout and //! Traits that nodes must implement. Breaks the otherwise-cyclic dependency between layout and
//! style. //! style.
use legacy::{IntegerAttribute, LengthAttribute, UnsignedIntegerAttribute}; use legacy::{IntegerAttribute, LengthAttribute, SimpleColorAttribute, UnsignedIntegerAttribute};
use selectors::AttrSelector; use selectors::AttrSelector;
use servo_util::str::LengthOrPercentageOrAuto; use servo_util::str::{LengthOrPercentageOrAuto, SimpleColor};
use string_cache::{Atom, Namespace}; use string_cache::{Atom, Namespace};
pub trait TNode<'a, E: TElement<'a>> : Clone + Copy { 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_length_attribute(self, attribute: LengthAttribute) -> LengthOrPercentageOrAuto;
fn get_integer_attribute(self, attribute: IntegerAttribute) -> Option<i32>; fn get_integer_attribute(self, attribute: IntegerAttribute) -> Option<i32>;
fn get_unsigned_integer_attribute(self, attribute: UnsignedIntegerAttribute) -> Option<u32>; fn get_unsigned_integer_attribute(self, attribute: UnsignedIntegerAttribute) -> Option<u32>;
fn get_simple_color_attribute(self, attribute: SimpleColorAttribute) -> Option<SimpleColor>;
} }

View file

@ -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 /// 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 /// either this list or `common_style_affecting_attributes`. See the comment in
/// `synthesize_presentational_hints_for_legacy_attributes`. /// `synthesize_presentational_hints_for_legacy_attributes`.
pub fn rare_style_affecting_attributes() -> [Atom, ..1] { pub fn rare_style_affecting_attributes() -> [Atom, ..2] {
[ atom!("border") ] [ atom!("bgcolor"), atom!("border") ]
} }
/// Determines whether the given element matches the given single selector. /// Determines whether the given element matches the given single selector.

View file

@ -7,6 +7,9 @@ authors = ["The Servo Project Developers"]
name = "util" name = "util"
path = "lib.rs" path = "lib.rs"
[dependencies.cssparser]
git = "https://github.com/servo/rust-cssparser"
[dependencies.geom] [dependencies.geom]
git = "https://github.com/servo/rust-geom" git = "https://github.com/servo/rust-geom"

View file

@ -13,6 +13,7 @@ extern crate log;
extern crate alloc; extern crate alloc;
extern crate collections; extern crate collections;
extern crate cssparser;
extern crate geom; extern crate geom;
extern crate getopts; extern crate getopts;
extern crate layers; extern crate layers;

View file

@ -4,6 +4,8 @@
use geometry::Au; use geometry::Au;
use cssparser::{mod, RGBAColor};
use std::ascii::AsciiExt;
use std::from_str::FromStr; use std::from_str::FromStr;
use std::iter::Filter; use std::iter::Filter;
use std::str::{CharEq, CharSplits}; 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)] #[deriving(Clone, Eq, PartialEq, Hash, Show)]
pub struct LowercaseString { pub struct LowercaseString {

2
ports/cef/Cargo.lock generated
View file

@ -118,7 +118,7 @@ dependencies = [
[[package]] [[package]]
name = "cssparser" name = "cssparser"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/servo/rust-cssparser#cbbfd66f794bd019bbdeaefc88b29eff455b62e5" source = "git+https://github.com/servo/rust-cssparser#3f98f1308b769b5d61efc6c133ac520df2b074ac"
dependencies = [ dependencies = [
"encoding 0.2.0 (git+https://github.com/lifthrasiir/rust-encoding)", "encoding 0.2.0 (git+https://github.com/lifthrasiir/rust-encoding)",
] ]

2
ports/gonk/Cargo.lock generated
View file

@ -101,7 +101,7 @@ dependencies = [
[[package]] [[package]]
name = "cssparser" name = "cssparser"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/servo/rust-cssparser#cbbfd66f794bd019bbdeaefc88b29eff455b62e5" source = "git+https://github.com/servo/rust-cssparser#3f98f1308b769b5d61efc6c133ac520df2b074ac"
dependencies = [ dependencies = [
"encoding 0.2.0 (git+https://github.com/lifthrasiir/rust-encoding)", "encoding 0.2.0 (git+https://github.com/lifthrasiir/rust-encoding)",
] ]

View file

@ -209,4 +209,5 @@ fragment=top != ../html/acid2.html acid2_ref.html
== box_shadow_inset_parsing_a.html box_shadow_inset_parsing_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_type_a.html list_style_type_ref.html
== list_style_position_a.html list_style_position_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 == legacy_table_border_attribute_a.html legacy_table_border_attribute_ref.html

View file

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<body>
<table border=0 cellspacing=0 cellpadding=0>
<tr><td bgcolor=chucknorris width=100>&nbsp;</td></tr>
<tr><td bgcolor=ChuckNorris width=100>&nbsp;</td></tr>
<tr><td bgcolor=sick width=100>&nbsp;</td></tr>
<tr><td bgcolor=crap width=100>&nbsp;</td></tr>
<tr><td bgcolor=LuckBeALadyTonight width=100>&nbsp;</td></tr>
<tr><td bgcolor=#abc width=100>&nbsp;</td></tr>
<tr><td bgcolor=#123456 width=100>&nbsp;</td></tr>
<tr><td bgcolor=#abacab width=100>&nbsp;</td></tr>
<tr><td bgcolor=#AbaCab width=100>&nbsp;</td></tr>
<tr><td bgcolor=#ABACAB width=100>&nbsp;</td></tr>
<tr><td bgcolor=transparent width=100>&nbsp;</td></tr>
<tr><td bgcolor=gold width=100>&nbsp;</td></tr>
</table>
</body>
</html>

View file

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<body>
<table border=0 cellspacing=0 cellpadding=0>
<tr><td style="background: #c00000" width=100>&nbsp;</td></tr>
<tr><td style="background: #c00000" width=100>&nbsp;</td></tr>
<tr><td style="background: #00c000" width=100>&nbsp;</td></tr>
<tr><td style="background: #c0a000" width=100>&nbsp;</td></tr>
<tr><td style="background: #00a000" width=100>&nbsp;</td></tr>
<tr><td style="background: #aabbcc" width=100>&nbsp;</td></tr>
<tr><td style="background: #123456" width=100>&nbsp;</td></tr>
<tr><td style="background: #abacab" width=100>&nbsp;</td></tr>
<tr><td style="background: #abacab" width=100>&nbsp;</td></tr>
<tr><td style="background: #abacab" width=100>&nbsp;</td></tr>
<tr><td width=100>&nbsp;</td></tr>
<tr><td style="background: gold" width=100>&nbsp;</td></tr>
</table>
</body>
</html>