Derive ToComputedValue

For now, only impls for types like in style::values::generics can be derived.

This also needed a few ToComputedValueAsSpecified impls that I would like to
replace by some #[to_computed_value(clone)] attribute, but I think it is ok
to keep it like this for now.
This commit is contained in:
Anthony Ramine 2017-05-21 01:04:00 +02:00
parent a99e73ba6b
commit 07c0456cfd
7 changed files with 247 additions and 422 deletions

View file

@ -4,6 +4,7 @@
//! Computed values. //! Computed values.
use Atom;
use context::QuirksMode; use context::QuirksMode;
use euclid::size::Size2D; use euclid::size::Size2D;
use font_metrics::FontMetricsProvider; use font_metrics::FontMetricsProvider;
@ -154,6 +155,79 @@ pub trait ToComputedValue {
fn from_computed_value(computed: &Self::ComputedValue) -> Self; fn from_computed_value(computed: &Self::ComputedValue) -> Self;
} }
impl<A, B> ToComputedValue for (A, B)
where A: ToComputedValue, B: ToComputedValue,
{
type ComputedValue = (
<A as ToComputedValue>::ComputedValue,
<B as ToComputedValue>::ComputedValue,
);
#[inline]
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
(self.0.to_computed_value(context), self.1.to_computed_value(context))
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
(A::from_computed_value(&computed.0), B::from_computed_value(&computed.1))
}
}
impl<T> ToComputedValue for Option<T>
where T: ToComputedValue
{
type ComputedValue = Option<<T as ToComputedValue>::ComputedValue>;
#[inline]
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
self.as_ref().map(|item| item.to_computed_value(context))
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
computed.as_ref().map(T::from_computed_value)
}
}
impl<T> ToComputedValue for Size2D<T>
where T: ToComputedValue
{
type ComputedValue = Size2D<<T as ToComputedValue>::ComputedValue>;
#[inline]
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
Size2D::new(
self.width.to_computed_value(context),
self.height.to_computed_value(context),
)
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
Size2D::new(
T::from_computed_value(&computed.width),
T::from_computed_value(&computed.height),
)
}
}
impl<T> ToComputedValue for Vec<T>
where T: ToComputedValue
{
type ComputedValue = Vec<<T as ToComputedValue>::ComputedValue>;
#[inline]
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
self.iter().map(|item| item.to_computed_value(context)).collect()
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
computed.iter().map(T::from_computed_value).collect()
}
}
/// A marker trait to represent that the specified value is also the computed /// A marker trait to represent that the specified value is also the computed
/// value. /// value.
pub trait ComputedValueAsSpecified {} pub trait ComputedValueAsSpecified {}
@ -174,6 +248,9 @@ impl<T> ToComputedValue for T
} }
} }
impl ComputedValueAsSpecified for Atom {}
impl ComputedValueAsSpecified for bool {}
/// A computed `<angle>` value. /// A computed `<angle>` value.
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, PartialOrd)] #[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, PartialOrd)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))] #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]

View file

