aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/style/properties/gecko.mako.rs3
-rw-r--r--components/style/properties/longhand/border.mako.rs110
-rw-r--r--components/style/values/computed/length.rs8
-rw-r--r--components/style/values/computed/mod.rs2
-rw-r--r--components/style/values/computed/rect.rs11
-rw-r--r--components/style/values/generics/mod.rs1
-rw-r--r--components/style/values/generics/rect.rs110
-rw-r--r--components/style/values/specified/length.rs6
-rw-r--r--components/style/values/specified/mod.rs2
-rw-r--r--components/style/values/specified/rect.rs21
10 files changed, 169 insertions, 105 deletions
diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs
index fa7d5c67271..d2416781330 100644
--- a/components/style/properties/gecko.mako.rs
+++ b/components/style/properties/gecko.mako.rs
@@ -959,8 +959,7 @@ fn static_assert() {
pub fn set_border_image_outset(&mut self, v: longhands::border_image_outset::computed_value::T) {
% for side in SIDES:
- v.${side.index}.to_gecko_style_coord(&mut self.gecko.mBorderImageOutset
- .data_at_mut(${side.index}));
+ v.${side.ident}.to_gecko_style_coord(&mut self.gecko.mBorderImageOutset.data_at_mut(${side.index}));
% endfor
}
diff --git a/components/style/properties/longhand/border.mako.rs b/components/style/properties/longhand/border.mako.rs
index 8c775b682c0..82169a9a943 100644
--- a/components/style/properties/longhand/border.mako.rs
+++ b/components/style/properties/longhand/border.mako.rs
@@ -200,109 +200,13 @@ ${helpers.predefined_type("border-image-source", "ImageLayer",
has_uncacheable_values=False,
boxed="True")}
-<%helpers:longhand name="border-image-outset" animation_value_type="none"
- spec="https://drafts.csswg.org/css-backgrounds/#border-image-outset">
- use std::fmt;
- use style_traits::ToCss;
- use values::specified::{LengthOrNumber, Number};
-
- pub mod computed_value {
- use values::computed::LengthOrNumber;
- #[derive(Debug, Clone, PartialEq)]
- #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
- pub struct T(pub LengthOrNumber, pub LengthOrNumber,
- pub LengthOrNumber, pub LengthOrNumber);
- }
-
- #[derive(Clone, Debug, HasViewportPercentage, PartialEq)]
- #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
- pub struct SpecifiedValue(pub Vec<LengthOrNumber>);
-
- impl ToCss for computed_value::T {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- try!(self.0.to_css(dest));
- try!(dest.write_str(" "));
- try!(self.1.to_css(dest));
- try!(dest.write_str(" "));
- try!(self.2.to_css(dest));
- try!(dest.write_str(" "));
- self.3.to_css(dest)
- }
- }
- impl ToCss for SpecifiedValue {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- try!(self.0[0].to_css(dest));
- for value in self.0.iter().skip(1) {
- try!(dest.write_str(" "));
- try!(value.to_css(dest));
- }
- Ok(())
- }
- }
-
- #[inline]
- pub fn get_initial_value() -> computed_value::T {
- computed_value::T(Either::Second(0.0), Either::Second(0.0),
- Either::Second(0.0), Either::Second(0.0))
- }
-
- #[inline]
- pub fn get_initial_specified_value() -> SpecifiedValue {
- SpecifiedValue(vec![Either::Second(Number::new(0.0))])
- }
-
- impl ToComputedValue for SpecifiedValue {
- type ComputedValue = computed_value::T;
-
- #[inline]
- fn to_computed_value(&self, context: &Context) -> computed_value::T {
- let length = self.0.len();
- match length {
- 4 => computed_value::T(self.0[0].to_computed_value(context),
- self.0[1].to_computed_value(context),
- self.0[2].to_computed_value(context),
- self.0[3].to_computed_value(context)),
- 3 => computed_value::T(self.0[0].to_computed_value(context),
- self.0[1].to_computed_value(context),
- self.0[2].to_computed_value(context),
- self.0[1].to_computed_value(context)),
- 2 => computed_value::T(self.0[0].to_computed_value(context),
- self.0[1].to_computed_value(context),
- self.0[0].to_computed_value(context),
- self.0[1].to_computed_value(context)),
- 1 => computed_value::T(self.0[0].to_computed_value(context),
- self.0[0].to_computed_value(context),
- self.0[0].to_computed_value(context),
- self.0[0].to_computed_value(context)),
- _ => unreachable!(),
- }
- }
- #[inline]
- fn from_computed_value(computed: &computed_value::T) -> Self {
- SpecifiedValue(vec![ToComputedValue::from_computed_value(&computed.0),
- ToComputedValue::from_computed_value(&computed.1),
- ToComputedValue::from_computed_value(&computed.2),
- ToComputedValue::from_computed_value(&computed.3)])
- }
- }
-
- pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
- let mut values = vec![];
- for _ in 0..4 {
- let value = input.try(|input| LengthOrNumber::parse_non_negative(context, input));
- match value {
- Ok(val) => values.push(val),
- Err(_) => break,
- }
- }
-
- if values.len() > 0 {
- Ok(SpecifiedValue(values))
- } else {
- Err(())
- }
- }
-</%helpers:longhand>
+${helpers.predefined_type("border-image-outset", "LengthOrNumberRect",
+ parse_method="parse_non_negative",
+ initial_value="computed::LengthOrNumber::zero().into()",
+ initial_specified_value="specified::LengthOrNumber::zero().into()",
+ spec="https://drafts.csswg.org/css-backgrounds/#border-image-outset",
+ animation_value_type="none",
+ boxed=True)}
<%helpers:longhand name="border-image-repeat" animation_value_type="none"
spec="https://drafts.csswg.org/css-backgrounds/#border-image-repeat">
diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs
index e2dac197652..1ed038941a7 100644
--- a/components/style/values/computed/length.rs
+++ b/components/style/values/computed/length.rs
@@ -603,6 +603,14 @@ pub type LengthOrAuto = Either<Length, Auto>;
/// Either a computed `<length>` or a `<number>` value.
pub type LengthOrNumber = Either<Length, Number>;
+impl LengthOrNumber {
+ /// Returns `0`.
+ #[inline]
+ pub fn zero() -> Self {
+ Either::Second(0.)
+ }
+}
+
/// Either a computed `<length>` or the `normal` keyword.
pub type LengthOrNormal = Either<Length, Normal>;
diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs
index 7251b315796..97d3ca76114 100644
--- a/components/style/values/computed/mod.rs
+++ b/components/style/values/computed/mod.rs
@@ -25,6 +25,7 @@ use super::specified;
pub use app_units::Au;
pub use cssparser::Color as CSSColor;
pub use self::image::{Gradient, GradientItem, ImageLayer, LineDirection, Image, ImageRect};
+pub use self::rect::LengthOrNumberRect;
pub use super::{Auto, Either, None_};
#[cfg(feature = "gecko")]
pub use super::specified::{AlignItems, AlignJustifyContent, AlignJustifySelf, JustifyItems};
@@ -40,6 +41,7 @@ pub mod basic_shape;
pub mod image;
pub mod length;
pub mod position;
+pub mod rect;
/// A `Context` is all the data a specified value could ever need to compute
/// itself and be transformed to a computed value.
diff --git a/components/style/values/computed/rect.rs b/components/style/values/computed/rect.rs
new file mode 100644
index 00000000000..46fcdc65583
--- /dev/null
+++ b/components/style/values/computed/rect.rs
@@ -0,0 +1,11 @@
+/* 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/. */
+
+//! Computed types for CSS borders.
+
+use values::computed::length::LengthOrNumber;
+use values::generics::rect::Rect;
+
+/// A specified rectangle made of four `<length-or-number>` values.
+pub type LengthOrNumberRect = Rect<LengthOrNumber>;
diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs
index 65fca55feb6..de5e043c52e 100644
--- a/components/style/values/generics/mod.rs
+++ b/components/style/values/generics/mod.rs
@@ -19,6 +19,7 @@ pub mod basic_shape;
pub mod grid;
pub mod image;
pub mod position;
+pub mod rect;
#[derive(Clone, Debug, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
diff --git a/components/style/values/generics/rect.rs b/components/style/values/generics/rect.rs
new file mode 100644
index 00000000000..767ce2223e4
--- /dev/null
+++ b/components/style/values/generics/rect.rs
@@ -0,0 +1,110 @@
+/* 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/. */
+
+//! Generic types for CSS values that are composed of four sides.
+
+use cssparser::Parser;
+use parser::{Parse, ParserContext};
+use std::fmt;
+use style_traits::ToCss;
+
+/// A CSS value made of four sides: top, right, bottom, and left.
+#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
+#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+pub struct Rect<T> {
+ /// Top
+ pub top: T,
+ /// Right.
+ pub right: T,
+ /// Bottom.
+ pub bottom: T,
+ /// Left.
+ pub left: T,
+}
+
+impl<T> Rect<T> {
+ /// Returns a new `Rect<T>` value.
+ pub fn new(top: T, right: T, bottom: T, left: T) -> Self {
+ Rect {
+ top: top,
+ right: right,
+ bottom: bottom,
+ left: left,
+ }
+ }
+}
+
+impl<T> Rect<T>
+ where T: Clone
+{
+ /// Parses a new `Rect<T>` value with the given parse function.
+ pub fn parse_with<Parse>(
+ context: &ParserContext,
+ input: &mut Parser,
+ parse: Parse)
+ -> Result<Self, ()>
+ where Parse: Fn(&ParserContext, &mut Parser) -> Result<T, ()>
+ {
+ let top = parse(context, input)?;
+ let right = if let Ok(right) = input.try(|i| parse(context, i)) { right } else {
+ // <top>
+ return Ok(Self::new(top.clone(), top.clone(), top.clone(), top));
+ };
+ let bottom = if let Ok(bottom) = input.try(|i| parse(context, i)) { bottom } else {
+ // <top> <right>
+ return Ok(Self::new(top.clone(), right.clone(), top, right));
+ };
+ let left = if let Ok(left) = input.try(|i| parse(context, i)) { left } else {
+ // <top> <right> <bottom>
+ return Ok(Self::new(top, right.clone(), bottom, right));
+ };
+ // <top> <right> <bottom> <left>
+ Ok(Self::new(top, right, bottom, left))
+ }
+}
+
+impl<T> From<T> for Rect<T>
+ where T: Clone
+{
+ #[inline]
+ fn from(value: T) -> Self {
+ Self::new(value.clone(), value.clone(), value.clone(), value)
+ }
+}
+
+impl<T> Parse for Rect<T>
+ where T: Clone + Parse
+{
+ #[inline]
+ fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
+ Self::parse_with(context, input, T::parse)
+ }
+}
+
+impl<T> ToCss for Rect<T>
+ where T: PartialEq + ToCss
+{
+ fn to_css<W>(&self, dest: &mut W) -> fmt::Result
+ where W: fmt::Write,
+ {
+ self.top.to_css(dest)?;
+ let same_vertical = self.top == self.bottom;
+ let same_horizontal = self.right == self.left;
+ if same_vertical && same_horizontal && self.top == self.right {
+ return Ok(());
+ }
+ dest.write_str(" ")?;
+ self.right.to_css(dest)?;
+ if same_vertical && same_horizontal {
+ return Ok(());
+ }
+ dest.write_str(" ")?;
+ self.bottom.to_css(dest)?;
+ if same_horizontal {
+ return Ok(());
+ }
+ dest.write_str(" ")?;
+ self.left.to_css(dest)
+ }
+}
diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs
index e37aad81f0e..ef4083544ae 100644
--- a/components/style/values/specified/length.rs
+++ b/components/style/values/specified/length.rs
@@ -1180,6 +1180,12 @@ impl LengthOrNumber {
Length::parse_non_negative(context, input).map(Either::First)
}
+
+ /// Returns `0`.
+ #[inline]
+ pub fn zero() -> Self {
+ Either::Second(Number::new(0.))
+ }
}
/// A value suitable for a `min-width` or `min-height` property.
diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs
index 8d75e0c4a07..87a46823d5f 100644
--- a/components/style/values/specified/mod.rs
+++ b/components/style/values/specified/mod.rs
@@ -30,6 +30,7 @@ use values::specified::calc::CalcNode;
#[cfg(feature = "gecko")]
pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, JustifyItems};
+pub use self::rect::LengthOrNumberRect;
pub use self::color::Color;
pub use super::generics::grid::GridLine;
pub use self::image::{ColorStop, EndingShape as GradientEndingShape, Gradient};
@@ -50,6 +51,7 @@ pub mod grid;
pub mod image;
pub mod length;
pub mod position;
+pub mod rect;
/// Common handling for the specified value CSS url() values.
pub mod url {
diff --git a/components/style/values/specified/rect.rs b/components/style/values/specified/rect.rs
new file mode 100644
index 00000000000..11c03e57f7b
--- /dev/null
+++ b/components/style/values/specified/rect.rs
@@ -0,0 +1,21 @@
+/* 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/. */
+
+//! Computed types for CSS borders.
+
+use cssparser::Parser;
+use parser::ParserContext;
+use values::generics::rect::Rect;
+use values::specified::length::LengthOrNumber;
+
+/// A specified rectangle made of four `<length-or-number>` values.
+pub type LengthOrNumberRect = Rect<LengthOrNumber>;
+
+impl LengthOrNumberRect {
+ /// Parses a `LengthOrNumberRect`, rejecting negative values.
+ #[inline]
+ pub fn parse_non_negative(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
+ Rect::parse_with(context, input, LengthOrNumber::parse_non_negative)
+ }
+}