aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/layout/display_list_builder.rs25
-rw-r--r--components/style/gecko/conversions.rs13
-rw-r--r--components/style/values/computed/image.rs322
-rw-r--r--components/style/values/generics/image.rs362
-rw-r--r--components/style/values/generics/mod.rs1
-rw-r--r--components/style/values/specified/image.rs162
6 files changed, 427 insertions, 458 deletions
diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs
index 5f9a783c896..5ecae6d66de 100644
--- a/components/layout/display_list_builder.rs
+++ b/components/layout/display_list_builder.rs
@@ -57,11 +57,12 @@ use style::properties::{self, ServoComputedValues};
use style::properties::longhands::border_image_repeat::computed_value::RepeatKeyword;
use style::properties::style_structs;
use style::servo::restyle_damage::REPAINT;
-use style::values::{Either, RGBA, computed};
+use style::values::{Either, RGBA};
use style::values::computed::{AngleOrCorner, Gradient, GradientItem, GradientKind, LengthOrPercentage};
use style::values::computed::{LengthOrPercentageOrAuto, LengthOrKeyword, LengthOrPercentageOrKeyword};
use style::values::computed::{NumberOrPercentage, Position};
use style::values::computed::image::{EndingShape, SizeKeyword};
+use style::values::generics::image::{GradientItem as GenericGradientItem, Image};
use style::values::specified::{HorizontalDirection, VerticalDirection};
use style_traits::CSSPixel;
use style_traits::cursor::Cursor;
@@ -610,7 +611,7 @@ fn convert_gradient_stops(gradient_items: &[GradientItem],
// Only keep the color stops, discard the color interpolation hints.
let mut stop_items = gradient_items.iter().filter_map(|item| {
match *item {
- GradientItem::ColorStop(ref stop) => Some(*stop),
+ GenericGradientItem::ColorStop(ref stop) => Some(*stop),
_ => None,
}
}).collect::<Vec<_>>();
@@ -855,7 +856,7 @@ impl FragmentDisplayListBuilding for Fragment {
for (i, background_image) in background.background_image.0.iter().enumerate().rev() {
match background_image.0 {
None => {}
- Some(computed::Image::Gradient(ref gradient)) => {
+ Some(Image::Gradient(ref gradient)) => {
self.build_display_list_for_background_gradient(state,
display_list_section,
&absolute_bounds,
@@ -864,7 +865,7 @@ impl FragmentDisplayListBuilding for Fragment {
gradient,
style);
}
- Some(computed::Image::Url(ref image_url)) => {
+ Some(Image::Url(ref image_url)) => {
if let Some(url) = image_url.url() {
self.build_display_list_for_background_image(state,
style,
@@ -875,10 +876,10 @@ impl FragmentDisplayListBuilding for Fragment {
i);
}
}
- Some(computed::Image::ImageRect(_)) => {
+ Some(Image::Rect(_)) => {
// TODO: Implement `-moz-image-rect`
}
- Some(computed::Image::Element(_)) => {
+ Some(Image::Element(_)) => {
// TODO: Implement `-moz-element`
}
}
@@ -1221,7 +1222,7 @@ impl FragmentDisplayListBuilding for Fragment {
style.get_cursor(Cursor::Default),
display_list_section);
- let display_item = match gradient.gradient_kind {
+ let display_item = match gradient.kind {
GradientKind::Linear(ref angle_or_corner) => {
let gradient = self.convert_linear_gradient(&bounds,
&gradient.items[..],
@@ -1357,8 +1358,8 @@ impl FragmentDisplayListBuilding for Fragment {
}),
}));
}
- Some(computed::Image::Gradient(ref gradient)) => {
- match gradient.gradient_kind {
+ Some(Image::Gradient(ref gradient)) => {
+ match gradient.kind {
GradientKind::Linear(angle_or_corner) => {
let grad = self.convert_linear_gradient(&bounds,
&gradient.items[..],
@@ -1398,13 +1399,13 @@ impl FragmentDisplayListBuilding for Fragment {
}
}
}
- Some(computed::Image::ImageRect(..)) => {
+ Some(Image::Rect(..)) => {
// TODO: Handle border-image with `-moz-image-rect`.
}
- Some(computed::Image::Element(..)) => {
+ Some(Image::Element(..)) => {
// TODO: Handle border-image with `-moz-element`.
}
- Some(computed::Image::Url(ref image_url)) => {
+ Some(Image::Url(ref image_url)) => {
if let Some(url) = image_url.url() {
let webrender_image = state.layout_context
.get_webrender_image_for_url(self.node,
diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs
index bb299a74db1..d3d74234c35 100644
--- a/components/style/gecko/conversions.rs
+++ b/components/style/gecko/conversions.rs
@@ -16,8 +16,9 @@ use gecko_bindings::structs::{nsCSSUnit, nsStyleCoord_CalcValue, nsStyleImage};
use gecko_bindings::structs::{nsresult, SheetType};
use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordDataMut};
use stylesheets::{Origin, RulesMutateError};
-use values::computed::{Angle, CalcLengthOrPercentage, Gradient, GradientItem, Image};
+use values::computed::{Angle, CalcLengthOrPercentage, Gradient, Image};
use values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
+use values::generics::image::{GradientItem, Image as GenericImage};
impl From<CalcLengthOrPercentage> for nsStyleCoord_CalcValue {
fn from(other: CalcLengthOrPercentage) -> nsStyleCoord_CalcValue {
@@ -138,10 +139,10 @@ impl nsStyleImage {
/// Set a given Servo `Image` value into this `nsStyleImage`.
pub fn set(&mut self, image: Image, cacheable: &mut bool) {
match image {
- Image::Gradient(gradient) => {
+ GenericImage::Gradient(gradient) => {
self.set_gradient(gradient)
},
- Image::Url(ref url) => {
+ GenericImage::Url(ref url) => {
unsafe {
Gecko_SetUrlImageValue(self, url.for_ffi());
// We unfortunately must make any url() value uncacheable, since
@@ -154,7 +155,7 @@ impl nsStyleImage {
*cacheable = false;
}
},
- Image::ImageRect(ref image_rect) => {
+ GenericImage::Rect(ref image_rect) => {
unsafe {
Gecko_SetUrlImageValue(self, image_rect.url.for_ffi());
Gecko_InitializeImageCropRect(self);
@@ -176,7 +177,7 @@ impl nsStyleImage {
image_rect.left.to_gecko_style_coord(&mut rect.data_at_mut(3));
}
}
- Image::Element(ref element) => {
+ GenericImage::Element(ref element) => {
unsafe {
Gecko_SetImageElement(self, element.as_ptr());
}
@@ -201,7 +202,7 @@ impl nsStyleImage {
return;
}
- let gecko_gradient = match gradient.gradient_kind {
+ let gecko_gradient = match gradient.kind {
GradientKind::Linear(angle_or_corner) => {
let gecko_gradient = unsafe {
Gecko_CreateGradient(NS_STYLE_GRADIENT_SHAPE_LINEAR as u8,
diff --git a/components/style/values/computed/image.rs b/components/style/values/computed/image.rs
index 01a6106f3d3..5140650d80e 100644
--- a/components/style/values/computed/image.rs
+++ b/components/style/values/computed/image.rs
@@ -7,128 +7,35 @@
//!
//! [image]: https://drafts.csswg.org/css-images/#image-values
-use Atom;
-use cssparser::{Color as CSSColor, serialize_identifier};
+use cssparser::Color as CSSColor;
use std::f32::consts::PI;
use std::fmt;
use style_traits::ToCss;
+use values::generics::image::{CompatMode, ColorStop as GenericColorStop};
+use values::generics::image::{Gradient as GenericGradient, GradientItem as GenericGradientItem};
+use values::generics::image::{Image as GenericImage, ImageRect as GenericImageRect};
use values::computed::{Angle, Context, Length, LengthOrPercentage, NumberOrPercentage, ToComputedValue};
use values::computed::position::Position;
use values::specified::{self, HorizontalDirection, VerticalDirection};
-use values::specified::image::CompatMode;
-use values::specified::url::SpecifiedUrl;
pub use values::specified::SizeKeyword;
-impl ToComputedValue for specified::Image {
- type ComputedValue = Image;
-
- #[inline]
- fn to_computed_value(&self, context: &Context) -> Image {
- match *self {
- specified::Image::Url(ref url_value) => {
- Image::Url(url_value.clone())
- },
- specified::Image::Gradient(ref gradient) => {
- Image::Gradient(gradient.to_computed_value(context))
- },
- specified::Image::ImageRect(ref image_rect) => {
- Image::ImageRect(image_rect.to_computed_value(context))
- },
- specified::Image::Element(ref selector) => {
- Image::Element(selector.clone())
- }
- }
- }
-
- #[inline]
- fn from_computed_value(computed: &Image) -> Self {
- match *computed {
- Image::Url(ref url_value) => {
- specified::Image::Url(url_value.clone())
- },
- Image::Gradient(ref linear_gradient) => {
- specified::Image::Gradient(
- ToComputedValue::from_computed_value(linear_gradient)
- )
- },
- Image::ImageRect(ref image_rect) => {
- specified::Image::ImageRect(
- ToComputedValue::from_computed_value(image_rect)
- )
- },
- Image::Element(ref selector) => {
- specified::Image::Element(selector.clone())
- },
- }
- }
-}
-
/// Computed values for an image according to CSS-IMAGES.
/// https://drafts.csswg.org/css-images/#image-values
-#[derive(Clone, PartialEq)]
-#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-#[allow(missing_docs)]
-pub enum Image {
- Url(SpecifiedUrl),
- Gradient(Gradient),
- ImageRect(ImageRect),
- Element(Atom),
-}
-
-impl fmt::Debug for Image {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- Image::Url(ref url) => url.to_css(f),
- Image::Gradient(ref grad) => {
- if grad.repeating {
- let _ = write!(f, "repeating-");
- }
- match grad.gradient_kind {
- GradientKind::Linear(_) => write!(f, "linear-gradient({:?})", grad),
- GradientKind::Radial(_, _) => write!(f, "radial-gradient({:?})", grad),
- }
- },
- Image::ImageRect(ref image_rect) => write!(f, "{:?}", image_rect),
- Image::Element(ref selector) => {
- f.write_str("-moz-element(#")?;
- serialize_identifier(&*selector.to_string(), f)?;
- f.write_str(")")
- },
- }
- }
-}
-
-impl ToCss for Image {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- match *self {
- Image::Url(ref url) => url.to_css(dest),
- Image::Gradient(ref gradient) => gradient.to_css(dest),
- Image::ImageRect(ref image_rect) => image_rect.to_css(dest),
- Image::Element(ref selector) => {
- dest.write_str("-moz-element(#")?;
- // FIXME: We should get rid of these intermediate strings.
- serialize_identifier(&*selector.to_string(), dest)?;
- dest.write_str(")")
- },
- }
- }
-}
+pub type Image = GenericImage<Gradient, NumberOrPercentage>;
/// Computed values for a CSS gradient.
/// https://drafts.csswg.org/css-images/#gradients
-#[derive(Clone, PartialEq)]
-#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-pub struct Gradient {
- /// The color stops.
- pub items: Vec<GradientItem>,
- /// True if this is a repeating gradient.
- pub repeating: bool,
- /// Gradient kind can be linear or radial.
- pub gradient_kind: GradientKind,
- /// Compatibility mode.
- pub compat_mode: CompatMode,
-}
+pub type Gradient = GenericGradient<GradientKind, CSSColor, LengthOrPercentage>;
+
+/// A computed gradient item.
+pub type GradientItem = GenericGradientItem<CSSColor, LengthOrPercentage>;
+
+/// A computed color stop.
+pub type ColorStop = GenericColorStop<CSSColor, LengthOrPercentage>;
+
+/// Computed values for ImageRect.
+pub type ImageRect = GenericImageRect<NumberOrPercentage>;
impl ToCss for Gradient {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
@@ -138,7 +45,7 @@ impl ToCss for Gradient {
if self.repeating {
try!(dest.write_str("repeating-"));
}
- match self.gradient_kind {
+ match self.kind {
GradientKind::Linear(angle_or_corner) => {
try!(dest.write_str("linear-gradient("));
try!(angle_or_corner.to_css(dest, self.compat_mode));
@@ -161,7 +68,7 @@ impl ToCss for Gradient {
impl fmt::Debug for Gradient {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match self.gradient_kind {
+ match self.kind {
GradientKind::Linear(angle_or_corner) => {
let _ = write!(f, "{:?}", angle_or_corner);
},
@@ -177,42 +84,6 @@ impl fmt::Debug for Gradient {
}
}
-impl ToComputedValue for specified::Gradient {
- type ComputedValue = Gradient;
-
- #[inline]
- fn to_computed_value(&self, context: &Context) -> Gradient {
- let specified::Gradient {
- ref items,
- repeating,
- ref gradient_kind,
- compat_mode,
- } = *self;
- Gradient {
- items: items.iter().map(|s| s.to_computed_value(context)).collect(),
- repeating: repeating,
- gradient_kind: gradient_kind.to_computed_value(context),
- compat_mode: compat_mode,
- }
- }
-
- #[inline]
- fn from_computed_value(computed: &Gradient) -> Self {
- let Gradient {
- ref items,
- repeating,
- ref gradient_kind,
- compat_mode,
- } = *computed;
- specified::Gradient {
- items: items.iter().map(ToComputedValue::from_computed_value).collect(),
- repeating: repeating,
- gradient_kind: ToComputedValue::from_computed_value(gradient_kind),
- compat_mode: compat_mode,
- }
- }
-}
-
/// Computed values for CSS linear or radial gradients.
/// https://drafts.csswg.org/css-images/#gradients
#[derive(Clone, PartialEq)]
@@ -252,112 +123,6 @@ impl ToComputedValue for specified::GradientKind {
}
}
-/// Specified values for color stops and interpolation hints.
-#[derive(Clone, PartialEq, Debug)]
-#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-pub enum GradientItem {
- /// A color stop.
- ColorStop(ColorStop),
- /// An interpolation hint.
- InterpolationHint(LengthOrPercentage),
-}
-
-impl ToCss for GradientItem {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- match *self {
- GradientItem::ColorStop(stop) => stop.to_css(dest),
- GradientItem::InterpolationHint(hint) => hint.to_css(dest),
- }
- }
-}
-
-impl ToComputedValue for specified::GradientItem {
- type ComputedValue = GradientItem;
-
- #[inline]
- fn to_computed_value(&self, context: &Context) -> GradientItem {
- match *self {
- specified::GradientItem::ColorStop(ref stop) => {
- GradientItem::ColorStop(stop.to_computed_value(context))
- },
- specified::GradientItem::InterpolationHint(ref hint) => {
- GradientItem::InterpolationHint(hint.to_computed_value(context))
- },
- }
- }
-
- #[inline]
- fn from_computed_value(computed: &GradientItem) -> Self {
- match *computed {
- GradientItem::ColorStop(ref stop) => {
- specified::GradientItem::ColorStop(ToComputedValue::from_computed_value(stop))
- },
- GradientItem::InterpolationHint(ref hint) => {
- specified::GradientItem::InterpolationHint(ToComputedValue::from_computed_value(hint))
- },
- }
- }
-}
-
-/// Computed values for one color stop in a linear gradient.
-/// https://drafts.csswg.org/css-images/#typedef-color-stop-list
-#[derive(Clone, PartialEq, Copy)]
-#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-pub struct ColorStop {
- /// The color of this stop.
- pub color: CSSColor,
-
- /// The position of this stop. If not specified, this stop is placed halfway between the
- /// point that precedes it and the point that follows it per CSS-IMAGES § 3.4.
- pub position: Option<LengthOrPercentage>,
-}
-
-impl ToCss for ColorStop {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- try!(self.color.to_css(dest));
- if let Some(position) = self.position {
- try!(dest.write_str(" "));
- try!(position.to_css(dest));
- }
- Ok(())
- }
-}
-
-impl fmt::Debug for ColorStop {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let _ = write!(f, "{:?}", self.color);
- self.position.map(|pos| {
- let _ = write!(f, " {:?}", pos);
- });
- Ok(())
- }
-}
-
-impl ToComputedValue for specified::ColorStop {
- type ComputedValue = ColorStop;
-
- #[inline]
- fn to_computed_value(&self, context: &Context) -> ColorStop {
- ColorStop {
- color: self.color.to_computed_value(context),
- position: match self.position {
- None => None,
- Some(ref value) => Some(value.to_computed_value(context)),
- },
- }
- }
- #[inline]
- fn from_computed_value(computed: &ColorStop) -> Self {
- specified::ColorStop {
- color: ToComputedValue::from_computed_value(&computed.color),
- position: match computed.position {
- None => None,
- Some(value) => Some(ToComputedValue::from_computed_value(&value)),
- },
- }
- }
-}
-
/// Computed values for EndingShape
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-ending-shape
#[derive(Clone, PartialEq)]
@@ -425,59 +190,6 @@ impl ToComputedValue for specified::GradientEndingShape {
}
}
-/// Computed values for ImageRect
-#[derive(Clone, PartialEq, Debug)]
-#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-#[allow(missing_docs)]
-pub struct ImageRect {
- pub url: SpecifiedUrl,
- pub top: NumberOrPercentage,
- pub bottom: NumberOrPercentage,
- pub right: NumberOrPercentage,
- pub left: NumberOrPercentage,
-}
-
-impl ToCss for ImageRect {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- dest.write_str("-moz-image-rect(")?;
- self.url.to_css(dest)?;
- dest.write_str(", ")?;
- self.top.to_css(dest)?;
- dest.write_str(", ")?;
- self.right.to_css(dest)?;
- dest.write_str(", ")?;
- self.bottom.to_css(dest)?;
- dest.write_str(", ")?;
- self.left.to_css(dest)?;
- dest.write_str(")")
- }
-}
-
-impl ToComputedValue for specified::ImageRect {
- type ComputedValue = ImageRect;
-
- #[inline]
- fn to_computed_value(&self, context: &Context) -> ImageRect {
- 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),
- }
- }
- #[inline]
- fn from_computed_value(computed: &ImageRect) -> Self {
- specified::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),
- }
- }
-}
-
/// https://drafts.csswg.org/css-images/#valdef-radial-gradient-size
#[derive(Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
diff --git a/components/style/values/generics/image.rs b/components/style/values/generics/image.rs
new file mode 100644
index 00000000000..de644215acc
--- /dev/null
+++ b/components/style/values/generics/image.rs
@@ -0,0 +1,362 @@
+/* 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 the handling of [images].
+//!
+//! [images]: https://drafts.csswg.org/css-images/#image-values
+
+use Atom;
+use cssparser::serialize_identifier;
+use std::fmt;
+use style_traits::ToCss;
+use values::HasViewportPercentage;
+use values::computed::{Context, ToComputedValue};
+use values::specified::url::SpecifiedUrl;
+
+/// An [image].
+///
+/// [image]: https://drafts.csswg.org/css-images/#image-values
+#[derive(Clone, PartialEq)]
+#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+pub enum Image<G, N> {
+ /// A `<url()>` image.
+ Url(SpecifiedUrl),
+ /// A `<gradient>` image.
+ Gradient(G),
+ /// A `-moz-image-rect` image
+ Rect(ImageRect<N>),
+ /// A `-moz-element(# <element-id>)`
+ Element(Atom),
+}
+
+/// A CSS gradient.
+/// https://drafts.csswg.org/css-images/#gradients
+#[derive(Clone, PartialEq, Debug)]
+#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+pub struct Gradient<K, C, L> {
+ /// Gradients can be linear or radial.
+ pub kind: K,
+ /// The color stops and interpolation hints.
+ pub items: Vec<GradientItem<C, L>>,
+ /// True if this is a repeating gradient.
+ pub repeating: bool,
+ /// Compatibility mode.
+ pub compat_mode: CompatMode,
+}
+
+#[derive(Clone, Copy, PartialEq, Debug)]
+#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+/// Whether we used the modern notation or the compatibility `-webkit` prefix.
+pub enum CompatMode {
+ /// Modern syntax.
+ Modern,
+ /// `-webkit` prefix.
+ WebKit,
+}
+
+/// A gradient item.
+/// https://drafts.csswg.org/css-images-4/#color-stop-syntax
+#[derive(Clone, Copy, PartialEq, Debug)]
+#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+pub enum GradientItem<C, L> {
+ /// A color stop.
+ ColorStop(ColorStop<C, L>),
+ /// An interpolation hint.
+ InterpolationHint(L),
+}
+
+/// A color stop.
+/// https://drafts.csswg.org/css-images/#typedef-color-stop-list
+#[derive(Clone, Copy, PartialEq)]
+#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+pub struct ColorStop<C, L> {
+ /// The color of this stop.
+ pub color: C,
+ /// The position of this stop.
+ pub position: Option<L>,
+}
+
+/// Values for `moz-image-rect`.
+///
+/// `-moz-image-rect(<uri>, top, right, bottom, left);`
+#[derive(Clone, PartialEq, Debug)]
+#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+#[allow(missing_docs)]
+pub struct ImageRect<C> {
+ pub url: SpecifiedUrl,
+ pub top: C,
+ pub bottom: C,
+ pub right: C,
+ pub left: C,
+}
+
+impl<G, N> fmt::Debug for Image<G, N>
+ where G: fmt::Debug, N: fmt::Debug,
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ Image::Url(ref url) => url.to_css(f),
+ Image::Gradient(ref grad) => grad.fmt(f),
+ Image::Rect(ref rect) => rect.fmt(f),
+ Image::Element(ref selector) => {
+ f.write_str("-moz-element(#")?;
+ serialize_identifier(&selector.to_string(), f)?;
+ f.write_str(")")
+ },
+ }
+ }
+}
+
+impl<G, N> ToCss for Image<G, N>
+ where G: ToCss, N: ToCss,
+{
+ fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+ match *self {
+ Image::Url(ref url) => url.to_css(dest),
+ Image::Gradient(ref gradient) => gradient.to_css(dest),
+ Image::Rect(ref rect) => rect.to_css(dest),
+ Image::Element(ref selector) => {
+ dest.write_str("-moz-element(#")?;
+ serialize_identifier(&selector.to_string(), dest)?;
+ dest.write_str(")")
+ },
+ }
+ }
+}
+
+impl<G, N> HasViewportPercentage for Image<G, N>
+ where G: HasViewportPercentage
+{
+ fn has_viewport_percentage(&self) -> bool {
+ match *self {
+ Image::Gradient(ref gradient) => gradient.has_viewport_percentage(),
+ _ => false,
+ }
+ }
+}
+
+impl<G, N> ToComputedValue for Image<G, N>
+ where G: ToComputedValue, N: ToComputedValue,
+{
+ type ComputedValue = Image<<G as ToComputedValue>::ComputedValue,
+ <N 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<K, C, L> HasViewportPercentage for Gradient<K, C, L>
+ where K: HasViewportPercentage, L: HasViewportPercentage,
+{
+ fn has_viewport_percentage(&self) -> bool {
+ self.kind.has_viewport_percentage() ||
+ self.items.iter().any(|i| i.has_viewport_percentage())
+ }
+}
+
+impl<K, C, L> ToComputedValue for Gradient<K, C, L>
+ where K: ToComputedValue, C: ToComputedValue, L: ToComputedValue,
+{
+ type ComputedValue = Gradient<<K as ToComputedValue>::ComputedValue,
+ <C as ToComputedValue>::ComputedValue,
+ <L 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<C, L> ToCss for GradientItem<C, L>
+ where C: ToCss, L: ToCss,
+{
+ fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+ match *self {
+ GradientItem::ColorStop(ref stop) => stop.to_css(dest),
+ GradientItem::InterpolationHint(ref hint) => hint.to_css(dest),
+ }
+ }
+}
+
+impl<C, L> HasViewportPercentage for GradientItem<C, L>
+ where L: HasViewportPercentage,
+{
+ fn has_viewport_percentage(&self) -> bool {
+ match *self {
+ GradientItem::ColorStop(ref stop) => stop.has_viewport_percentage(),
+ GradientItem::InterpolationHint(ref hint) => hint.has_viewport_percentage(),
+ }
+ }
+}
+
+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>
+ where C: fmt::Debug, L: fmt::Debug,
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{:?}", self.color)?;
+ if let Some(ref pos) = self.position {
+ write!(f, " {:?}", pos)?;
+ }
+ Ok(())
+ }
+}
+
+impl<C, L> ToCss for ColorStop<C, L>
+ where C: ToCss, L: ToCss,
+{
+ fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+ self.color.to_css(dest)?;
+ if let Some(ref position) = self.position {
+ dest.write_str(" ")?;
+ position.to_css(dest)?;
+ }
+ Ok(())
+ }
+}
+
+impl<C, L> HasViewportPercentage for ColorStop<C, L>
+ where L: HasViewportPercentage,
+{
+ fn has_viewport_percentage(&self) -> bool {
+ self.position.as_ref().map_or(false, HasViewportPercentage::has_viewport_percentage)
+ }
+}
+
+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>
+ where C: ToCss,
+{
+ fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+ dest.write_str("-moz-image-rect(")?;
+ self.url.to_css(dest)?;
+ dest.write_str(", ")?;
+ self.top.to_css(dest)?;
+ dest.write_str(", ")?;
+ self.right.to_css(dest)?;
+ dest.write_str(", ")?;
+ self.bottom.to_css(dest)?;
+ dest.write_str(", ")?;
+ self.left.to_css(dest)?;
+ 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.clone(),
+ 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: computed.url.clone(),
+ 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),
+ }
+ }
+}
diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs
index 43cf722fb7e..604d6e21238 100644
--- a/components/style/values/generics/mod.rs
+++ b/components/style/values/generics/mod.rs
@@ -14,6 +14,7 @@ use super::computed::{Context, ToComputedValue};
pub use self::basic_shape::serialize_radius_values;
pub mod basic_shape;
+pub mod image;
pub mod position;
#[derive(Clone, PartialEq, Debug)]
diff --git a/components/style/values/specified/image.rs b/components/style/values/specified/image.rs
index 515082d2c11..62e971782f9 100644
--- a/components/style/values/specified/image.rs
+++ b/components/style/values/specified/image.rs
@@ -8,68 +8,58 @@
//! [image]: https://drafts.csswg.org/css-images/#image-values
use Atom;
-use cssparser::{Parser, Token, serialize_identifier};
+use cssparser::{Parser, Token};
use parser::{Parse, ParserContext};
#[cfg(feature = "servo")]
use servo_url::ServoUrl;
use std::fmt;
use style_traits::ToCss;
+use values::generics::image::{CompatMode, ColorStop as GenericColorStop};
+use values::generics::image::{Gradient as GenericGradient, GradientItem as GenericGradientItem};
+use values::generics::image::{Image as GenericImage, ImageRect as GenericImageRect};
use values::specified::{Angle, CSSColor, Length, LengthOrPercentage, NumberOrPercentage};
use values::specified::position::Position;
use values::specified::url::SpecifiedUrl;
/// Specified values for an image according to CSS-IMAGES.
/// https://drafts.csswg.org/css-images/#image-values
-#[derive(Clone, PartialEq, Debug)]
-#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-pub enum Image {
- /// A `<url()>` image.
- Url(SpecifiedUrl),
- /// A `<gradient>` image.
- Gradient(Gradient),
- /// A `-moz-image-rect` image
- ImageRect(ImageRect),
- /// A `-moz-element(# <element-id>)`
- Element(Atom),
-}
+pub type Image = GenericImage<Gradient, NumberOrPercentage>;
-impl ToCss for Image {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- match *self {
- Image::Url(ref url_value) => url_value.to_css(dest),
- Image::Gradient(ref gradient) => gradient.to_css(dest),
- Image::ImageRect(ref image_rect) => image_rect.to_css(dest),
- Image::Element(ref selector) => {
- dest.write_str("-moz-element(#")?;
- // FIXME: We should get rid of these intermediate strings.
- serialize_identifier(&*selector.to_string(), dest)?;
- dest.write_str(")")
- },
- }
- }
-}
+/// Specified values for a CSS gradient.
+/// https://drafts.csswg.org/css-images/#gradients
+pub type Gradient = GenericGradient<GradientKind, CSSColor, LengthOrPercentage>;
+
+/// A specified gradient item.
+pub type GradientItem = GenericGradientItem<CSSColor, LengthOrPercentage>;
+
+/// A computed color stop.
+pub type ColorStop = GenericColorStop<CSSColor, LengthOrPercentage>;
+
+/// Specified values for `moz-image-rect`
+/// -moz-image-rect(<uri>, top, right, bottom, left);
+pub type ImageRect = GenericImageRect<NumberOrPercentage>;
impl Image {
#[allow(missing_docs)]
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Image, ()> {
if let Ok(url) = input.try(|input| SpecifiedUrl::parse(context, input)) {
- return Ok(Image::Url(url));
+ return Ok(GenericImage::Url(url));
}
if let Ok(gradient) = input.try(|input| Gradient::parse_function(context, input)) {
- return Ok(Image::Gradient(gradient));
+ return Ok(GenericImage::Gradient(gradient));
}
if let Ok(image_rect) = input.try(|input| ImageRect::parse(context, input)) {
- return Ok(Image::ImageRect(image_rect));
+ return Ok(GenericImage::Rect(image_rect));
}
- Ok(Image::Element(Image::parse_element(input)?))
+ Ok(GenericImage::Element(Image::parse_element(input)?))
}
/// Creates an already specified image value from an already resolved URL
/// for insertion in the cascade.
#[cfg(feature = "servo")]
pub fn for_cascade(url: ServoUrl) -> Self {
- Image::Url(SpecifiedUrl::for_cascade(url))
+ GenericImage::Url(SpecifiedUrl::for_cascade(url))
}
/// Parses a `-moz-element(# <element-id>)`.
@@ -87,21 +77,6 @@ impl Image {
}
}
-/// Specified values for a CSS gradient.
-/// https://drafts.csswg.org/css-images/#gradients
-#[derive(Clone, PartialEq, Debug)]
-#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-pub struct Gradient {
- /// The color stops and interpolation hints.
- pub items: Vec<GradientItem>,
- /// True if this is a repeating gradient.
- pub repeating: bool,
- /// Gradients can be linear or radial.
- pub gradient_kind: GradientKind,
- /// Compatibility mode.
- pub compat_mode: CompatMode,
-}
-
impl ToCss for Gradient {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
if self.compat_mode == CompatMode::WebKit {
@@ -111,7 +86,7 @@ impl ToCss for Gradient {
try!(dest.write_str("repeating-"));
}
let mut skipcomma = false;
- match self.gradient_kind {
+ match self.kind {
GradientKind::Linear(angle_or_corner) => {
try!(dest.write_str("linear-gradient("));
try!(angle_or_corner.to_css(dest, self.compat_mode));
@@ -198,7 +173,7 @@ impl Gradient {
Ok(Gradient {
items: items,
repeating: repeating,
- gradient_kind: gradient_kind,
+ kind: gradient_kind,
compat_mode: compat_mode,
})
}
@@ -209,11 +184,11 @@ impl Gradient {
if seen_stop {
if let Ok(hint) = input.try(|i| LengthOrPercentage::parse(context, i)) {
seen_stop = false;
- return Ok(GradientItem::InterpolationHint(hint));
+ return Ok(GenericGradientItem::InterpolationHint(hint));
}
}
seen_stop = true;
- ColorStop::parse(context, input).map(GradientItem::ColorStop)
+ ColorStop::parse(context, input).map(GenericGradientItem::ColorStop)
}));
if !seen_stop || items.len() < 2 {
return Err(());
@@ -238,16 +213,6 @@ pub enum GradientKind {
Radial(EndingShape, Position),
}
-#[derive(Clone, Copy, PartialEq, Debug)]
-#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-/// Whether we used the modern notation or the compatibility `-webkit` prefix.
-pub enum CompatMode {
- /// Modern syntax.
- Modern,
- /// `-webkit` prefix.
- WebKit,
-}
-
impl GradientKind {
/// Parses a linear gradient kind from the given arguments.
fn parse_modern_linear(context: &ParserContext, input: &mut Parser) -> Result<GradientKind, ()> {
@@ -396,35 +361,6 @@ impl GradientKind {
}
}
-/// Specified values for `moz-image-rect`
-/// -moz-image-rect(<uri>, top, right, bottom, left);
-#[derive(Clone, PartialEq, Debug)]
-#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-#[allow(missing_docs)]
-pub struct ImageRect {
- pub url: SpecifiedUrl,
- pub top: NumberOrPercentage,
- pub bottom: NumberOrPercentage,
- pub right: NumberOrPercentage,
- pub left: NumberOrPercentage,
-}
-
-impl ToCss for ImageRect {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- dest.write_str("-moz-image-rect(")?;
- self.url.to_css(dest)?;
- dest.write_str(", ")?;
- self.top.to_css(dest)?;
- dest.write_str(", ")?;
- self.right.to_css(dest)?;
- dest.write_str(", ")?;
- self.bottom.to_css(dest)?;
- dest.write_str(", ")?;
- self.left.to_css(dest)?;
- dest.write_str(")")
- }
-}
-
impl Parse for ImageRect {
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
match_ignore_ascii_case! { &try!(input.expect_function()),
@@ -502,50 +438,6 @@ impl AngleOrCorner {
}
}
-/// Specified values for color stops and interpolation hints.
-/// https://drafts.csswg.org/css-images-4/#color-stop-syntax
-#[derive(Clone, PartialEq, Debug)]
-#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-pub enum GradientItem {
- /// A color stop.
- ColorStop(ColorStop),
- /// An interpolation hint.
- InterpolationHint(LengthOrPercentage),
-}
-
-impl ToCss for GradientItem {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- match *self {
- GradientItem::ColorStop(ref stop) => stop.to_css(dest),
- GradientItem::InterpolationHint(ref hint) => hint.to_css(dest),
- }
- }
-}
-
-/// Specified values for one color stop in a gradient.
-/// https://drafts.csswg.org/css-images/#typedef-color-stop-list
-#[derive(Clone, PartialEq, Debug)]
-#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-pub struct ColorStop {
- /// The color of this stop.
- pub color: CSSColor,
-
- /// The position of this stop. If not specified, this stop is placed halfway between the
- /// point that precedes it and the point that follows it.
- pub position: Option<LengthOrPercentage>,
-}
-
-impl ToCss for ColorStop {
- fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
- try!(self.color.to_css(dest));
- if let Some(ref position) = self.position {
- try!(dest.write_str(" "));
- try!(position.to_css(dest));
- }
- Ok(())
- }
-}
-
define_css_keyword_enum!(HorizontalDirection: "left" => Left, "right" => Right);
define_css_keyword_enum!(VerticalDirection: "top" => Top, "bottom" => Bottom);