@ -12,14 +12,14 @@ use properties::shorthands::serialize_four_sides;
use std::ascii::AsciiExt; use std::ascii::AsciiExt;
use std::fmt; use std::fmt;
use style_traits::{HasViewportPercentage, ToCss}; use style_traits::{HasViewportPercentage, ToCss};
use values::computed::{ComputedValueAsSpecified, Context, ToComputedValue}; use values::computed::ComputedValueAsSpecified;
use values::generics::BorderRadiusSize; use values::generics::BorderRadiusSize;
use values::specified::url::SpecifiedUrl; use values::specified::url::SpecifiedUrl;
/// A generic type used for `border-radius`, `outline-radius` and `inset()` values. /// A generic type used for `border-radius`, `outline-radius` and `inset()` values.
/// ///
/// https://drafts.csswg.org/css-backgrounds-3/#border-radius /// https://drafts.csswg.org/css-backgrounds-3/#border-radius
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, Debug, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct BorderRadius<L> { pub struct BorderRadius<L> {
/// The top left radius. /// The top left radius.
@ -59,32 +59,8 @@ impl<L: ToCss + PartialEq> ToCss for BorderRadius<L> {
} }
} }
impl<L: ToComputedValue> ToComputedValue for BorderRadius<L> {
type ComputedValue = BorderRadius<L::ComputedValue>;
#[inline]
fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue {
BorderRadius {
top_left: self.top_left.to_computed_value(cx),
top_right: self.top_right.to_computed_value(cx),
bottom_right: self.bottom_right.to_computed_value(cx),
bottom_left: self.bottom_left.to_computed_value(cx),
}
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
BorderRadius {
top_left: ToComputedValue::from_computed_value(&computed.top_left),
top_right: ToComputedValue::from_computed_value(&computed.top_right),
bottom_right: ToComputedValue::from_computed_value(&computed.bottom_right),
bottom_left: ToComputedValue::from_computed_value(&computed.bottom_left),
}
}
}
/// https://drafts.csswg.org/css-shapes/#typedef-shape-radius /// https://drafts.csswg.org/css-shapes/#typedef-shape-radius
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, Debug, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)] #[allow(missing_docs)]
pub enum ShapeRadius<L> { pub enum ShapeRadius<L> {
@ -109,28 +85,6 @@ impl<L: ToCss> ToCss for ShapeRadius<L> {
} }
} }
impl<L: ToComputedValue> ToComputedValue for ShapeRadius<L> {
type ComputedValue = ShapeRadius<L::ComputedValue>;
#[inline]
fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue {
match *self {
ShapeRadius::Length(ref lop) => ShapeRadius::Length(lop.to_computed_value(cx)),
ShapeRadius::ClosestSide => ShapeRadius::ClosestSide,
ShapeRadius::FarthestSide => ShapeRadius::FarthestSide,
}
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
match *computed {
ShapeRadius::Length(ref lop) => ShapeRadius::Length(ToComputedValue::from_computed_value(lop)),
ShapeRadius::ClosestSide => ShapeRadius::ClosestSide,
ShapeRadius::FarthestSide => ShapeRadius::FarthestSide,
}
}
}
// https://drafts.csswg.org/css-shapes/#typedef-fill-rule // https://drafts.csswg.org/css-shapes/#typedef-fill-rule
// NOTE: Basic shapes spec says that these are the only two values, however // NOTE: Basic shapes spec says that these are the only two values, however
// https://www.w3.org/TR/SVG/painting.html#FillRuleProperty // https://www.w3.org/TR/SVG/painting.html#FillRuleProperty
@ -147,7 +101,7 @@ impl Default for FillRule {
fn default() -> Self { FillRule::NonZero } fn default() -> Self { FillRule::NonZero }
} }
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, Debug, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// A generic type for representing the `polygon()` function /// A generic type for representing the `polygon()` function
/// ///
@ -211,32 +165,7 @@ impl<L: ToCss> ToCss for Polygon<L> {
} }
} }
impl<L: ToComputedValue> ToComputedValue for Polygon<L> { #[derive(Clone, Debug, PartialEq, ToComputedValue)]
type ComputedValue = Polygon<L::ComputedValue>;
#[inline]
fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue {
Polygon {
fill: self.fill.to_computed_value(cx),
coordinates: self.coordinates.iter().map(|c| {
(c.0.to_computed_value(cx), c.1.to_computed_value(cx))
}).collect(),
}
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
Polygon {
fill: ToComputedValue::from_computed_value(&computed.fill),
coordinates: computed.coordinates.iter().map(|c| {
(ToComputedValue::from_computed_value(&c.0),
ToComputedValue::from_computed_value(&c.1))
}).collect(),
}
}
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// https://drafts.csswg.org/css-shapes/#funcdef-inset /// https://drafts.csswg.org/css-shapes/#funcdef-inset
#[allow(missing_docs)] #[allow(missing_docs)]
@ -268,37 +197,11 @@ impl<L: ToCss + PartialEq> ToCss for InsetRect<L> {
} }
} }
impl<L: ToComputedValue> ToComputedValue for InsetRect<L> {
type ComputedValue = InsetRect<L::ComputedValue>;
#[inline]
fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue {
InsetRect {
top: self.top.to_computed_value(cx),
right: self.right.to_computed_value(cx),
bottom: self.bottom.to_computed_value(cx),
left: self.left.to_computed_value(cx),
round: self.round.as_ref().map(|r| r.to_computed_value(cx)),
}
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
InsetRect {
top: ToComputedValue::from_computed_value(&computed.top),
right: ToComputedValue::from_computed_value(&computed.right),
bottom: ToComputedValue::from_computed_value(&computed.bottom),
left: ToComputedValue::from_computed_value(&computed.left),
round: computed.round.as_ref().map(|r| ToComputedValue::from_computed_value(r)),
}
}
}
/// A shape source, for some reference box /// A shape source, for some reference box
/// ///
/// `clip-path` uses ShapeSource<BasicShape, GeometryBox>, /// `clip-path` uses ShapeSource<BasicShape, GeometryBox>,
/// `shape-outside` uses ShapeSource<BasicShape, ShapeBox> /// `shape-outside` uses ShapeSource<BasicShape, ShapeBox>
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, Debug, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)] #[allow(missing_docs)]
pub enum ShapeSource<B, T> { pub enum ShapeSource<B, T> {
@ -364,33 +267,3 @@ impl<B: Parse, T: Parse> Parse for ShapeSource<B, T> {
ref_box.map(|v| ShapeSource::Box(v)).ok_or(()) ref_box.map(|v| ShapeSource::Box(v)).ok_or(())
} }
} }
impl<B: ToComputedValue, T: ToComputedValue> ToComputedValue for ShapeSource<B, T> {
type ComputedValue = ShapeSource<B::ComputedValue, T::ComputedValue>;
#[inline]
fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue {
match *self {
ShapeSource::Url(ref url) => ShapeSource::Url(url.to_computed_value(cx)),
ShapeSource::Shape(ref shape, ref ref_box) => {
ShapeSource::Shape(shape.to_computed_value(cx),
ref_box.as_ref().map(|ref val| val.to_computed_value(cx)))
},
ShapeSource::Box(ref ref_box) => ShapeSource::Box(ref_box.to_computed_value(cx)),
ShapeSource::None => ShapeSource::None,
}
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
match *computed {
ShapeSource::Url(ref url) => ShapeSource::Url(SpecifiedUrl::from_computed_value(url)),
ShapeSource::Shape(ref shape, ref ref_box) => {
ShapeSource::Shape(ToComputedValue::from_computed_value(shape),
ref_box.as_ref().map(|val| ToComputedValue::from_computed_value(val)))
},
ShapeSource::Box(ref ref_box) => ShapeSource::Box(ToComputedValue::from_computed_value(ref_box)),
ShapeSource::None => ShapeSource::None,
}
}
}

