style: Simplify parsing and storage of SVG paint server fallback. r=boris

Differential Revision: https://phabricator.services.mozilla.com/D36806
This commit is contained in:
Emilio Cobos Álvarez 2019-07-06 08:24:39 +00:00
parent f0b5d02901
commit 83da7c1535
No known key found for this signature in database
GPG key ID: E1152D0994E4BF8A
5 changed files with 71 additions and 99 deletions

View file

@ -5,9 +5,36 @@
//! Generic types for CSS values in SVG
use crate::parser::{Parse, ParserContext};
use crate::values::{Either, None_};
use cssparser::Parser;
use style_traits::{ParseError, StyleParseErrorKind};
use style_traits::ParseError;
/// The fallback of an SVG paint server value.
#[derive(
Animate,
Clone,
ComputeSquaredDistance,
Debug,
MallocSizeOf,
PartialEq,
Parse,
SpecifiedValueInfo,
ToAnimatedValue,
ToAnimatedZero,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
)]
pub enum SVGPaintFallback<C> {
/// The `none` keyword.
None,
/// A magic value that represents no fallback specified and serializes to
/// the empty string.
#[css(skip)]
Unset,
/// A color.
Color(C),
}
/// An SVG paint value
///
@ -22,16 +49,26 @@ use style_traits::{ParseError, StyleParseErrorKind};
PartialEq,
SpecifiedValueInfo,
ToAnimatedValue,
ToAnimatedZero,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
)]
pub struct SVGPaint<ColorType, UrlPaintServer> {
/// The paint source
/// The paint source.
pub kind: SVGPaintKind<ColorType, UrlPaintServer>,
/// The fallback color. It would be empty, the `none` keyword or <color>.
pub fallback: Option<Either<ColorType, None_>>,
/// The fallback color.
pub fallback: SVGPaintFallback<ColorType>,
}
impl<C, U> Default for SVGPaint<C, U> {
fn default() -> Self {
Self {
kind: SVGPaintKind::None,
fallback: SVGPaintFallback::Unset,
}
}
}
/// An SVG paint value without the fallback
@ -47,6 +84,7 @@ pub struct SVGPaint<ColorType, UrlPaintServer> {
Debug,
MallocSizeOf,
PartialEq,
Parse,
SpecifiedValueInfo,
ToAnimatedValue,
ToAnimatedZero,
@ -70,65 +108,22 @@ pub enum SVGPaintKind<ColorType, UrlPaintServer> {
ContextStroke,
}
impl<ColorType, UrlPaintServer> SVGPaintKind<ColorType, UrlPaintServer> {
/// Parse a keyword value only
fn parse_ident<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
try_match_ident_ignore_ascii_case! { input,
"none" => Ok(SVGPaintKind::None),
"context-fill" => Ok(SVGPaintKind::ContextFill),
"context-stroke" => Ok(SVGPaintKind::ContextStroke),
}
}
}
/// Parse SVGPaint's fallback.
/// fallback is keyword(none), Color or empty.
/// <https://svgwg.org/svg2-draft/painting.html#SpecifyingPaint>
fn parse_fallback<'i, 't, ColorType: Parse>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Option<Either<ColorType, None_>> {
if input.try(|i| i.expect_ident_matching("none")).is_ok() {
Some(Either::Second(None_))
} else {
if let Ok(color) = input.try(|i| ColorType::parse(context, i)) {
Some(Either::First(color))
} else {
None
}
}
}
impl<ColorType: Parse, UrlPaintServer: Parse> Parse for SVGPaint<ColorType, UrlPaintServer> {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
if let Ok(url) = input.try(|i| UrlPaintServer::parse(context, i)) {
Ok(SVGPaint {
kind: SVGPaintKind::PaintServer(url),
fallback: parse_fallback(context, input),
})
} else if let Ok(kind) = input.try(SVGPaintKind::parse_ident) {
if let SVGPaintKind::None = kind {
Ok(SVGPaint {
kind: kind,
fallback: None,
})
} else {
Ok(SVGPaint {
kind: kind,
fallback: parse_fallback(context, input),
})
}
} else if let Ok(color) = input.try(|i| ColorType::parse(context, i)) {
Ok(SVGPaint {
kind: SVGPaintKind::Color(color),
fallback: None,
})
} else {
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
let kind = SVGPaintKind::parse(context, input)?;
if matches!(kind, SVGPaintKind::None | SVGPaintKind::Color(..)) {
return Ok(SVGPaint {
kind,
fallback: SVGPaintFallback::Unset
});
}
let fallback = input
.try(|i| SVGPaintFallback::parse(context, i))
.unwrap_or(SVGPaintFallback::Unset);
Ok(SVGPaint { kind, fallback })
}
}