Skip to content

Commit

Permalink
stylo: Add SVGPaint type for <paint>
Browse files Browse the repository at this point in the history
MozReview-Commit-ID: 4QKKzJ1DVYP
  • Loading branch information
Manishearth committed Feb 18, 2017
1 parent c1d7941 commit fabc1b8
Show file tree
Hide file tree
Showing 2 changed files with 208 additions and 1 deletion.
57 changes: 56 additions & 1 deletion components/style/values/computed/mod.rs
Expand Up @@ -19,7 +19,7 @@ pub use super::{Auto, Either, None_};
#[cfg(feature = "gecko")]
pub use super::specified::{AlignJustifyContent, AlignJustifySelf};
pub use super::specified::{Angle, BorderStyle, GridLine, Time, UrlOrNone};
pub use super::specified::url::UrlExtraData;
pub use super::specified::url::{SpecifiedUrl, UrlExtraData};
pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrAuto};
pub use self::length::{LengthOrPercentageOrAutoOrContent, LengthOrPercentageOrNone, LengthOrNone};
pub use self::position::Position;
Expand Down Expand Up @@ -185,6 +185,61 @@ pub type Number = CSSFloat;
pub type Opacity = CSSFloat;


/// 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<CSSColor>,
}

/// 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>`
Color(CSSColor),
/// `url(...)`
PaintServer(SpecifiedUrl),
/// `context-fill`
ContextFill,
/// `context-stroke`
ContextStroke,
}

impl ToCss for SVGPaintKind {
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 ToCss for SVGPaint {
fn to_css<W>(&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(())
}
}


#[derive(Clone, PartialEq, Eq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
Expand Down
152 changes: 152 additions & 0 deletions components/style/values/specified/mod.rs
Expand Up @@ -670,6 +670,158 @@ impl Shadow {
}
}

/// 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<CSSColor>,
}

/// 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>`
Color(CSSColor),
/// `url(...)`
PaintServer(SpecifiedUrl),
/// `context-fill`
ContextFill,
/// `context-stroke`
ContextStroke,
}

impl SVGPaintKind {
fn parse_ident(input: &mut Parser) -> Result<Self, ()> {
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<Self, ()> {
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<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 ToCss for SVGPaint {
fn to_css<W>(&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(())
}
}


impl ToComputedValue for SVGPaint {
type ComputedValue = super::computed::SVGPaint;

#[inline]
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
super::computed::SVGPaint {
kind: self.kind.to_computed_value(context),
fallback: self.fallback.as_ref().map(|f| f.to_computed_value(context))
}
}

#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
SVGPaint {
kind: ToComputedValue::from_computed_value(&computed.kind),
fallback: computed.fallback.as_ref().map(ToComputedValue::from_computed_value)
}
}
}

impl ToComputedValue for SVGPaintKind {
type ComputedValue = super::computed::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) => {
super::computed::SVGPaintKind::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))
}
}
}
}


impl HasViewportPercentage for ClipRect {
fn has_viewport_percentage(&self) -> bool {
Expand Down

0 comments on commit fabc1b8

Please sign in to comment.