View file

@ -10,13 +10,13 @@ use Atom;
use cssparser::serialize_identifier; use cssparser::serialize_identifier;
use std::fmt; use std::fmt;
use style_traits::{HasViewportPercentage, ToCss}; use style_traits::{HasViewportPercentage, ToCss};
use values::computed::{Context, ToComputedValue}; use values::computed::ComputedValueAsSpecified;
use values::specified::url::SpecifiedUrl; use values::specified::url::SpecifiedUrl;
/// An [image]. /// An [image].
/// ///
/// [image]: https://drafts.csswg.org/css-images/#image-values /// [image]: https://drafts.csswg.org/css-images/#image-values
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum Image<Gradient, ImageRect> { pub enum Image<Gradient, ImageRect> {
/// A `<url()>` image. /// A `<url()>` image.
@ -31,7 +31,7 @@ pub enum Image<Gradient, ImageRect> {
/// A CSS gradient. /// A CSS gradient.
/// https://drafts.csswg.org/css-images/#gradients /// https://drafts.csswg.org/css-images/#gradients
#[derive(Clone, Debug, HasViewportPercentage, PartialEq)] #[derive(Clone, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct Gradient<LineDirection, Length, LengthOrPercentage, Position, Color> { pub struct Gradient<LineDirection, Length, LengthOrPercentage, Position, Color> {
/// Gradients can be linear or radial. /// Gradients can be linear or radial.
@ -44,7 +44,7 @@ pub struct Gradient<LineDirection, Length, LengthOrPercentage, Position, Color>
pub compat_mode: CompatMode, pub compat_mode: CompatMode,
} }
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq)] #[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// Whether we used the modern notation or the compatibility `-webkit` prefix. /// Whether we used the modern notation or the compatibility `-webkit` prefix.
pub enum CompatMode { pub enum CompatMode {
@ -55,7 +55,7 @@ pub enum CompatMode {
} }
/// A gradient kind. /// A gradient kind.
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq)] #[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum GradientKind<LineDirection, Length, LengthOrPercentage, Position> { pub enum GradientKind<LineDirection, Length, LengthOrPercentage, Position> {
/// A linear gradient. /// A linear gradient.
@ -65,7 +65,7 @@ pub enum GradientKind<LineDirection, Length, LengthOrPercentage, Position> {
} }
/// A radial gradient's ending shape. /// A radial gradient's ending shape.
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq)] #[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum EndingShape<Length, LengthOrPercentage> { pub enum EndingShape<Length, LengthOrPercentage> {
/// A circular gradient. /// A circular gradient.
@ -75,7 +75,7 @@ pub enum EndingShape<Length, LengthOrPercentage> {
} }
/// A circle shape. /// A circle shape.
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq)] #[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum Circle<Length> { pub enum Circle<Length> {
/// A circle radius. /// A circle radius.
@ -85,7 +85,7 @@ pub enum Circle<Length> {
} }
/// An ellipse shape. /// An ellipse shape.
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq)] #[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum Ellipse<LengthOrPercentage> { pub enum Ellipse<LengthOrPercentage> {
/// An ellipse pair of radii. /// An ellipse pair of radii.
@ -104,10 +104,11 @@ define_css_keyword_enum!(ShapeExtent:
"cover" => Cover "cover" => Cover
); );
no_viewport_percentage!(ShapeExtent); no_viewport_percentage!(ShapeExtent);
impl ComputedValueAsSpecified for ShapeExtent {}
/// A gradient item. /// A gradient item.
/// https://drafts.csswg.org/css-images-4/#color-stop-syntax /// https://drafts.csswg.org/css-images-4/#color-stop-syntax
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq)] #[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum GradientItem<Color, LengthOrPercentage> { pub enum GradientItem<Color, LengthOrPercentage> {
/// A color stop. /// A color stop.
@ -118,7 +119,7 @@ pub enum GradientItem<Color, LengthOrPercentage> {
/// A color stop. /// A color stop.
/// https://drafts.csswg.org/css-images/#typedef-color-stop-list /// https://drafts.csswg.org/css-images/#typedef-color-stop-list
#[derive(Clone, Copy, HasViewportPercentage, PartialEq)] #[derive(Clone, Copy, HasViewportPercentage, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct ColorStop<Color, LengthOrPercentage> { pub struct ColorStop<Color, LengthOrPercentage> {
/// The color of this stop. /// The color of this stop.
@ -130,7 +131,7 @@ pub struct ColorStop<Color, LengthOrPercentage> {
/// Values for `moz-image-rect`. /// Values for `moz-image-rect`.
/// ///
/// `-moz-image-rect(<uri>, top, right, bottom, left);` /// `-moz-image-rect(<uri>, top, right, bottom, left);`
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, Debug, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)] #[allow(missing_docs)]
pub struct ImageRect<NumberOrPercentage> { pub struct ImageRect<NumberOrPercentage> {
@ -186,47 +187,6 @@ impl<G, R> HasViewportPercentage for Image<G, R>
} }
} }
impl<G, R> ToComputedValue for Image<G, R>
where G: ToComputedValue, R: ToComputedValue,
{
type ComputedValue = Image<<G as ToComputedValue>::ComputedValue,
<R as ToComputedValue>::ComputedValue>;
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
match *self {
Image::Url(ref url) => {
Image::Url(url.clone())
},
Image::Gradient(ref gradient) => {
Image::Gradient(gradient.to_computed_value(context))
},
Image::Rect(ref rect) => {
Image::Rect(rect.to_computed_value(context))
},
Image::Element(ref selector) => {
Image::Element(selector.clone())
}
}
}
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
match *computed {
Image::Url(ref url) => {
Image::Url(url.clone())
},
Image::Gradient(ref gradient) => {
Image::Gradient(ToComputedValue::from_computed_value(gradient))
},
Image::Rect(ref rect) => {
Image::Rect(ToComputedValue::from_computed_value(rect))
},
Image::Element(ref selector) => {
Image::Element(selector.clone())
},
}
}
}
impl<D, L, LoP, P, C> ToCss for Gradient<D, L, LoP, P, C> impl<D, L, LoP, P, C> ToCss for Gradient<D, L, LoP, P, C>
where D: LineDirection, L: ToCss, LoP: ToCss, P: ToCss, C: ToCss, where D: LineDirection, L: ToCss, LoP: ToCss, P: ToCss, C: ToCss,
{ {
@ -281,38 +241,6 @@ impl<D, L, LoP, P, C> ToCss for Gradient<D, L, LoP, P, C>
} }
} }
impl<D, L, LoP, P, C> ToComputedValue for Gradient<D, L, LoP, P, C>
where D: ToComputedValue,
L: ToComputedValue,
LoP: ToComputedValue,
P: ToComputedValue,
C: ToComputedValue,
{
type ComputedValue = Gradient<<D as ToComputedValue>::ComputedValue,
<L as ToComputedValue>::ComputedValue,
<LoP as ToComputedValue>::ComputedValue,
<P as ToComputedValue>::ComputedValue,
<C as ToComputedValue>::ComputedValue>;
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
Gradient {
kind: self.kind.to_computed_value(context),
items: self.items.iter().map(|s| s.to_computed_value(context)).collect(),
repeating: self.repeating,
compat_mode: self.compat_mode,
}
}
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
Gradient {
kind: ToComputedValue::from_computed_value(&computed.kind),
items: computed.items.iter().map(ToComputedValue::from_computed_value).collect(),
repeating: computed.repeating,
compat_mode: computed.compat_mode,
}
}
}
impl<D, L, LoP, P> GradientKind<D, L, LoP, P> { impl<D, L, LoP, P> GradientKind<D, L, LoP, P> {
fn label(&self) -> &str { fn label(&self) -> &str {
match *self { match *self {
@ -322,43 +250,6 @@ impl<D, L, LoP, P> GradientKind<D, L, LoP, P> {
} }
} }
impl<D, L, LoP, P> ToComputedValue for GradientKind<D, L, LoP, P>
where D: ToComputedValue,
L: ToComputedValue,
LoP: ToComputedValue,
P: ToComputedValue,
{
type ComputedValue = GradientKind<<D as ToComputedValue>::ComputedValue,
<L as ToComputedValue>::ComputedValue,
<LoP as ToComputedValue>::ComputedValue,
<P as ToComputedValue>::ComputedValue>;
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
match *self {
GradientKind::Linear(ref direction) => {
GradientKind::Linear(direction.to_computed_value(context))
},
GradientKind::Radial(ref shape, ref position) => {
GradientKind::Radial(shape.to_computed_value(context), position.to_computed_value(context))
},
}
}
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
match *computed {
GradientKind::Linear(ref direction) => {
GradientKind::Linear(ToComputedValue::from_computed_value(direction))
},
GradientKind::Radial(ref shape, ref position) => {
GradientKind::Radial(
ToComputedValue::from_computed_value(shape),
ToComputedValue::from_computed_value(position),
)
}
}
}
}
/// The direction of a linear gradient. /// The direction of a linear gradient.
pub trait LineDirection { pub trait LineDirection {
/// Whether this direction points towards, and thus can be omitted. /// Whether this direction points towards, and thus can be omitted.
@ -397,53 +288,6 @@ impl<L, LoP> ToCss for EndingShape<L, LoP>
} }
} }
impl<L, LoP> ToComputedValue for EndingShape<L, LoP>
where L: ToComputedValue, LoP: ToComputedValue,
{
type ComputedValue = EndingShape<<L as ToComputedValue>::ComputedValue,
<LoP as ToComputedValue>::ComputedValue>;
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
match *self {
EndingShape::Circle(Circle::Radius(ref length)) => {
EndingShape::Circle(Circle::Radius(length.to_computed_value(context)))
},
EndingShape::Circle(Circle::Extent(extent)) => {
EndingShape::Circle(Circle::Extent(extent))
},
EndingShape::Ellipse(Ellipse::Radii(ref x, ref y)) => {
EndingShape::Ellipse(Ellipse::Radii(
x.to_computed_value(context),
y.to_computed_value(context),
))
},
EndingShape::Ellipse(Ellipse::Extent(extent)) => {
EndingShape::Ellipse(Ellipse::Extent(extent))
},
}
}
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
match *computed {
EndingShape::Circle(Circle::Radius(ref length)) => {
EndingShape::Circle(Circle::Radius(ToComputedValue::from_computed_value(length)))
},
EndingShape::Circle(Circle::Extent(extent)) => {
EndingShape::Circle(Circle::Extent(extent))
},
EndingShape::Ellipse(Ellipse::Radii(ref x, ref y)) => {
EndingShape::Ellipse(Ellipse::Radii(
ToComputedValue::from_computed_value(x),
ToComputedValue::from_computed_value(y),
))
},
EndingShape::Ellipse(Ellipse::Extent(extent)) => {
EndingShape::Ellipse(Ellipse::Extent(extent))
},
}
}
}
impl<C, L> ToCss for GradientItem<C, L> impl<C, L> ToCss for GradientItem<C, L>
where C: ToCss, L: ToCss, where C: ToCss, L: ToCss,
{ {
@ -455,35 +299,6 @@ impl<C, L> ToCss for GradientItem<C, L>
} }
} }
impl<C, L> ToComputedValue for GradientItem<C, L>
where C: ToComputedValue, L: ToComputedValue,
{
type ComputedValue = GradientItem<<C as ToComputedValue>::ComputedValue,
<L as ToComputedValue>::ComputedValue>;
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
match *self {
GradientItem::ColorStop(ref stop) => {
GradientItem::ColorStop(stop.to_computed_value(context))
},
GradientItem::InterpolationHint(ref hint) => {
GradientItem::InterpolationHint(hint.to_computed_value(context))
},
}
}
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
match *computed {
GradientItem::ColorStop(ref stop) => {
GradientItem::ColorStop(ToComputedValue::from_computed_value(stop))
},
GradientItem::InterpolationHint(ref hint) => {
GradientItem::InterpolationHint(ToComputedValue::from_computed_value(hint))
},
}
}
}
impl<C, L> fmt::Debug for ColorStop<C, L> impl<C, L> fmt::Debug for ColorStop<C, L>
where C: fmt::Debug, L: fmt::Debug, where C: fmt::Debug, L: fmt::Debug,
{ {
@ -509,27 +324,6 @@ impl<C, L> ToCss for ColorStop<C, L>
} }
} }
impl<C, L> ToComputedValue for ColorStop<C, L>
where C: ToComputedValue, L: ToComputedValue,
{
type ComputedValue = ColorStop<<C as ToComputedValue>::ComputedValue,
<L as ToComputedValue>::ComputedValue>;
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
ColorStop {
color: self.color.to_computed_value(context),
position: self.position.as_ref().map(|p| p.to_computed_value(context)),
}
}
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
ColorStop {
color: ToComputedValue::from_computed_value(&computed.color),
position: computed.position.as_ref().map(ToComputedValue::from_computed_value),
}
}
}
impl<C> ToCss for ImageRect<C> impl<C> ToCss for ImageRect<C>
where C: ToCss, where C: ToCss,
{ {
@ -547,29 +341,3 @@ impl<C> ToCss for ImageRect<C>
dest.write_str(")") dest.write_str(")")
} }
} }
impl<C> ToComputedValue for ImageRect<C>
where C: ToComputedValue,
{
type ComputedValue = ImageRect<<C as ToComputedValue>::ComputedValue>;
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
ImageRect {
url: self.url.to_computed_value(context),
top: self.top.to_computed_value(context),
right: self.right.to_computed_value(context),
bottom: self.bottom.to_computed_value(context),
left: self.left.to_computed_value(context),
}
}
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
ImageRect {
url: ToComputedValue::from_computed_value(&computed.url),
top: ToComputedValue::from_computed_value(&computed.top),
right: ToComputedValue::from_computed_value(&computed.right),
bottom: ToComputedValue::from_computed_value(&computed.bottom),
left: ToComputedValue::from_computed_value(&computed.left),
}
}
}

