/* 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 https://mozilla.org/MPL/2.0/. */ //! 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}; /// An SVG paint value /// /// #[animation(no_bound(UrlPaintServer))] #[derive( Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToComputedValue, ToCss, ToResolvedValue, ToShmem, )] pub struct SVGPaint { /// The paint source pub kind: SVGPaintKind, /// The fallback color. It would be empty, the `none` keyword or . 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. #[animation(no_bound(UrlPaintServer))] #[derive( Animate, Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, ToComputedValue, ToCss, ToResolvedValue, ToShmem, )] pub enum SVGPaintKind { /// `none` #[animation(error)] None, /// `` Color(ColorType), /// `url(...)` #[animation(error)] PaintServer(UrlPaintServer), /// `context-fill` ContextFill, /// `context-stroke` ContextStroke, } impl SVGPaintKind { /// Parse a keyword value only fn parse_ident<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { 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. /// fn parse_fallback<'i, 't, ColorType: Parse>( context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Option> { 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 Parse for SVGPaint { fn parse<'i, 't>( context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result> { 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)) } } } /// An SVG length value supports `context-value` in addition to length. #[derive( Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, ToComputedValue, ToCss, ToResolvedValue, ToShmem, )] pub enum SVGLength { /// ` | | ` LengthPercentage(L), /// `context-value` #[animation(error)] ContextValue, } /// Generic value for stroke-dasharray. #[derive( Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, ToComputedValue, ToCss, ToResolvedValue, ToShmem, )] pub enum SVGStrokeDashArray { /// `[ | | ]#` #[css(comma)] Values(#[css(if_empty = "none", iterable)] Vec), /// `context-value` ContextValue, } /// An SVG opacity value accepts `context-{fill,stroke}-opacity` in /// addition to opacity value. #[derive( Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq, Parse, SpecifiedValueInfo, ToAnimatedZero, ToComputedValue, ToCss, ToResolvedValue, ToShmem, )] pub enum SVGOpacity { /// `` Opacity(OpacityType), /// `context-fill-opacity` #[animation(error)] ContextFillOpacity, /// `context-stroke-opacity` #[animation(error)] ContextStrokeOpacity, }