aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-06-07 08:55:08 -0700
committerGitHub <noreply@github.com>2017-06-07 08:55:08 -0700
commit738483742c32f6de680b13be31ffc552059b39b9 (patch)
tree058ec0acdb2b6df5679394c967e982abdc039f8b
parent7e273d6c9b86d6ffbf216e84ae7326976888e5ef (diff)
parent45e8b0e8c7a7958c688fbbfcdd056592a9958ca5 (diff)
downloadservo-738483742c32f6de680b13be31ffc552059b39b9.tar.gz
servo-738483742c32f6de680b13be31ffc552059b39b9.zip
Auto merge of #17209 - servo:derive-all-the-things, r=emilio
Introduce more generics and more deriving <!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/17209) <!-- Reviewable:end -->
-rw-r--r--components/style/properties/gecko.mako.rs12
-rw-r--r--components/style/properties/longhand/box.mako.rs13
-rw-r--r--components/style/properties/longhand/font.mako.rs29
-rw-r--r--components/style/properties/longhand/text.mako.rs77
-rw-r--r--components/style/properties/properties.mako.rs18
-rw-r--r--components/style/values/computed/mod.rs2
-rw-r--r--components/style/values/computed/text.rs9
-rw-r--r--components/style/values/generics/background.rs23
-rw-r--r--components/style/values/generics/basic_shape.rs13
-rw-r--r--components/style/values/generics/border.rs16
-rw-r--r--components/style/values/generics/grid.rs12
-rw-r--r--components/style/values/generics/mod.rs25
-rw-r--r--components/style/values/generics/text.rs74
-rw-r--r--components/style/values/specified/border.rs15
-rw-r--r--components/style/values/specified/length.rs41
-rw-r--r--components/style/values/specified/mod.rs2
-rw-r--r--components/style/values/specified/text.rs20
-rw-r--r--components/style/values/specified/transform.rs18
-rw-r--r--components/style_derive/to_css.rs46
-rw-r--r--components/style_traits/values.rs11
20 files changed, 153 insertions, 323 deletions
diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs
index fa2bac3f618..efefebcfe16 100644
--- a/components/style/properties/gecko.mako.rs
+++ b/components/style/properties/gecko.mako.rs
@@ -3894,18 +3894,18 @@ fn static_assert() {
}
pub fn set_initial_letter(&mut self, v: longhands::initial_letter::computed_value::T) {
- use properties::longhands::initial_letter::computed_value::T;
+ use values::generics::text::InitialLetter;
match v {
- T::Normal => {
+ InitialLetter::Normal => {
self.gecko.mInitialLetterSize = 0.;
self.gecko.mInitialLetterSink = 0;
},
- T::Specified(size, sink) => {
- self.gecko.mInitialLetterSize = size.get();
+ InitialLetter::Specified(size, sink) => {
+ self.gecko.mInitialLetterSize = size;
if let Some(sink) = sink {
- self.gecko.mInitialLetterSink = sink.value();
+ self.gecko.mInitialLetterSink = sink;
} else {
- self.gecko.mInitialLetterSink = size.get().floor() as i32;
+ self.gecko.mInitialLetterSink = size.floor() as i32;
}
}
}
diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs
index 2bf0c1b17f3..0b358609ab7 100644
--- a/components/style/properties/longhand/box.mako.rs
+++ b/components/style/properties/longhand/box.mako.rs
@@ -545,8 +545,6 @@ ${helpers.predefined_type("animation-timing-function",
extra_prefixes="moz webkit"
spec="https://drafts.csswg.org/css-animations/#propdef-animation-iteration-count",
allowed_in_keyframe_block="False">
- use std::fmt;
- use style_traits::ToCss;
use values::computed::ComputedValueAsSpecified;
pub mod computed_value {
@@ -554,8 +552,8 @@ ${helpers.predefined_type("animation-timing-function",
}
// https://drafts.csswg.org/css-animations/#animation-iteration-count
- #[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+ #[derive(Debug, Clone, PartialEq, ToCss)]
pub enum SpecifiedValue {
Number(f32),
Infinite,
@@ -576,15 +574,6 @@ ${helpers.predefined_type("animation-timing-function",
}
}
- impl ToCss for SpecifiedValue {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- match *self {
- SpecifiedValue::Number(n) => write!(dest, "{}", n),
- SpecifiedValue::Infinite => dest.write_str("infinite"),
- }
- }
- }
-
no_viewport_percentage!(SpecifiedValue);
#[inline]
diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs
index 2c491a1630a..51963a7dbb0 100644
--- a/components/style/properties/longhand/font.mako.rs
+++ b/components/style/properties/longhand/font.mako.rs
@@ -1039,28 +1039,15 @@ ${helpers.single_keyword_system("font-variant-caps",
pub mod computed_value {
use properties::animated_properties::Animatable;
- use std::fmt;
- use style_traits::ToCss;
use values::CSSFloat;
- #[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+ #[derive(Copy, Clone, Debug, PartialEq, ToCss)]
pub enum T {
None,
Number(CSSFloat),
}
- impl ToCss for T {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result
- where W: fmt::Write,
- {
- match *self {
- T::None => dest.write_str("none"),
- T::Number(number) => number.to_css(dest),
- }
- }
- }
-
impl T {
pub fn from_gecko_adjust(gecko: f32) -> Self {
if gecko == -1.0 {
@@ -2214,9 +2201,7 @@ ${helpers.single_keyword("-moz-math-variant",
use app_units::Au;
use cssparser::Parser;
use properties::longhands;
- use std::fmt;
use std::hash::{Hash, Hasher};
- use style_traits::ToCss;
use values::computed::{ToComputedValue, Context};
<%
system_fonts = """caption icon menu message-box small-caption status-bar
@@ -2230,23 +2215,13 @@ ${helpers.single_keyword("-moz-math-variant",
kw_cast = """font_style font_variant_caps font_stretch
font_kerning font_variant_position""".split()
%>
- #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+ #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, ToCss)]
pub enum SystemFont {
% for font in system_fonts:
${to_camel_case(font)},
% endfor
}
- impl ToCss for SystemFont {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- dest.write_str(match *self {
- % for font in system_fonts:
- SystemFont::${to_camel_case(font)} => "${font}",
- % endfor
- })
- }
- }
-
// ComputedValues are compared at times
// so we need these impls. We don't want to
// add Eq to Number (which contains a float)
diff --git a/components/style/properties/longhand/text.mako.rs b/components/style/properties/longhand/text.mako.rs
index 0b4257b67f6..d636ed3cb64 100644
--- a/components/style/properties/longhand/text.mako.rs
+++ b/components/style/properties/longhand/text.mako.rs
@@ -287,72 +287,11 @@ ${helpers.predefined_type(
ignored_when_colors_disabled=True,
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-color")}
-<%helpers:longhand name="initial-letter"
- animation_value_type="none"
- products="gecko"
- spec="https://drafts.csswg.org/css-inline/#sizing-drop-initials">
- use std::fmt;
- use style_traits::ToCss;
- use values::computed::ComputedValueAsSpecified;
- use values::specified::{Number, Integer};
-
- impl ComputedValueAsSpecified for SpecifiedValue {}
- no_viewport_percentage!(SpecifiedValue);
-
- #[derive(PartialEq, Clone, Debug)]
- #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
- pub enum SpecifiedValue {
- Normal,
- Specified(Number, Option<Integer>)
- }
-
- pub mod computed_value {
- pub use super::SpecifiedValue as T;
- }
-
- impl ToCss for SpecifiedValue {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- match *self {
- SpecifiedValue::Normal => try!(dest.write_str("normal")),
- SpecifiedValue::Specified(size, sink) => {
- try!(size.to_css(dest));
- if let Some(sink) = sink {
- try!(dest.write_str(" "));
- try!(sink.to_css(dest));
- }
- }
- };
-
- Ok(())
- }
- }
-
- #[inline]
- pub fn get_initial_value() -> computed_value::T {
- computed_value::T::Normal
- }
-
- #[inline]
- pub fn get_initial_specified_value() -> SpecifiedValue {
- SpecifiedValue::Normal
- }
-
- /// normal | <number> <integer>?
- pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
- if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
- return Ok(SpecifiedValue::Normal);
- }
-
- let size = try!(Number::parse_at_least_one(context, input));
-
- match input.try(|input| Integer::parse(context, input)) {
- Ok(number) => {
- if number.value() < 1 {
- return Err(());
- }
- Ok(SpecifiedValue::Specified(size, Some(number)))
- }
- Err(()) => Ok(SpecifiedValue::Specified(size, None)),
- }
- }
-</%helpers:longhand>
+${helpers.predefined_type(
+ "initial-letter",
+ "InitialLetter",
+ "computed::InitialLetter::normal()",
+ initial_specified_value="specified::InitialLetter::normal()",
+ animation_value_type="none",
+ products="gecko",
+ spec="https://drafts.csswg.org/css-inline/#sizing-drop-initials")}
diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs
index 1ec0dee0ef7..1a4af56d9cc 100644
--- a/components/style/properties/properties.mako.rs
+++ b/components/style/properties/properties.mako.rs
@@ -450,8 +450,8 @@ impl PropertyDeclarationIdSet {
% endfor
/// An enum to represent a CSS Wide keyword.
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, ToCss)]
pub enum CSSWideKeyword {
/// The `initial` keyword.
Initial,
@@ -483,12 +483,6 @@ impl CSSWideKeyword {
}
}
-impl ToCss for CSSWideKeyword {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- dest.write_str(self.to_str())
- }
-}
-
impl Parse for CSSWideKeyword {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
let ident = input.expect_ident()?;
@@ -628,8 +622,8 @@ impl LonghandId {
}
/// An identifier for a given shorthand property.
-#[derive(Clone, Copy, Eq, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+#[derive(Clone, Copy, Debug, Eq, PartialEq, ToCss)]
pub enum ShorthandId {
% for property in data.shorthands:
/// ${property.name}
@@ -637,14 +631,6 @@ pub enum ShorthandId {
% endfor
}
-impl ToCss for ShorthandId {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result
- where W: fmt::Write,
- {
- dest.write_str(self.name())
- }
-}
-
impl ShorthandId {
/// Get the name for this shorthand property.
pub fn name(&self) -> &'static str {
diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs
index 1fbaa17c87f..1547cf29424 100644
--- a/components/style/values/computed/mod.rs
+++ b/components/style/values/computed/mod.rs
@@ -42,7 +42,7 @@ pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNumber, LengthOrP
pub use self::length::{LengthOrPercentageOrAutoOrContent, LengthOrPercentageOrNone, LengthOrNone};
pub use self::length::{MaxLength, MozLength};
pub use self::position::Position;
-pub use self::text::{LetterSpacing, LineHeight, WordSpacing};
+pub use self::text::{InitialLetter, LetterSpacing, LineHeight, WordSpacing};
pub use self::transform::{TimingFunction, TransformOrigin};
pub mod background;
diff --git a/components/style/values/computed/text.rs b/components/style/values/computed/text.rs
index d45242015c4..857a985d851 100644
--- a/components/style/values/computed/text.rs
+++ b/components/style/values/computed/text.rs
@@ -6,9 +6,14 @@
use app_units::Au;
use properties::animated_properties::Animatable;
-use values::CSSFloat;
+use values::{CSSInteger, CSSFloat};
use values::computed::length::{Length, LengthOrPercentage};
-use values::generics::text::{LineHeight as GenericLineHeight, Spacing};
+use values::generics::text::InitialLetter as GenericInitialLetter;
+use values::generics::text::LineHeight as GenericLineHeight;
+use values::generics::text::Spacing;
+
+/// A computed value for the `initial-letter` property.
+pub type InitialLetter = GenericInitialLetter<CSSFloat, CSSInteger>;
/// A computed value for the `letter-spacing` property.
pub type LetterSpacing = Spacing<Length>;
diff --git a/components/style/values/generics/background.rs b/components/style/values/generics/background.rs
index af8cef23a38..aa24454ef6d 100644
--- a/components/style/values/generics/background.rs
+++ b/components/style/values/generics/background.rs
@@ -4,11 +4,8 @@
//! Generic types for CSS values related to backgrounds.
-use std::fmt;
-use style_traits::ToCss;
-
/// A generic value for the `background-size` property.
-#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
+#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue, ToCss)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum BackgroundSize<LengthOrPercentageOrAuto> {
/// `<width> <height>`
@@ -32,21 +29,3 @@ impl<L> From<L> for BackgroundSize<L>
BackgroundSize::Explicit { width: value.clone(), height: value }
}
}
-
-impl<L> ToCss for BackgroundSize<L>
- where L: ToCss
-{
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result
- where W: fmt::Write
- {
- match *self {
- BackgroundSize::Explicit { ref width, ref height } => {
- width.to_css(dest)?;
- dest.write_str(" ")?;
- height.to_css(dest)
- },
- BackgroundSize::Cover => dest.write_str("cover"),
- BackgroundSize::Contain => dest.write_str("contain"),
- }
- }
-}
diff --git a/components/style/values/generics/basic_shape.rs b/components/style/values/generics/basic_shape.rs
index b2d402dd38f..cd8e315f3b3 100644
--- a/components/style/values/generics/basic_shape.rs
+++ b/components/style/values/generics/basic_shape.rs
@@ -19,7 +19,7 @@ pub type ClippingShape<BasicShape> = ShapeSource<BasicShape, GeometryBox>;
/// https://drafts.fxtf.org/css-masking-1/#typedef-geometry-box
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-#[derive(Clone, Copy, Debug, PartialEq)]
+#[derive(Clone, Copy, Debug, PartialEq, ToCss)]
pub enum GeometryBox {
FillBox,
StrokeBox,
@@ -142,17 +142,6 @@ impl<B: ToCss, T: ToCss> ToCss for ShapeSource<B, T> {
}
}
-impl ToCss for GeometryBox {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- match *self {
- GeometryBox::FillBox => dest.write_str("fill-box"),
- GeometryBox::StrokeBox => dest.write_str("stroke-box"),
- GeometryBox::ViewBox => dest.write_str("view-box"),
- GeometryBox::ShapeBox(s) => s.to_css(dest),
- }
- }
-}
-
impl<L> ToCss for InsetRect<L>
where L: ToCss + PartialEq
{
diff --git a/components/style/values/generics/border.rs b/components/style/values/generics/border.rs
index f1384e580e3..5d8c9032e6a 100644
--- a/components/style/values/generics/border.rs
+++ b/components/style/values/generics/border.rs
@@ -11,7 +11,7 @@ use values::generics::rect::Rect;
/// A generic value for a single side of a `border-image-width` property.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
+#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue, ToCss)]
pub enum BorderImageSideWidth<LengthOrPercentage, Number> {
/// `<length-or-percentage>`
Length(LengthOrPercentage),
@@ -52,20 +52,6 @@ pub struct BorderRadius<LengthOrPercentage> {
/// A generic value for `border-*-radius` longhand properties.
pub struct BorderCornerRadius<L>(pub Size2D<L>);
-impl<L, N> ToCss for BorderImageSideWidth<L, N>
- where L: ToCss, N: ToCss,
-{
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result
- where W: fmt::Write
- {
- match *self {
- BorderImageSideWidth::Length(ref length) => length.to_css(dest),
- BorderImageSideWidth::Number(ref number) => number.to_css(dest),
- BorderImageSideWidth::Auto => dest.write_str("auto"),
- }
- }
-}
-
impl<N> From<N> for BorderImageSlice<N>
where N: Clone,
{
diff --git a/components/style/values/generics/grid.rs b/components/style/values/generics/grid.rs
index 73640a91e49..3775bb30597 100644
--- a/components/style/values/generics/grid.rs
+++ b/components/style/values/generics/grid.rs
@@ -329,8 +329,8 @@ pub fn concat_serialize_idents<W>(prefix: &str, suffix: &str,
/// The initial argument of the `repeat` function.
///
/// https://drafts.csswg.org/css-grid/#typedef-track-repeat
-#[derive(Clone, Copy, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+#[derive(Clone, Copy, Debug, PartialEq, ToCss)]
pub enum RepeatCount {
/// A positive integer. This is allowed only for `<track-repeat>` and `<fixed-repeat>`
Number(Integer),
@@ -340,16 +340,6 @@ pub enum RepeatCount {
AutoFit,
}
-impl ToCss for RepeatCount {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- match *self {
- RepeatCount::Number(ref c) => c.to_css(dest),
- RepeatCount::AutoFill => dest.write_str("auto-fill"),
- RepeatCount::AutoFit => dest.write_str("auto-fit"),
- }
- }
-}
-
impl Parse for RepeatCount {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
if let Ok(i) = input.try(|i| Integer::parse(context, i)) {
diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs
index ef88d7c342c..40d3f4e46df 100644
--- a/components/style/values/generics/mod.rs
+++ b/components/style/values/generics/mod.rs
@@ -182,8 +182,8 @@ impl<T: Parse> Parse for FontSettingTag<T> {
/// A font settings value for font-variation-settings or font-feature-settings
-#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+#[derive(Clone, Debug, Eq, PartialEq, ToCss)]
pub enum FontSettings<T> {
/// No settings (default)
Normal,
@@ -191,15 +191,6 @@ pub enum FontSettings<T> {
Tag(Vec<FontSettingTag<T>>)
}
-impl<T: ToCss> ToCss for FontSettings<T> {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- match *self {
- FontSettings::Normal => dest.write_str("normal"),
- FontSettings::Tag(ref ftvs) => ftvs.to_css(dest)
- }
- }
-}
-
impl<T: Parse> Parse for FontSettings<T> {
/// https://www.w3.org/TR/css-fonts-3/#propdef-font-feature-settings
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
@@ -290,8 +281,8 @@ pub struct SVGPaint<ColorType> {
/// Whereas the spec only allows PaintServer
/// to have a fallback, Gecko lets the context
/// properties have a fallback as well.
-#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+#[derive(Clone, Debug, PartialEq, ToCss)]
pub enum SVGPaintKind<ColorType> {
/// `none`
None,
@@ -378,18 +369,6 @@ impl<ColorType: Parse> Parse for SVGPaint<ColorType> {
}
}
-impl<ColorType: ToCss> ToCss for SVGPaintKind<ColorType> {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- match *self {
- SVGPaintKind::None => dest.write_str("none"),
- SVGPaintKind::ContextStroke => dest.write_str("context-stroke"),
- SVGPaintKind::ContextFill => dest.write_str("context-fill"),
- SVGPaintKind::Color(ref color) => color.to_css(dest),
- SVGPaintKind::PaintServer(ref server) => server.to_css(dest),
- }
- }
-}
-
impl<ColorType: ToCss> ToCss for SVGPaint<ColorType> {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
self.kind.to_css(dest)?;
diff --git a/components/style/values/generics/text.rs b/components/style/values/generics/text.rs
index 2ba5ae4af98..5a5a10bb9d9 100644
--- a/components/style/values/generics/text.rs
+++ b/components/style/values/generics/text.rs
@@ -11,9 +11,50 @@ use properties::animated_properties::Animatable;
use std::fmt;
use style_traits::ToCss;
-/// A generic spacing value for the `letter-spacing` and `word-spacing` properties.alloc
+/// A generic value for the `initial-letter` property.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
+pub enum InitialLetter<Number, Integer> {
+ /// `normal`
+ Normal,
+ /// `<number> <integer>?`
+ Specified(Number, Option<Integer>),
+}
+
+impl<N, I> InitialLetter<N, I> {
+ /// Returns `normal`.
+ #[inline]
+ pub fn normal() -> Self {
+ InitialLetter::Normal
+ }
+}
+
+impl<N, I> ToCss for InitialLetter<N, I>
+where
+ N: ToCss,
+ I: ToCss,
+{
+ fn to_css<W>(&self, dest: &mut W) -> fmt::Result
+ where
+ W: fmt::Write,
+ {
+ match *self {
+ InitialLetter::Normal => dest.write_str("normal"),
+ InitialLetter::Specified(ref size, ref sink) => {
+ size.to_css(dest)?;
+ if let Some(ref sink) = *sink {
+ dest.write_str(" ")?;
+ sink.to_css(dest)?;
+ }
+ Ok(())
+ },
+ }
+ }
+}
+
+/// A generic spacing value for the `letter-spacing` and `word-spacing` properties.
+#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue, ToCss)]
pub enum Spacing<Value> {
/// `normal`
Normal,
@@ -76,22 +117,9 @@ impl<Value> Animatable for Spacing<Value>
}
}
-impl<Value> ToCss for Spacing<Value>
- where Value: ToCss,
-{
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result
- where W: fmt::Write
- {
- match *self {
- Spacing::Normal => dest.write_str("normal"),
- Spacing::Value(ref value) => value.to_css(dest),
- }
- }
-}
-
/// A generic value for the `line-height` property.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq)]
+#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToCss)]
pub enum LineHeight<Number, LengthOrPercentage> {
/// `normal`
Normal,
@@ -111,19 +139,3 @@ impl<N, L> LineHeight<N, L> {
LineHeight::Normal
}
}
-
-impl<N, L> ToCss for LineHeight<N, L>
- where N: ToCss, L: ToCss,
-{
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result
- where W: fmt::Write,
- {
- match *self {
- LineHeight::Normal => dest.write_str("normal"),
- #[cfg(feature = "gecko")]
- LineHeight::MozBlockHeight => dest.write_str("-moz-block-height"),
- LineHeight::Number(ref number) => number.to_css(dest),
- LineHeight::Length(ref value) => value.to_css(dest),
- }
- }
-}
diff --git a/components/style/values/specified/border.rs b/components/style/values/specified/border.rs
index b931ef36245..53260bc8e33 100644
--- a/components/style/values/specified/border.rs
+++ b/components/style/values/specified/border.rs
@@ -7,8 +7,6 @@
use app_units::Au;
use cssparser::Parser;
use parser::{Parse, ParserContext};
-use std::fmt;
-use style_traits::ToCss;
use values::computed::{Context, ToComputedValue};
use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
use values::generics::border::BorderImageSideWidth as GenericBorderImageSideWidth;
@@ -20,7 +18,7 @@ use values::specified::length::{Length, LengthOrPercentage};
/// A specified value for a single side of the `border-width` property.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-#[derive(Clone, Debug, HasViewportPercentage, PartialEq)]
+#[derive(Clone, Debug, HasViewportPercentage, PartialEq, ToCss)]
pub enum BorderSideWidth {
/// `thin`
Thin,
@@ -73,17 +71,6 @@ impl Parse for BorderSideWidth {
}
}
-impl ToCss for BorderSideWidth {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- match *self {
- BorderSideWidth::Thin => dest.write_str("thin"),
- BorderSideWidth::Medium => dest.write_str("medium"),
- BorderSideWidth::Thick => dest.write_str("thick"),
- BorderSideWidth::Length(ref length) => length.to_css(dest)
- }
- }
-}
-
impl ToComputedValue for BorderSideWidth {
type ComputedValue = Au;
diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs
index 61335ee0e55..e7b49ee9392 100644
--- a/components/style/values/specified/length.rs
+++ b/components/style/values/specified/length.rs
@@ -894,9 +894,9 @@ impl LengthOrPercentage {
}
/// Either a `<length>`, a `<percentage>`, or the `auto` keyword.
-#[derive(Clone, Debug, HasViewportPercentage, PartialEq)]
-#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
+#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+#[derive(Clone, Debug, HasViewportPercentage, PartialEq, ToCss)]
pub enum LengthOrPercentageOrAuto {
Length(NoCalcLength),
Percentage(Percentage),
@@ -918,17 +918,6 @@ impl From<Percentage> for LengthOrPercentageOrAuto {
}
}
-impl ToCss for LengthOrPercentageOrAuto {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- match *self {
- LengthOrPercentageOrAuto::Length(ref length) => length.to_css(dest),
- LengthOrPercentageOrAuto::Percentage(percentage) => percentage.to_css(dest),
- LengthOrPercentageOrAuto::Auto => dest.write_str("auto"),
- LengthOrPercentageOrAuto::Calc(ref calc) => calc.to_css(dest),
- }
- }
-}
-
impl LengthOrPercentageOrAuto {
fn parse_internal(context: &ParserContext,
input: &mut Parser,
@@ -1012,8 +1001,8 @@ impl LengthOrPercentageOrAuto {
}
/// Either a `<length>`, a `<percentage>`, or the `none` keyword.
-#[derive(Clone, Debug, HasViewportPercentage, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+#[derive(Clone, Debug, HasViewportPercentage, PartialEq, ToCss)]
#[allow(missing_docs)]
pub enum LengthOrPercentageOrNone {
Length(NoCalcLength),
@@ -1022,16 +1011,6 @@ pub enum LengthOrPercentageOrNone {
None,
}
-impl ToCss for LengthOrPercentageOrNone {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- match *self {
- 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(context: &ParserContext,
input: &mut Parser,
@@ -1099,8 +1078,8 @@ pub type LengthOrAuto = Either<Length, Auto>;
/// Either a `<length>` or a `<percentage>` or the `auto` keyword or the
/// `content` keyword.
-#[derive(Clone, Debug, HasViewportPercentage, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+#[derive(Clone, Debug, HasViewportPercentage, PartialEq, ToCss)]
pub enum LengthOrPercentageOrAutoOrContent {
/// A `<length>`.
Length(NoCalcLength),
@@ -1156,18 +1135,6 @@ impl LengthOrPercentageOrAutoOrContent {
}
}
-impl ToCss for LengthOrPercentageOrAutoOrContent {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- match *self {
- LengthOrPercentageOrAutoOrContent::Length(ref len) => len.to_css(dest),
- LengthOrPercentageOrAutoOrContent::Percentage(perc) => perc.to_css(dest),
- LengthOrPercentageOrAutoOrContent::Auto => dest.write_str("auto"),
- LengthOrPercentageOrAutoOrContent::Content => dest.write_str("content"),
- LengthOrPercentageOrAutoOrContent::Calc(ref calc) => calc.to_css(dest),
- }
- }
-}
-
/// Either a `<length>` or a `<number>`.
pub type LengthOrNumber = Either<Length, Number>;
diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs
index d7046451336..59ff135c303 100644
--- a/components/style/values/specified/mod.rs
+++ b/components/style/values/specified/mod.rs
@@ -45,7 +45,7 @@ pub use self::length::{Percentage, LengthOrNone, LengthOrNumber, LengthOrPercent
pub use self::length::{LengthOrPercentageOrNone, LengthOrPercentageOrAutoOrContent, NoCalcLength};
pub use self::length::{MaxLength, MozLength};
pub use self::position::{Position, PositionComponent};
-pub use self::text::{LetterSpacing, LineHeight, WordSpacing};
+pub use self::text::{InitialLetter, LetterSpacing, LineHeight, WordSpacing};
pub use self::transform::{TimingFunction, TransformOrigin};
pub use super::generics::grid::GridLine;
diff --git a/components/style/values/specified/text.rs b/components/style/values/specified/text.rs
index cc517ad4abb..2d277e143ee 100644
--- a/components/style/values/specified/text.rs
+++ b/components/style/values/specified/text.rs
@@ -9,10 +9,15 @@ use parser::{Parse, ParserContext};
use std::ascii::AsciiExt;
use values::computed::{Context, ToComputedValue};
use values::computed::text::LineHeight as ComputedLineHeight;
-use values::generics::text::{LineHeight as GenericLineHeight, Spacing};
-use values::specified::{AllowQuirks, Number};
+use values::generics::text::InitialLetter as GenericInitialLetter;
+use values::generics::text::LineHeight as GenericLineHeight;
+use values::generics::text::Spacing;
+use values::specified::{AllowQuirks, Integer, Number};
use values::specified::length::{FontRelativeLength, Length, LengthOrPercentage, NoCalcLength};
+/// A specified type for the `initial-letter` property.
+pub type InitialLetter = GenericInitialLetter<Number, Integer>;
+
/// A specified value for the `letter-spacing` property.
pub type LetterSpacing = Spacing<Length>;
@@ -22,6 +27,17 @@ pub type WordSpacing = Spacing<LengthOrPercentage>;
/// A specified value for the `line-height` property.
pub type LineHeight = GenericLineHeight<Number, LengthOrPercentage>;
+impl Parse for InitialLetter {
+ fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
+ if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
+ return Ok(GenericInitialLetter::Normal);
+ }
+ let size = Number::parse_at_least_one(context, input)?;
+ let sink = input.try(|i| Integer::parse_positive(context, i)).ok();
+ Ok(GenericInitialLetter::Specified(size, sink))
+ }
+}
+
impl Parse for LetterSpacing {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
Spacing::parse_with(context, input, |c, i| {
diff --git a/components/style/values/specified/transform.rs b/components/style/values/specified/transform.rs
index f41539fc5b2..e0e5b1c2d6f 100644
--- a/components/style/values/specified/transform.rs
+++ b/components/style/values/specified/transform.rs
@@ -7,8 +7,6 @@
use cssparser::Parser;
use euclid::Point2D;
use parser::{Parse, ParserContext};
-use std::fmt;
-use style_traits::ToCss;
use values::computed::{LengthOrPercentage as ComputedLengthOrPercentage, Context, ToComputedValue};
use values::computed::transform::TimingFunction as ComputedTimingFunction;
use values::generics::transform::{StepPosition, TimingFunction as GenericTimingFunction};
@@ -22,7 +20,7 @@ pub type TransformOrigin = GenericTransformOrigin<OriginComponent<X>, OriginComp
/// The specified value of a component of a CSS `<transform-origin>`.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-#[derive(Clone, Debug, HasViewportPercentage, PartialEq)]
+#[derive(Clone, Debug, HasViewportPercentage, PartialEq, ToCss)]
pub enum OriginComponent<S> {
/// `center`
Center,
@@ -99,20 +97,6 @@ impl<S> Parse for OriginComponent<S>
}
}
-impl<S: ToCss> ToCss for OriginComponent<S>
- where S: ToCss,
-{
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result
- where W: fmt::Write,
- {
- match *self {
- OriginComponent::Center => dest.write_str("center"),
- OriginComponent::Length(ref lop) => lop.to_css(dest),
- OriginComponent::Side(ref keyword) => keyword.to_css(dest),
- }
- }
-}
-
impl<S> ToComputedValue for OriginComponent<S>
where S: Side,
{
diff --git a/components/style_derive/to_css.rs b/components/style_derive/to_css.rs
index 774add083fa..f85fe1ce418 100644
--- a/components/style_derive/to_css.rs
+++ b/components/style_derive/to_css.rs
@@ -15,9 +15,12 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
}
let style = synstructure::BindStyle::Ref.into();
- let match_body = synstructure::each_variant(&input, &style, |bindings, _| {
+ let match_body = synstructure::each_variant(&input, &style, |bindings, variant| {
if bindings.is_empty() {
- panic!("unit variants are not yet supported");
+ let identifier = to_css_identifier(variant.ident.as_ref());
+ return Some(quote! {
+ ::std::fmt::Write::write_str(dest, #identifier)
+ });
}
let (first, rest) = bindings.split_first().expect("unit variants are not yet supported");
where_clause.predicates.push(where_predicate(first.field.ty.clone()));
@@ -28,7 +31,7 @@ pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
where_clause.predicates.push(where_predicate(binding.field.ty.clone()));
expr = quote! {
#expr?;
- dest.write_str(" ")?;
+ ::std::fmt::Write::write_str(dest, " ")?;
::style_traits::ToCss::to_css(#binding, dest)
};
}
@@ -68,3 +71,40 @@ fn where_predicate(ty: syn::Ty) -> syn::WherePredicate {
)],
})
}
+
+/// Transforms "FooBar" to "foo-bar".
+///
+/// If the first Camel segment is "Moz"" or "Webkit", the result string
+/// is prepended with "-".
+fn to_css_identifier(mut camel_case: &str) -> String {
+ let mut first = true;
+ let mut result = String::with_capacity(camel_case.len());
+ while let Some(segment) = split_camel_segment(&mut camel_case) {
+ if first {
+ match segment {
+ "Moz" | "Webkit" => first = false,
+ _ => {},
+ }
+ }
+ if !first {
+ result.push_str("-");
+ }
+ first = false;
+ result.push_str(&segment.to_lowercase());
+ }
+ result
+}
+
+/// Given "FooBar", returns "Foo" and sets `camel_case` to "Bar".
+fn split_camel_segment<'input>(camel_case: &mut &'input str) -> Option<&'input str> {
+ let index = match camel_case.chars().next() {
+ None => return None,
+ Some(ch) => ch.len_utf8(),
+ };
+ let end_position = camel_case[index..]
+ .find(char::is_uppercase)
+ .map_or(camel_case.len(), |pos| index + pos);
+ let result = &camel_case[..end_position];
+ *camel_case = &camel_case[end_position..];
+ Some(result)
+}
diff --git a/components/style_traits/values.rs b/components/style_traits/values.rs
index aaff1a998ea..7c73f7bd4cf 100644
--- a/components/style_traits/values.rs
+++ b/components/style_traits/values.rs
@@ -8,8 +8,15 @@ use app_units::Au;
use cssparser::UnicodeRange;
use std::fmt;
-/// The real `ToCss` trait can't be implemented for types in crates that don't
-/// depend on each other.
+/// Serialises a value according to its CSS representation.
+///
+/// This trait is derivable with `#[derive(ToCss)]`, with the following behaviour:
+/// * unit variants get serialised as the `snake-case` representation
+/// of their name;
+/// * unit variants whose name starts with "Moz" or "Webkit" are prepended
+/// with a "-";
+/// * variants with fields get serialised as the space-separated serialisations
+/// of their fields.
pub trait ToCss {
/// Serialize `self` in CSS syntax, writing to `dest`.
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write;