View file

@ -12,7 +12,6 @@ use parser::{Parse, ParserContext};
use std::fmt; use std::fmt;
use style_traits::{HasViewportPercentage, ToCss}; use style_traits::{HasViewportPercentage, ToCss};
use super::CustomIdent; use super::CustomIdent;
use super::computed::{Context, ToComputedValue};
pub use self::basic_shape::serialize_radius_values; pub use self::basic_shape::serialize_radius_values;
@ -20,9 +19,9 @@ pub mod basic_shape;
pub mod image; pub mod image;
pub mod position; pub mod position;
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, Debug, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// A type for representing CSS `widthh` and `height` values. /// A type for representing CSS `width` and `height` values.
pub struct BorderRadiusSize<L>(pub Size2D<L>); pub struct BorderRadiusSize<L>(pub Size2D<L>);
impl<L> HasViewportPercentage for BorderRadiusSize<L> { impl<L> HasViewportPercentage for BorderRadiusSize<L> {
@ -61,24 +60,6 @@ impl<L: ToCss> ToCss for BorderRadiusSize<L> {
} }
} }
impl<L: ToComputedValue> ToComputedValue for BorderRadiusSize<L> {
type ComputedValue = BorderRadiusSize<L::ComputedValue>;
#[inline]
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
let w = self.0.width.to_computed_value(context);
let h = self.0.height.to_computed_value(context);
BorderRadiusSize(Size2D::new(w, h))
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
let w = ToComputedValue::from_computed_value(&computed.0.width);
let h = ToComputedValue::from_computed_value(&computed.0.height);
BorderRadiusSize(Size2D::new(w, h))
}
}
/// https://drafts.csswg.org/css-counter-styles/#typedef-counter-style /// https://drafts.csswg.org/css-counter-styles/#typedef-counter-style
/// ///
/// Since wherever <counter-style> is used, 'none' is a valid value as /// Since wherever <counter-style> is used, 'none' is a valid value as

