/* This Source Code Form is subject to the terms of the Mozilla Public * 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/. */ //! Legacy presentational attributes defined in the HTML5 specification: ``, //! ``, and so forth. use std::sync::Arc; use selectors::tree::{TElement, TNode}; use selectors::matching::DeclarationBlock; use node::TElementAttributes; use values::specified::CSSColor; use values::{CSSFloat, specified}; use properties::DeclaredValue::SpecifiedValue; use properties::PropertyDeclaration; use properties::longhands; use selector_matching::Stylist; use cssparser::Color; use selectors::smallvec::VecLike; use util::geometry::Au; use util::str::LengthOrPercentageOrAuto; /// Legacy presentational attributes that take a length as defined in HTML5 § 2.4.4.4. #[derive(Copy, PartialEq, Eq)] pub enum LengthAttribute { /// `` Width, } /// Legacy presentational attributes that take an integer as defined in HTML5 § 2.4.4.2. #[derive(Copy, PartialEq, Eq)] pub enum IntegerAttribute { /// `` Size, Cols, Rows, } /// Legacy presentational attributes that take a nonnegative integer as defined in HTML5 § 2.4.4.2. #[derive(Copy, PartialEq, Eq)] pub enum UnsignedIntegerAttribute { /// `` Border, /// `` ColSpan, } /// Legacy presentational attributes that take a simple color as defined in HTML5 § 2.4.6. #[derive(Copy, PartialEq, Eq)] pub enum SimpleColorAttribute { /// `` BgColor, } /// 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 /// ``, ``, ``, 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, matching_rules_list: &mut V, shareable: &mut bool) where E: TElement<'a> + TElementAttributes, N: TNode<'a,E>, V: VecLike>>; /// 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, element: E, matching_rules_list: &mut V, shareable: &mut bool) where E: TElement<'a> + TElementAttributes, V: VecLike>>; } impl PresentationalHintSynthesis for Stylist { fn synthesize_presentational_hints_for_legacy_attributes<'a,E,N,V>( &self, node: &N, matching_rules_list: &mut V, shareable: &mut bool) where E: TElement<'a> + TElementAttributes, N: TNode<'a,E>, V: VecLike>> { let element = node.as_element(); match element.get_local_name() { name if *name == atom!("td") => { match element.get_length_attribute(LengthAttribute::Width) { LengthOrPercentageOrAuto::Auto => {} LengthOrPercentageOrAuto::Percentage(percentage) => { let width_value = specified::LengthOrPercentageOrAuto::Percentage(percentage); matching_rules_list.vec_push(from_declaration( PropertyDeclaration::Width(SpecifiedValue(width_value)))); *shareable = false } LengthOrPercentageOrAuto::Length(length) => { let width_value = specified::LengthOrPercentageOrAuto::Length(specified::Length::Absolute(length)); matching_rules_list.vec_push(from_declaration( PropertyDeclaration::Width(SpecifiedValue(width_value)))); *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") || *name == atom!("tr") || *name == atom!("thead") || *name == atom!("tbody") || *name == atom!("tfoot") => { self.synthesize_presentational_hint_for_legacy_background_color_attribute( element, matching_rules_list, shareable); } name if *name == atom!("input") => { match element.get_integer_attribute(IntegerAttribute::Size) { Some(value) if value != 0 => { // Per HTML 4.01 § 17.4, this value is in characters if `type` is `text` or // `password` and in pixels otherwise. // // FIXME(pcwalton): More use of atoms, please! let value = match element.get_attr(&ns!(""), &atom!("type")) { Some("text") | Some("password") => { specified::Length::ServoCharacterWidth(specified::CharacterWidth(value)) } _ => specified::Length::Absolute(Au::from_px(value as int)), }; matching_rules_list.vec_push(from_declaration( PropertyDeclaration::Width(SpecifiedValue( specified::LengthOrPercentageOrAuto::Length(value))))); *shareable = false } Some(_) | None => {} } } name if *name == atom!("textarea") => { match element.get_integer_attribute(IntegerAttribute::Cols) { Some(value) if value != 0 => { // TODO(mttr) ServoCharacterWidth uses the size math for , but // the math for