--- a/servo/components/layout_thread/lib.rs
+++ b/servo/components/layout_thread/lib.rs
@@ -1109,16 +1109,24 @@ impl LayoutThread {
if data.document_stylesheets.iter().any(|sheet| sheet.dirty_on_viewport_size_change) {
let mut iter = node.traverse_preorder();
let mut next = iter.next();
while let Some(node) = next {
if node.needs_dirty_on_viewport_size_changed() {
// NB: The dirty bit is propagated down the tree.
unsafe { node.set_dirty(true); }
+
+ let mut current = node.parent_node();
+ while let Some(node) = current {
+ if node.has_dirty_descendants() { break; }
+ unsafe { node.set_dirty_descendants(true); }
+ current = node.parent_node();
+ }
+
next = iter.next_skipping_children();
} else {
next = iter.next();
}
}
}
}
--- a/servo/components/style/animation.rs
+++ b/servo/components/style/animation.rs
@@ -389,16 +389,17 @@ fn compute_style_for_animation_step(cont
source_order: 0,
specificity: ::std::u32::MAX,
};
let (computed, _) = properties::cascade(context.viewport_size,
&[declaration_block],
false,
Some(previous_style),
None,
+ None,
context.error_reporter.clone());
computed
}
}
}
pub fn maybe_start_animations(context: &SharedStyleContext,
new_animations_sender: &Sender<Animation>,
new file mode 100644
--- /dev/null
+++ b/servo/components/style/cascade_info.rs
@@ -0,0 +1,78 @@
+/* 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/. */
+use dom::TNode;
+use properties::{DeclaredValue, PropertyDeclaration};
+use values::HasViewportPercentage;
+
+/// A structure to collect information about the cascade.
+///
+/// This is useful to gather information about what an element is affected by,
+/// and can be used in the future to track optimisations like when a
+/// non-inherited property is explicitly inherited, in order to cut-off the
+/// traversal.
+pub struct CascadeInfo {
+ pub saw_viewport_units: bool,
+ #[cfg(debug_assertions)]
+ finished: bool,
+}
+
+impl CascadeInfo {
+ #[cfg(debug_assertions)]
+ pub fn new() -> Self {
+ CascadeInfo {
+ saw_viewport_units: false,
+ finished: false,
+ }
+ }
+
+ #[cfg(not(debug_assertions))]
+ pub fn new() -> Self {
+ CascadeInfo {
+ saw_viewport_units: false,
+ }
+ }
+
+ /// Called when a property is cascaded.
+ ///
+ /// NOTE: We can add a vast amount of information here.
+ #[inline]
+ pub fn on_cascade_property<T>(&mut self,
+ _property_declaration: &PropertyDeclaration,
+ value: &DeclaredValue<T>)
+ where T: HasViewportPercentage
+ {
+ // TODO: we can be smarter and keep a property bitfield to keep track of
+ // the last applying rule.
+ if value.has_viewport_percentage() {
+ self.saw_viewport_units = true;
+ }
+ }
+
+ #[cfg(debug_assertions)]
+ fn mark_as_finished_if_appropriate(&mut self) {
+ self.finished = true;
+ }
+
+ #[cfg(not(debug_assertions))]
+ fn mark_as_finished_if_appropriate(&mut self) {}
+
+ #[allow(unsafe_code)]
+ pub fn finish<N: TNode>(mut self, node: &N) {
+ self.mark_as_finished_if_appropriate();
+
+ if self.saw_viewport_units {
+ unsafe {
+ node.set_dirty_on_viewport_size_changed();
+ }
+ }
+ }
+}
+
+#[cfg(debug_assertions)]
+impl Drop for CascadeInfo {
+ fn drop(&mut self) {
+ debug_assert!(self.finished,
+ "Didn't use the result of CascadeInfo, if you don't need it, consider passing None");
+ }
+}
--- a/servo/components/style/custom_properties.rs
+++ b/servo/components/style/custom_properties.rs
@@ -34,16 +34,22 @@ pub struct SpecifiedValue {
first_token_type: TokenSerializationType,
last_token_type: TokenSerializationType,
/// Custom property names in var() functions.
references: HashSet<Name>,
}
+impl ::values::HasViewportPercentage for SpecifiedValue {
+ fn has_viewport_percentage(&self) -> bool {
+ panic!("has_viewport_percentage called before resolving!");
+ }
+}
+
pub struct BorrowedSpecifiedValue<'a> {
css: &'a str,
first_token_type: TokenSerializationType,
last_token_type: TokenSerializationType,
references: Option<&'a HashSet<Name>>,
}
#[derive(Clone, Debug)]
--- a/servo/components/style/lib.rs
+++ b/servo/components/style/lib.rs
@@ -69,16 +69,17 @@ extern crate style_traits;
extern crate time;
extern crate url;
extern crate util;
pub mod animation;
pub mod attr;
pub mod bezier;
pub mod cache;
+pub mod cascade_info;
pub mod context;
pub mod custom_properties;
pub mod data;
pub mod dom;
pub mod element_state;
pub mod error_reporting;
pub mod font_face;
#[cfg(feature = "gecko")] pub mod gecko_conversions;
--- a/servo/components/style/matching.rs
+++ b/servo/components/style/matching.rs
@@ -4,16 +4,17 @@
//! High-level interface to CSS selector matching.
#![allow(unsafe_code)]
use animation;
use arc_ptr_eq;
use cache::{LRUCache, SimpleHashCache};
+use cascade_info::CascadeInfo;
use context::{StyleContext, SharedStyleContext};
use data::PrivateStyleData;
use dom::{TElement, TNode, TRestyleDamage};
use properties::longhands::display::computed_value as display;
use properties::{ComputedValues, PropertyDeclaration, cascade};
use selector_impl::{ElementExt, TheSelectorImpl, PseudoElement};
use selector_matching::{DeclarationBlock, Stylist};
use selectors::bloom::BloomFilter;
@@ -438,40 +439,44 @@ trait PrivateMatchMethods: TNode {
{
let mut cacheable = true;
let shared_context = context.shared_context();
if animate_properties {
cacheable = !self.update_animations_for_cascade(shared_context,
&mut old_style) && cacheable;
}
+ let mut cascade_info = CascadeInfo::new();
let (this_style, is_cacheable) = match parent_style {
Some(ref parent_style) => {
let cache_entry = applicable_declarations_cache.find(applicable_declarations);
let cached_computed_values = match cache_entry {
Some(ref style) => Some(&**style),
None => None,
};
cascade(shared_context.viewport_size,
applicable_declarations,
shareable,
Some(&***parent_style),
cached_computed_values,
+ Some(&mut cascade_info),
shared_context.error_reporter.clone())
}
None => {
cascade(shared_context.viewport_size,
applicable_declarations,
shareable,
None,
None,
+ Some(&mut cascade_info),
shared_context.error_reporter.clone())
}
};
+ cascade_info.finish(self);
cacheable = cacheable && is_cacheable;
let mut this_style = Arc::new(this_style);
if animate_properties {
let new_animations_sender = &context.local_context().new_animations_sender;
let this_opaque = self.opaque();
@@ -492,17 +497,16 @@ trait PrivateMatchMethods: TNode {
&**style,
&mut this_style,
&shared_context.timer);
}
cacheable = cacheable && !animations_started
}
-
// Cache the resolved style if it was cacheable.
if cacheable {
applicable_declarations_cache.insert(applicable_declarations.to_vec(),
this_style.clone());
}
this_style
}
--- a/servo/components/style/properties/helpers.mako.rs
+++ b/servo/components/style/properties/helpers.mako.rs
@@ -162,16 +162,17 @@
%>
pub mod ${property.ident} {
#![allow(unused_imports)]
% if not property.derived_from:
use cssparser::Parser;
use parser::{ParserContext, ParserContextExtraData};
use properties::{CSSWideKeyword, DeclaredValue, Shorthand};
% endif
+ use cascade_info::CascadeInfo;
use error_reporting::ParseErrorReporter;
use properties::longhands;
use properties::property_bit_field::PropertyBitField;
use properties::{ComputedValues, PropertyDeclaration};
use properties::style_structs;
use std::boxed::Box as StdBox;
use std::collections::HashMap;
use std::sync::Arc;
@@ -180,32 +181,39 @@
use string_cache::Atom;
${caller.body()}
#[allow(unused_variables)]
pub fn cascade_property(declaration: &PropertyDeclaration,
inherited_style: &ComputedValues,
context: &mut computed::Context,
seen: &mut PropertyBitField,
cacheable: &mut bool,
+ cascade_info: &mut Option<<&mut CascadeInfo>,
error_reporter: &mut StdBox<ParseErrorReporter + Send>) {
let declared_value = match *declaration {
PropertyDeclaration::${property.camel_case}(ref declared_value) => {
declared_value
}
_ => panic!("entered the wrong cascade_property() implementation"),
};
% if not property.derived_from:
if seen.get_${property.ident}() {
return
}
seen.set_${property.ident}();
{
let custom_props = context.style().custom_properties();
::properties::substitute_variables_${property.ident}(
- declared_value, &custom_props, |value| match *value {
+ declared_value, &custom_props,
+ |value| {
+ if let Some(ref mut cascade_info) = *cascade_info {
+ cascade_info.on_cascade_property(&declaration,
+ &value);
+ }
+ match *value {
DeclaredValue::Value(ref specified_value) => {
let computed = specified_value.to_computed_value(context);
context.mutate_style().mutate_${data.current_style_struct.name_lower}()
.set_${property.ident}(computed);
}
DeclaredValue::WithVariables { .. } => unreachable!(),
DeclaredValue::Initial => {
// We assume that it's faster to use copy_*_from rather than
@@ -221,18 +229,18 @@
//
// FIXME: is it still?
*cacheable = false;
let inherited_struct =
inherited_style.get_${data.current_style_struct.name_lower}();
context.mutate_style().mutate_${data.current_style_struct.name_lower}()
.copy_${property.ident}_from(inherited_struct);
}
- }, error_reporter
- );
+ }
+ }, error_reporter);
}
% if property.custom_cascade:
cascade_property_custom(declaration,
inherited_style,
context,
seen,
cacheable,
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -29,16 +29,17 @@ use computed_values;
#[cfg(feature = "servo")] use logical_geometry::{LogicalMargin, PhysicalSide};
use logical_geometry::WritingMode;
use parser::{ParserContext, ParserContextExtraData, log_css_error};
use selectors::matching::DeclarationBlock;
use stylesheets::Origin;
use values::LocalToCss;
use values::HasViewportPercentage;
use values::computed::{self, ToComputedValue};
+use cascade_info::CascadeInfo;
#[cfg(feature = "servo")] use values::specified::BorderStyle;
use self::property_bit_field::PropertyBitField;
<%!
from data import Method, Keyword, to_rust_ident
%>
@@ -768,16 +769,29 @@ pub enum DeclaredValue<T> {
},
Initial,
Inherit,
// There is no Unset variant here.
// The 'unset' keyword is represented as either Initial or Inherit,
// depending on whether the property is inherited.
}
+impl<T: HasViewportPercentage> HasViewportPercentage for DeclaredValue<T> {
+ fn has_viewport_percentage(&self) -> bool {
+ match *self {
+ DeclaredValue::Value(ref v)
+ => v.has_viewport_percentage(),
+ DeclaredValue::WithVariables { .. }
+ => panic!("DeclaredValue::has_viewport_percentage without resolving variables!"),
+ DeclaredValue::Initial |
+ DeclaredValue::Inherit => false,
+ }
+ }
+}
+
impl<T: ToCss> ToCss for DeclaredValue<T> {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
DeclaredValue::Value(ref inner) => inner.to_css(dest),
DeclaredValue::WithVariables { ref css, from_shorthand: None, .. } => {
dest.write_str(css)
}
// https://drafts.csswg.org/css-variables/#variables-in-shorthands
@@ -792,16 +806,30 @@ impl<T: ToCss> ToCss for DeclaredValue<T
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum PropertyDeclaration {
% for property in data.longhands:
${property.camel_case}(DeclaredValue<longhands::${property.ident}::SpecifiedValue>),
% endfor
Custom(::custom_properties::Name, DeclaredValue<::custom_properties::SpecifiedValue>),
}
+impl HasViewportPercentage for PropertyDeclaration {
+ fn has_viewport_percentage(&self) -> bool {
+ match *self {
+ % for property in data.longhands:
+ PropertyDeclaration::${property.camel_case}(ref val) => {
+ val.has_viewport_percentage()
+ },
+ % endfor
+ PropertyDeclaration::Custom(_, ref val) => {
+ val.has_viewport_percentage()
+ }
+ }
+ }
+}
#[derive(Eq, PartialEq, Copy, Clone)]
pub enum PropertyDeclarationParseResult {
UnknownProperty,
ExperimentalProperty,
InvalidValue,
ValidOrIgnoredDeclaration,
}
@@ -849,29 +877,16 @@ impl ToCss for PropertyDeclaration {
PropertyDeclaration::Custom(_, ref value) => value.to_css(dest),
% if any(property.derived_from for property in data.longhands):
_ => Err(fmt::Error),
% endif
}
}
}
-impl HasViewportPercentage for PropertyDeclaration {
- fn has_viewport_percentage(&self) -> bool {
- match *self {
- % for property in data.longhands:
- PropertyDeclaration::${property.camel_case}(DeclaredValue::Value(ref val)) => {
- val.has_viewport_percentage()
- },
- % endfor
- _ => false
- }
- }
-}
-
impl PropertyDeclaration {
pub fn name(&self) -> PropertyDeclarationName {
match *self {
% for property in data.longhands:
PropertyDeclaration::${property.camel_case}(..) =>
% if not property.derived_from:
PropertyDeclarationName::Longhand("${property.name}"),
% else:
@@ -1617,16 +1632,17 @@ mod lazy_static_module {
#[allow(unused_mut, unused_imports)]
fn cascade_with_cached_declarations(
viewport_size: Size2D<Au>,
applicable_declarations: &[DeclarationBlock<Vec<PropertyDeclaration>>],
shareable: bool,
parent_style: &ComputedValues,
cached_style: &ComputedValues,
custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
+ mut cascade_info: Option<<&mut CascadeInfo>,
mut error_reporter: StdBox<ParseErrorReporter + Send>)
-> ComputedValues {
let mut context = computed::Context {
is_root_element: false,
viewport_size: viewport_size,
inherited_style: parent_style,
style: ComputedValues::new(
custom_properties,
@@ -1659,17 +1675,22 @@ fn cascade_with_cached_declarations(
% if style_struct.inherited:
if seen.get_${property.ident}() {
continue
}
seen.set_${property.ident}();
let custom_props = context.style().custom_properties();
substitute_variables_${property.ident}(
declared_value, &custom_props,
- |value| match *value {
+ |value| {
+ if let Some(ref mut cascade_info) = cascade_info {
+ cascade_info.on_cascade_property(&declaration,
+ &value);
+ }
+ match *value {
DeclaredValue::Value(ref specified_value)
=> {
let computed = specified_value.to_computed_value(&context);
context.mutate_style().mutate_${style_struct.name_lower}()
.set_${property.ident}(computed);
},
DeclaredValue::Initial
=> {
@@ -1683,18 +1704,18 @@ fn cascade_with_cached_declarations(
// matter.
//
// FIXME: is it still?
let inherited_struct = parent_style.get_${style_struct.ident}();
context.mutate_style().mutate_${style_struct.name_lower}()
.copy_${property.ident}_from(inherited_struct);
}
DeclaredValue::WithVariables { .. } => unreachable!()
- }, &mut error_reporter
- );
+ }
+ }, &mut error_reporter);
% endif
% if property.name in data.derived_longhands:
% for derived in data.derived_longhands[property.name]:
longhands::${derived.ident}
::derive_from_${property.ident}(&mut context);
% endfor
% endif
@@ -1723,16 +1744,17 @@ fn cascade_with_cached_declarations(
}
pub type CascadePropertyFn =
extern "Rust" fn(declaration: &PropertyDeclaration,
inherited_style: &ComputedValues,
context: &mut computed::Context,
seen: &mut PropertyBitField,
cacheable: &mut bool,
+ cascade_info: &mut Option<<&mut CascadeInfo>,
error_reporter: &mut StdBox<ParseErrorReporter + Send>);
#[cfg(feature = "servo")]
static CASCADE_PROPERTY: [CascadePropertyFn; ${len(data.longhands)}] = [
% for property in data.longhands:
longhands::${property.ident}::cascade_property,
% endfor
];
@@ -1755,16 +1777,17 @@ static CASCADE_PROPERTY: [CascadePropert
/// this is ignored.
///
/// Returns the computed values and a boolean indicating whether the result is cacheable.
pub fn cascade(viewport_size: Size2D<Au>,
applicable_declarations: &[DeclarationBlock<Vec<PropertyDeclaration>>],
shareable: bool,
parent_style: Option<<&ComputedValues>,
cached_style: Option<<&ComputedValues>,
+ mut cascade_info: Option<<&mut CascadeInfo>,
mut error_reporter: StdBox<ParseErrorReporter + Send>)
-> (ComputedValues, bool) {
let initial_values = ComputedValues::initial_values();
let (is_root_element, inherited_style) = match parent_style {
Some(parent_style) => (false, parent_style),
None => (true, initial_values),
};
@@ -1789,16 +1812,17 @@ pub fn cascade(viewport_size: Size2D<Au>
if let (Some(cached_style), Some(parent_style)) = (cached_style, parent_style) {
let style = cascade_with_cached_declarations(viewport_size,
applicable_declarations,
shareable,
parent_style,
cached_style,
custom_properties,
+ cascade_info,
error_reporter);
return (style, false)
}
let mut context = computed::Context {
is_root_element: is_root_element,
viewport_size: viewport_size,
inherited_style: inherited_style,
@@ -1858,16 +1882,17 @@ pub fn cascade(viewport_size: Size2D<Au>
continue
}
let discriminant = declaration.discriminant_value();
(cascade_property[discriminant])(declaration,
inherited_style,
&mut context,
&mut seen,
&mut cacheable,
+ &mut cascade_info,
&mut error_reporter);
}
}
% endfor
});
let mut style = context.style;
--- a/servo/components/style/selector_matching.rs
+++ b/servo/components/style/selector_matching.rs
@@ -225,30 +225,32 @@ impl Stylist {
-> Option<Arc<ComputedValues>> {
debug_assert!(TheSelectorImpl::pseudo_element_cascade_type(pseudo).is_precomputed());
if let Some(declarations) = self.precomputed_pseudo_element_decls.get(pseudo) {
let (computed, _) =
properties::cascade(self.device.au_viewport_size(),
&declarations, false,
parent.map(|p| &**p),
None,
+ None,
Box::new(StdoutErrorReporter));
Some(Arc::new(computed))
} else {
parent.map(|p| p.clone())
}
}
pub fn lazily_compute_pseudo_element_style<E>(&self,
element: &E,
pseudo: &PseudoElement,
parent: &Arc<ComputedValues>)
-> Option<Arc<ComputedValues>>
- where E: Element<Impl=TheSelectorImpl> +
- PresentationalHintsSynthetizer {
+ where E: Element<Impl=TheSelectorImpl> +
+ PresentationalHintsSynthetizer
+ {
debug_assert!(TheSelectorImpl::pseudo_element_cascade_type(pseudo).is_lazy());
if self.pseudos_map.get(pseudo).is_none() {
return None;
}
let mut declarations = vec![];
// NB: This being cached could be worth it, maybe allow an optional
@@ -257,18 +259,20 @@ impl Stylist {
None,
None,
Some(pseudo),
&mut declarations);
let (computed, _) =
properties::cascade(self.device.au_viewport_size(),
&declarations, false,
- Some(&**parent), None,
+ Some(&**parent), None, None,
Box::new(StdoutErrorReporter));
+
+
Some(Arc::new(computed))
}
pub fn set_device(&mut self, mut device: Device, stylesheets: &[Arc<Stylesheet>]) {
let cascaded_rule = stylesheets.iter()
.flat_map(|s| s.effective_rules(&self.device).viewport())
.cascade();
--- a/servo/components/style/stylesheets.rs
+++ b/servo/components/style/stylesheets.rs
@@ -164,17 +164,18 @@ impl Stylesheet {
}
}
}
Stylesheet {
origin: origin,
rules: rules,
media: None,
- dirty_on_viewport_size_change: input.seen_viewport_percentages(),
+ dirty_on_viewport_size_change:
+ input.seen_viewport_percentages(),
}
}
/// Set the MediaQueryList associated with the style-sheet.
pub fn set_media(&mut self, media: Option<MediaQueryList>) {
self.media = media;
}
--- a/servo/components/style/traversal.rs
+++ b/servo/components/style/traversal.rs
@@ -365,28 +365,14 @@ pub fn recalc_style_at<'a, N, C>(context
// Before running the children, we need to insert our nodes into the bloom
// filter.
debug!("[{}] + {:X}", tid(), unsafe_layout_node.0);
node.insert_into_bloom_filter(&mut *bf);
// NB: flow construction updates the bloom filter on the way up.
put_thread_local_bloom_filter(bf, &unsafe_layout_node, context.shared_context());
- // Mark the node as DIRTY_ON_VIEWPORT_SIZE_CHANGE is it uses viewport
- // percentage units.
- if !node.needs_dirty_on_viewport_size_changed() {
- if let Some(element) = node.as_element() {
- if let Some(ref property_declaration_block) = *element.style_attribute() {
- if property_declaration_block.declarations().any(|d| d.0.has_viewport_percentage()) {
- unsafe {
- node.set_dirty_on_viewport_size_changed();
- }
- }
- }
- }
- }
-
if nonincremental_layout {
RestyleResult::Continue
} else {
restyle_result
}
}
--- a/servo/components/style/values/specified/mod.rs
+++ b/servo/components/style/values/specified/mod.rs
@@ -192,28 +192,29 @@ pub enum Length {
Calc(CalcLengthOrPercentage),
}
impl HasViewportPercentage for Length {
fn has_viewport_percentage(&self) -> bool {
match *self {
Length::ViewportPercentage(_) => true,
+ Length::Calc(ref calc) => calc.has_viewport_percentage(),
_ => false
}
}
}
impl ToCss for Length {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
Length::Absolute(length) => write!(dest, "{}px", length.to_f32_px()),
Length::FontRelative(length) => length.to_css(dest),
Length::ViewportPercentage(length) => length.to_css(dest),
- Length::Calc(calc) => calc.to_css(dest),
+ Length::Calc(ref calc) => calc.to_css(dest),
Length::ServoCharacterWidth(_)
=> panic!("internal CSS values should never be serialized"),
}
}
}
impl Mul<CSSFloat> for Length {
type Output = Length;
@@ -462,16 +463,17 @@ pub struct CalcLengthOrPercentage {
pub vmin: Option<ViewportPercentageLength>,
pub vmax: Option<ViewportPercentageLength>,
pub em: Option<FontRelativeLength>,
pub ex: Option<FontRelativeLength>,
pub ch: Option<FontRelativeLength>,
pub rem: Option<FontRelativeLength>,
pub percentage: Option<Percentage>,
}
+
impl CalcLengthOrPercentage {
fn parse_sum(input: &mut Parser, expected_unit: CalcUnit) -> Result<CalcSumNode, ()> {
let mut products = Vec::new();
products.push(try!(CalcLengthOrPercentage::parse_product(input, expected_unit)));
while let Ok(token) = input.next() {
match token {
Token::Delim('+') => {
@@ -746,16 +748,23 @@ impl CalcLengthOrPercentage {
match (angle, number) {
(Some(angle), None) => Ok(Angle(angle)),
(None, Some(value)) if value == 0. => Ok(Angle(0.)),
_ => Err(())
}
}
}
+impl HasViewportPercentage for CalcLengthOrPercentage {
+ fn has_viewport_percentage(&self) -> bool {
+ self.vw.is_some() || self.vh.is_some() ||
+ self.vmin.is_some() || self.vmax.is_some()
+ }
+}
+
impl ToCss for CalcLengthOrPercentage {
#[allow(unused_assignments)]
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
macro_rules! count {
( $( $val:ident ),* ) => {
{
let mut count = 0;
$(
@@ -818,17 +827,18 @@ pub enum LengthOrPercentage {
Length(Length),
Percentage(Percentage),
Calc(CalcLengthOrPercentage),
}
impl HasViewportPercentage for LengthOrPercentage {
fn has_viewport_percentage(&self) -> bool {
match *self {
- LengthOrPercentage::Length(length) => length.has_viewport_percentage(),
+ LengthOrPercentage::Length(ref length) => length.has_viewport_percentage(),
+ LengthOrPercentage::Calc(ref calc) => calc.has_viewport_percentage(),
_ => false
}
}
}
impl ToCss for LengthOrPercentage {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
@@ -877,17 +887,18 @@ pub enum LengthOrPercentageOrAuto {
Percentage(Percentage),
Auto,
Calc(CalcLengthOrPercentage),
}
impl HasViewportPercentage for LengthOrPercentageOrAuto {
fn has_viewport_percentage(&self) -> bool {
match *self {
- LengthOrPercentageOrAuto::Length(length) => length.has_viewport_percentage(),
+ LengthOrPercentageOrAuto::Length(ref length) => length.has_viewport_percentage(),
+ LengthOrPercentageOrAuto::Calc(ref calc) => calc.has_viewport_percentage(),
_ => false
}
}
}
impl ToCss for LengthOrPercentageOrAuto {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
@@ -936,28 +947,29 @@ pub enum LengthOrPercentageOrNone {
Percentage(Percentage),
Calc(CalcLengthOrPercentage),
None,
}
impl HasViewportPercentage for LengthOrPercentageOrNone {
fn has_viewport_percentage(&self) -> bool {
match *self {
- LengthOrPercentageOrNone::Length(length) => length.has_viewport_percentage(),
+ LengthOrPercentageOrNone::Length(ref length) => length.has_viewport_percentage(),
+ LengthOrPercentageOrNone::Calc(ref calc) => calc.has_viewport_percentage(),
_ => false
}
}
}
impl ToCss for LengthOrPercentageOrNone {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
- LengthOrPercentageOrNone::Length(length) => length.to_css(dest),
- LengthOrPercentageOrNone::Percentage(percentage) => percentage.to_css(dest),
- LengthOrPercentageOrNone::Calc(calc) => calc.to_css(dest),
+ LengthOrPercentageOrNone::Length(ref length) => length.to_css(dest),
+ LengthOrPercentageOrNone::Percentage(ref percentage) => percentage.to_css(dest),
+ LengthOrPercentageOrNone::Calc(ref calc) => calc.to_css(dest),
LengthOrPercentageOrNone::None => dest.write_str("none"),
}
}
}
impl LengthOrPercentageOrNone {
fn parse_internal(input: &mut Parser, context: &AllowedNumericType)
-> Result<LengthOrPercentageOrNone, ()>
{
@@ -992,17 +1004,17 @@ impl LengthOrPercentageOrNone {
pub enum LengthOrNone {
Length(Length),
None,
}
impl HasViewportPercentage for LengthOrNone {
fn has_viewport_percentage(&self) -> bool {
match *self {
- LengthOrNone::Length(length) => length.has_viewport_percentage(),
+ LengthOrNone::Length(ref length) => length.has_viewport_percentage(),
_ => false
}
}
}
impl ToCss for LengthOrNone {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
@@ -1046,16 +1058,17 @@ pub enum LengthOrPercentageOrAutoOrConte
Auto,
Content
}
impl HasViewportPercentage for LengthOrPercentageOrAutoOrContent {
fn has_viewport_percentage(&self) -> bool {
match *self {
LengthOrPercentageOrAutoOrContent::Length(length) => length.has_viewport_percentage(),
+ LengthOrPercentageOrAutoOrContent::Calc(ref calc) => calc.has_viewport_percentage(),
_ => false
}
}
}
impl ToCss for LengthOrPercentageOrAutoOrContent {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {