From 74f3284c69749d34608da733c78544222df45a32 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Mon, 5 Jun 2017 16:50:16 -0700 Subject: [PATCH] Make SVGPaint generic --- components/style/properties/gecko.mako.rs | 2 +- components/style/values/computed/mod.rs | 62 +--------- components/style/values/generics/mod.rs | 131 ++++++++++++++++++++++ components/style/values/specified/mod.rs | 131 ++-------------------- 4 files changed, 148 insertions(+), 178 deletions(-) diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index c041e23c049..3328e682f1c 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -416,7 +416,7 @@ fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor { <%def name="impl_svg_paint(ident, gecko_ffi_name, need_clone=False, complex_color=True)"> #[allow(non_snake_case)] pub fn set_${ident}(&mut self, mut v: longhands::${ident}::computed_value::T) { - use values::computed::SVGPaintKind; + use values::generics::SVGPaintKind; use self::structs::nsStyleSVGPaintType; use self::structs::nsStyleSVGFallbackType; diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 3548a045d9c..26165dc4e13 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -532,23 +532,15 @@ impl IntegerOrAuto { } } - -/// An SVG paint value -/// -/// https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint -#[derive(Debug, Clone, PartialEq)] -#[cfg_attr(feature = "servo", derive(HeapSizeOf))] -pub struct SVGPaint { - /// The paint source - pub kind: SVGPaintKind, - /// The fallback color - pub fallback: Option, -} +/// Computed SVG Paint value +pub type SVGPaint = ::values::generics::SVGPaint; +/// Computed SVG Paint Kind value +pub type SVGPaintKind = ::values::generics::SVGPaintKind; impl Default for SVGPaint { fn default() -> Self { SVGPaint { - kind: SVGPaintKind::None, + kind: ::values::generics::SVGPaintKind::None, fallback: None, } } @@ -559,54 +551,12 @@ impl SVGPaint { pub fn black() -> Self { let rgba = RGBA::from_floats(0., 0., 0., 1.); SVGPaint { - kind: SVGPaintKind::Color(CSSColor::RGBA(rgba)), + kind: ::values::generics::SVGPaintKind::Color(CSSColor::RGBA(rgba)), fallback: None, } } } -/// An SVG paint value without the fallback -/// -/// 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))] -pub enum SVGPaintKind { - /// `none` - None, - /// `` - Color(CSSColor), - /// `url(...)` - PaintServer(SpecifiedUrl), - /// `context-fill` - ContextFill, - /// `context-stroke` - ContextStroke, -} - -impl ToCss for SVGPaintKind { - fn to_css(&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 ToCss for SVGPaint { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - self.kind.to_css(dest)?; - if let Some(ref fallback) = self.fallback { - fallback.to_css(dest)?; - } - Ok(()) - } -} - /// | | pub type LengthOrPercentageOrNumber = Either; diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index 7cbadffe10a..3ff55fda6c8 100644 --- a/components/style/values/generics/mod.rs +++ b/components/style/values/generics/mod.rs @@ -11,6 +11,7 @@ use parser::{Parse, ParserContext}; use std::fmt; use style_traits::{OneOrMoreCommaSeparated, ToCss}; use super::CustomIdent; +use values::specified::url::SpecifiedUrl; pub mod background; pub mod basic_shape; @@ -268,3 +269,133 @@ impl ToCss for FontSettingTagFloat { self.0.to_css(dest) } } + + +/// An SVG paint value +/// +/// https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint +#[derive(Debug, Clone, PartialEq)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +pub struct SVGPaint { + /// The paint source + pub kind: SVGPaintKind, + /// The fallback color + pub fallback: Option, +} + +/// An SVG paint value without the fallback +/// +/// 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))] +pub enum SVGPaintKind { + /// `none` + None, + /// `` + Color(ColorType), + /// `url(...)` + PaintServer(SpecifiedUrl), + /// `context-fill` + ContextFill, + /// `context-stroke` + ContextStroke, +} + +impl SVGPaintKind { + /// Convert to a value with a different kind of color + pub fn convert(&self, f: F) -> SVGPaintKind + where F: Fn(&ColorType) -> OtherColor { + match *self { + SVGPaintKind::None => SVGPaintKind::None, + SVGPaintKind::ContextStroke => SVGPaintKind::ContextStroke, + SVGPaintKind::ContextFill => SVGPaintKind::ContextFill, + SVGPaintKind::Color(ref color) => { + SVGPaintKind::Color(f(color)) + } + SVGPaintKind::PaintServer(ref server) => { + SVGPaintKind::PaintServer(server.clone()) + } + } + } +} + +impl SVGPaint { + /// Convert to a value with a different kind of color + pub fn convert(&self, f: F) -> SVGPaint + where F: Fn(&ColorType) -> OtherColor { + SVGPaint { + kind: self.kind.convert(&f), + fallback: self.fallback.as_ref().map(|color| f(color)) + } + } +} + +impl SVGPaintKind { + /// Parse a keyword value only + fn parse_ident(input: &mut Parser) -> Result { + Ok(match_ignore_ascii_case! { &input.expect_ident()?, + "none" => SVGPaintKind::None, + "context-fill" => SVGPaintKind::ContextFill, + "context-stroke" => SVGPaintKind::ContextStroke, + _ => return Err(()) + }) + } +} + +impl Parse for SVGPaint { + fn parse(context: &ParserContext, input: &mut Parser) -> Result { + if let Ok(url) = input.try(|i| SpecifiedUrl::parse(context, i)) { + let fallback = input.try(|i| ColorType::parse(context, i)); + Ok(SVGPaint { + kind: SVGPaintKind::PaintServer(url), + fallback: fallback.ok(), + }) + } else if let Ok(kind) = input.try(SVGPaintKind::parse_ident) { + if let SVGPaintKind::None = kind { + Ok(SVGPaint { + kind: kind, + fallback: None, + }) + } else { + let fallback = input.try(|i| ColorType::parse(context, i)); + Ok(SVGPaint { + kind: kind, + fallback: fallback.ok(), + }) + } + } else if let Ok(color) = input.try(|i| ColorType::parse(context, i)) { + Ok(SVGPaint { + kind: SVGPaintKind::Color(color), + fallback: None, + }) + } else { + Err(()) + } + } +} + +impl ToCss for SVGPaintKind { + fn to_css(&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 ToCss for SVGPaint { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + self.kind.to_css(dest)?; + if let Some(ref fallback) = self.fallback { + fallback.to_css(dest)?; + } + Ok(()) + } +} + + diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 71008d4e1d1..2299362f6de 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -933,103 +933,11 @@ impl Shadow { no_viewport_percentage!(SVGPaint); -/// An SVG paint value -/// -/// https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint -#[derive(Debug, Clone, PartialEq)] -#[cfg_attr(feature = "servo", derive(HeapSizeOf))] -pub struct SVGPaint { - /// The paint source - pub kind: SVGPaintKind, - /// The fallback color - pub fallback: Option, -} - -/// An SVG paint value without the fallback -/// -/// 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))] -pub enum SVGPaintKind { - /// `none` - None, - /// `` - Color(CSSColor), - /// `url(...)` - PaintServer(SpecifiedUrl), - /// `context-fill` - ContextFill, - /// `context-stroke` - ContextStroke, -} - -impl SVGPaintKind { - fn parse_ident(input: &mut Parser) -> Result { - Ok(match_ignore_ascii_case! { &input.expect_ident()?, - "none" => SVGPaintKind::None, - "context-fill" => SVGPaintKind::ContextFill, - "context-stroke" => SVGPaintKind::ContextStroke, - _ => return Err(()) - }) - } -} - -impl Parse for SVGPaint { - fn parse(context: &ParserContext, input: &mut Parser) -> Result { - if let Ok(url) = input.try(|i| SpecifiedUrl::parse(context, i)) { - let fallback = input.try(|i| CSSColor::parse(context, i)); - Ok(SVGPaint { - kind: SVGPaintKind::PaintServer(url), - fallback: fallback.ok(), - }) - } else if let Ok(kind) = input.try(SVGPaintKind::parse_ident) { - if kind == SVGPaintKind::None { - Ok(SVGPaint { - kind: kind, - fallback: None, - }) - } else { - let fallback = input.try(|i| CSSColor::parse(context, i)); - Ok(SVGPaint { - kind: kind, - fallback: fallback.ok(), - }) - } - } else if let Ok(color) = input.try(|i| CSSColor::parse(context, i)) { - Ok(SVGPaint { - kind: SVGPaintKind::Color(color), - fallback: None, - }) - } else { - Err(()) - } - } -} - -impl ToCss for SVGPaintKind { - fn to_css(&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 ToCss for SVGPaint { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - self.kind.to_css(dest)?; - if let Some(ref fallback) = self.fallback { - fallback.to_css(dest)?; - } - Ok(()) - } -} +/// Specified SVG Paint value +pub type SVGPaint = ::values::generics::SVGPaint; +/// Specified SVG Paint Kind value +pub type SVGPaintKind = ::values::generics::SVGPaintKind; impl ToComputedValue for SVGPaint { type ComputedValue = super::computed::SVGPaint; @@ -1056,36 +964,17 @@ impl ToComputedValue for SVGPaintKind { #[inline] fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { - match *self { - SVGPaintKind::None => super::computed::SVGPaintKind::None, - SVGPaintKind::ContextStroke => super::computed::SVGPaintKind::ContextStroke, - SVGPaintKind::ContextFill => super::computed::SVGPaintKind::ContextFill, - SVGPaintKind::Color(ref color) => { - let color = match color.parsed { - Color::CurrentColor => cssparser::Color::RGBA(context.style().get_color().clone_color()), - _ => color.to_computed_value(context), - }; - super::computed::SVGPaintKind::Color(color) + self.convert(|color| { + match color.parsed { + Color::CurrentColor => cssparser::Color::RGBA(context.style().get_color().clone_color()), + _ => color.to_computed_value(context), } - SVGPaintKind::PaintServer(ref server) => { - super::computed::SVGPaintKind::PaintServer(server.to_computed_value(context)) - } - } + }) } #[inline] fn from_computed_value(computed: &Self::ComputedValue) -> Self { - match *computed { - super::computed::SVGPaintKind::None => SVGPaintKind::None, - super::computed::SVGPaintKind::ContextStroke => SVGPaintKind::ContextStroke, - super::computed::SVGPaintKind::ContextFill => SVGPaintKind::ContextFill, - super::computed::SVGPaintKind::Color(ref color) => { - SVGPaintKind::Color(ToComputedValue::from_computed_value(color)) - } - super::computed::SVGPaintKind::PaintServer(ref server) => { - SVGPaintKind::PaintServer(ToComputedValue::from_computed_value(server)) - } - } + computed.convert(ToComputedValue::from_computed_value) } }