servo/components/style/properties/longhand/inherited_svg.mako.rs

292 lines
11 KiB
Rust

/* 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/. */
<%namespace name="helpers" file="/helpers.mako.rs" />
// SVG 1.1 (Second Edition)
// https://www.w3.org/TR/SVG/
<% data.new_style_struct("InheritedSVG",
inherited=True,
gecko_name="SVG") %>
// Section 10 - Text
${helpers.single_keyword("text-anchor",
"start middle end",
products="gecko",
animation_value_type="discrete",
spec="https://www.w3.org/TR/SVG/text.html#TextAnchorProperty")}
// Section 11 - Painting: Filling, Stroking and Marker Symbols
${helpers.single_keyword("color-interpolation",
"srgb auto linearrgb",
products="gecko",
animation_value_type="discrete",
spec="https://www.w3.org/TR/SVG11/painting.html#ColorInterpolationProperty")}
${helpers.single_keyword("color-interpolation-filters", "linearrgb auto srgb",
products="gecko",
gecko_constant_prefix="NS_STYLE_COLOR_INTERPOLATION",
animation_value_type="discrete",
spec="https://www.w3.org/TR/SVG11/painting.html#ColorInterpolationFiltersProperty")}
${helpers.predefined_type(
"fill", "SVGPaint",
"::values::computed::SVGPaint::black()",
products="gecko",
animation_value_type="IntermediateSVGPaint",
boxed=True,
spec="https://www.w3.org/TR/SVG2/painting.html#SpecifyingFillPaint")}
${helpers.predefined_type("fill-opacity", "Opacity", "1.0",
products="gecko", animation_value_type="ComputedValue",
spec="https://www.w3.org/TR/SVG11/painting.html#FillOpacityProperty")}
${helpers.single_keyword("fill-rule", "nonzero evenodd",
gecko_enum_prefix="StyleFillRule",
gecko_inexhaustive=True,
products="gecko", animation_value_type="discrete",
spec="https://www.w3.org/TR/SVG11/painting.html#FillRuleProperty")}
${helpers.single_keyword("shape-rendering",
"auto optimizespeed crispedges geometricprecision",
products="gecko",
animation_value_type="discrete",
spec="https://www.w3.org/TR/SVG11/painting.html#ShapeRenderingProperty")}
${helpers.predefined_type(
"stroke", "SVGPaint",
"Default::default()",
products="gecko",
animation_value_type="IntermediateSVGPaint",
boxed=True,
spec="https://www.w3.org/TR/SVG2/painting.html#SpecifyingStrokePaint")}
${helpers.predefined_type(
"stroke-width", "LengthOrPercentageOrNumber",
"Either::First(1.0)",
"parse_non_negative",
products="gecko",
animation_value_type="ComputedValue",
spec="https://www.w3.org/TR/SVG2/painting.html#StrokeWidth")}
${helpers.single_keyword("stroke-linecap", "butt round square",
products="gecko", animation_value_type="discrete",
spec="https://www.w3.org/TR/SVG11/painting.html#StrokeLinecapProperty")}
${helpers.single_keyword("stroke-linejoin", "miter round bevel",
products="gecko", animation_value_type="discrete",
spec="https://www.w3.org/TR/SVG11/painting.html#StrokeLinejoinProperty")}
${helpers.predefined_type("stroke-miterlimit", "Number", "4.0",
"parse_at_least_one", products="gecko",
animation_value_type="ComputedValue",
spec="https://www.w3.org/TR/SVG11/painting.html#StrokeMiterlimitProperty")}
${helpers.predefined_type("stroke-opacity", "Opacity", "1.0",
products="gecko", animation_value_type="ComputedValue",
spec="https://www.w3.org/TR/SVG11/painting.html#StrokeOpacityProperty")}
${helpers.predefined_type(
"stroke-dasharray",
"LengthOrPercentageOrNumber",
None,
"parse_non_negative",
vector=True,
delegate_animate=True,
products="gecko",
animation_value_type="ComputedValue",
space_separated_allowed="True",
spec="https://www.w3.org/TR/SVG2/painting.html#StrokeDashing",
)}
${helpers.predefined_type(
"stroke-dashoffset", "LengthOrPercentageOrNumber",
"Either::First(0.0)",
products="gecko",
animation_value_type="ComputedValue",
spec="https://www.w3.org/TR/SVG2/painting.html#StrokeDashing")}
// Section 14 - Clipping, Masking and Compositing
${helpers.single_keyword("clip-rule", "nonzero evenodd",
products="gecko",
gecko_enum_prefix="StyleFillRule",
gecko_inexhaustive=True,
animation_value_type="discrete",
spec="https://www.w3.org/TR/SVG11/masking.html#ClipRuleProperty")}
${helpers.predefined_type("marker-start", "UrlOrNone", "Either::Second(None_)",
products="gecko",
boxed="True" if product == "gecko" else "False",
animation_value_type="none",
spec="https://www.w3.org/TR/SVG2/painting.html#VertexMarkerProperties")}
${helpers.predefined_type("marker-mid", "UrlOrNone", "Either::Second(None_)",
products="gecko",
boxed="True" if product == "gecko" else "False",
animation_value_type="none",
spec="https://www.w3.org/TR/SVG2/painting.html#VertexMarkerProperties")}
${helpers.predefined_type("marker-end", "UrlOrNone", "Either::Second(None_)",
products="gecko",
boxed="True" if product == "gecko" else "False",
animation_value_type="none",
spec="https://www.w3.org/TR/SVG2/painting.html#VertexMarkerProperties")}
<%helpers:longhand name="paint-order"
animation_value_type="none"
products="gecko"
spec="https://www.w3.org/TR/SVG2/painting.html#PaintOrder">
use values::computed::ComputedValueAsSpecified;
use std::fmt;
use style_traits::ToCss;
pub const NORMAL: u8 = 0;
pub const FILL: u8 = 1;
pub const STROKE: u8 = 2;
pub const MARKERS: u8 = 3;
// number of bits for each component
pub const SHIFT: u8 = 2;
// mask with above bits set
pub const MASK: u8 = 0b11;
// number of non-normal keyword values
pub const COUNT: u8 = 3;
// all keywords
pub const ALL: [u8; 3] = [FILL, STROKE, MARKERS];
/// Represented as a six-bit field, of 3 two-bit pairs
///
/// Each pair can be set to FILL, STROKE, or MARKERS
/// Lowest significant bit pairs are highest priority.
/// `normal` is the empty bitfield. The three pairs are
/// never zero in any case other than `normal`.
///
/// Higher priority values, i.e. the values specified first,
/// will be painted first (and may be covered by paintings of lower priority)
#[derive(PartialEq, Clone, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct SpecifiedValue(pub u8);
pub mod computed_value {
pub use super::SpecifiedValue as T;
}
pub fn get_initial_value() -> SpecifiedValue {
SpecifiedValue(NORMAL)
}
impl SpecifiedValue {
pub fn bits_at(&self, pos: u8) -> u8 {
(self.0 >> pos * SHIFT) & MASK
}
}
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue,ParseError<'i>> {
if let Ok(()) = input.try(|i| i.expect_ident_matching("normal")) {
Ok(SpecifiedValue(0))
} else {
let mut value = 0;
// bitfield representing what we've seen so far
// bit 1 is fill, bit 2 is stroke, bit 3 is markers
let mut seen = 0;
let mut pos = 0;
loop {
let result: Result<_, ParseError> = input.try(|i| {
try_match_ident_ignore_ascii_case! { i.expect_ident()?,
"fill" => Ok(FILL),
"stroke" => Ok(STROKE),
"markers" => Ok(MARKERS),
}
});
match result {
Ok(val) => {
if (seen & (1 << val)) != 0 {
// don't parse the same ident twice
return Err(StyleParseError::UnspecifiedError.into())
} else {
value |= val << (pos * SHIFT);
seen |= 1 << val;
pos += 1;
}
}
Err(_) => break,
}
}
if value == 0 {
// couldn't find any keyword
Err(StyleParseError::UnspecifiedError.into())
} else {
// fill in rest
for i in pos..COUNT {
for paint in &ALL {
// if not seen, set bit at position, mark as seen
if (seen & (1 << paint)) == 0 {
seen |= 1 << paint;
value |= paint << (i * SHIFT);
break;
}
}
}
Ok(SpecifiedValue(value))
}
}
}
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
if self.0 == 0 {
return dest.write_str("normal")
}
for pos in 0..COUNT {
if pos != 0 {
dest.write_str(" ")?
}
match self.bits_at(pos) {
FILL => dest.write_str("fill")?,
STROKE => dest.write_str("stroke")?,
MARKERS => dest.write_str("markers")?,
_ => unreachable!(),
}
}
Ok(())
}
}
no_viewport_percentage!(SpecifiedValue);
impl ComputedValueAsSpecified for SpecifiedValue { }
</%helpers:longhand>
<%helpers:vector_longhand name="-moz-context-properties"
animation_value_type="none"
products="gecko"
spec="Nonstandard (Internal-only)"
allow_empty="True">
use values::CustomIdent;
use values::computed::ComputedValueAsSpecified;
no_viewport_percentage!(SpecifiedValue);
impl ComputedValueAsSpecified for SpecifiedValue { }
pub type SpecifiedValue = CustomIdent;
pub mod computed_value {
pub type T = super::SpecifiedValue;
}
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
let i = input.expect_ident()?;
CustomIdent::from_ident(i, &["all", "none", "auto"])
}
</%helpers:vector_longhand>