View file

@ -5,9 +5,7 @@
//! Generic types for CSS handling of specified and computed values of //! Generic types for CSS handling of specified and computed values of
//! [`position`](https://drafts.csswg.org/css-backgrounds-3/#position) //! [`position`](https://drafts.csswg.org/css-backgrounds-3/#position)
use values::computed::{Context, ToComputedValue}; #[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)]
#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
/// A generic type for representing a CSS [position](https://drafts.csswg.org/css-values/#position). /// A generic type for representing a CSS [position](https://drafts.csswg.org/css-values/#position).
pub struct Position<H, V> { pub struct Position<H, V> {
@ -26,24 +24,3 @@ impl<H, V> Position<H, V> {
} }
} }
} }
impl<H: ToComputedValue, V: ToComputedValue> ToComputedValue for Position<H, V> {
type ComputedValue = Position<<H as ToComputedValue>::ComputedValue,
<V as ToComputedValue>::ComputedValue>;
#[inline]
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
Position {
horizontal: self.horizontal.to_computed_value(context),
vertical: self.vertical.to_computed_value(context),
}
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
Self {
horizontal: ToComputedValue::from_computed_value(&computed.horizontal),
vertical: ToComputedValue::from_computed_value(&computed.vertical),
}
}
}

View file

@ -10,9 +10,16 @@ extern crate synstructure;
use proc_macro::TokenStream; use proc_macro::TokenStream;
mod has_viewport_percentage; mod has_viewport_percentage;
mod to_computed_value;
#[proc_macro_derive(HasViewportPercentage)] #[proc_macro_derive(HasViewportPercentage)]
pub fn derive_has_viewport_percentage(stream: TokenStream) -> TokenStream { pub fn derive_has_viewport_percentage(stream: TokenStream) -> TokenStream {
let input = syn::parse_derive_input(&stream.to_string()).unwrap(); let input = syn::parse_derive_input(&stream.to_string()).unwrap();
has_viewport_percentage::derive(input).to_string().parse().unwrap() has_viewport_percentage::derive(input).to_string().parse().unwrap()
} }
#[proc_macro_derive(ToComputedValue)]
pub fn derive_to_computed_value(stream: TokenStream) -> TokenStream {
let input = syn::parse_derive_input(&stream.to_string()).unwrap();
to_computed_value::derive(input).to_string().parse().unwrap()
}

View file

@ -0,0 +1,142 @@
/* 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 quote;
use syn;
use synstructure;
pub fn derive(input: syn::DeriveInput) -> quote::Tokens {
let name = &input.ident;
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let mut where_clause = where_clause.clone();
for param in &input.generics.ty_params {
where_clause.predicates.push(where_predicate(syn::Ty::Path(None, param.ident.clone().into()), None));
}
let computed_value_type = syn::Path::from(syn::PathSegment {
ident: name.clone(),
parameters: syn::PathParameters::AngleBracketed(syn::AngleBracketedParameterData {
lifetimes: input.generics.lifetimes.iter().map(|l| {
l.lifetime.clone()
}).collect(),
types: input.generics.ty_params.iter().map(|ty| {
syn::Ty::Path(
Some(syn::QSelf {
ty: Box::new(syn::Ty::Path(None, ty.ident.clone().into())),
position: 3,
}),
syn::Path {
global: true,
segments: vec![
"values".into(),
"computed".into(),
"ToComputedValue".into(),
"ComputedValue".into(),
],
},
)
}).collect(),
.. Default::default()
}),
});
let to_body = match_body(&input, |field| {
quote!(::values::computed::ToComputedValue::to_computed_value(#field, context))
});
let from_body = match_body(&input, |field| {
quote!(::values::computed::ToComputedValue::from_computed_value(#field))
});
quote! {
impl #impl_generics ::values::computed::ToComputedValue for #name #ty_generics #where_clause {
type ComputedValue = #computed_value_type;
#[allow(unused_variables)]
#[inline]
fn to_computed_value(&self, context: &::values::computed::Context) -> Self::ComputedValue {
match *self {
#to_body
}
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
match *computed {
#from_body
}
}
}
}
}
fn match_body<F>(input: &syn::DeriveInput, f: F) -> quote::Tokens
where F: Fn(&synstructure::BindingInfo) -> quote::Tokens,
{
let by_ref = synstructure::BindStyle::Ref.into();
let by_value = synstructure::BindStyle::Move.into();
synstructure::each_variant(&input, &by_ref, |fields, variant| {
let name = if let syn::Body::Enum(_) = input.body {
format!("{}::{}", input.ident, variant.ident).into()
} else {
variant.ident.clone()
};
let (computed_value, computed_fields) = synstructure::match_pattern(&name, &variant.data, &by_value);
let fields_pairs = fields.iter().zip(computed_fields.iter());
let mut computations = quote!();
computations.append_all(fields_pairs.map(|(field, computed_field)| {
let expr = f(field);
quote!(let #computed_field = #expr;)
}));
Some(quote!(
#computations
#computed_value
))
})
}
/// `#ty: ::values::computed::ToComputedValue<ComputedValue = #computed_value,>`
fn where_predicate(ty: syn::Ty, computed_value: Option<syn::Ty>) -> syn::WherePredicate {
syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate {
bound_lifetimes: vec![],
bounded_ty: ty,
bounds: vec![syn::TyParamBound::Trait(
syn::PolyTraitRef {
bound_lifetimes: vec![],
trait_ref: trait_ref(computed_value),
},
syn::TraitBoundModifier::None
)],
})
}
/// `::values::computed::ToComputedValue<ComputedValue = #computed_value,>`
fn trait_ref(computed_value: Option<syn::Ty>) -> syn::Path {
syn::Path {
global: true,
segments: vec![
"values".into(),
"computed".into(),
syn::PathSegment {
ident: "ToComputedValue".into(),
parameters: syn::PathParameters::AngleBracketed(
syn::AngleBracketedParameterData {
bindings: trait_bindings(computed_value),
.. Default::default()
}
),
}
],
}
}
/// `ComputedValue = #computed_value,`
fn trait_bindings(computed_value: Option<syn::Ty>) -> Vec<syn::TypeBinding> {
computed_value.into_iter().map(|ty| {
syn::TypeBinding {
ident: "ComputedValue".into(),
ty: ty,
}
}).collect()
}