Make stroke-dasharray accept context-value.

This commit is contained in:
Xidorn Quan 2017-08-02 09:27:48 +10:00
parent aa80859a71
commit 7827ca6bb5
8 changed files with 143 additions and 23 deletions

View file

@ -4981,27 +4981,41 @@ clip-path
${impl_simple_copy('paint_order', 'mPaintOrder')} ${impl_simple_copy('paint_order', 'mPaintOrder')}
pub fn set_stroke_dasharray<I>(&mut self, v: I) pub fn set_stroke_dasharray(&mut self, v: longhands::stroke_dasharray::computed_value::T) {
where I: IntoIterator<Item = longhands::stroke_dasharray::computed_value::single_value::T>, use gecko_bindings::structs::nsStyleSVG_STROKE_DASHARRAY_CONTEXT as CONTEXT_VALUE;
I::IntoIter: ExactSizeIterator use values::generics::svg::SVGStrokeDashArray;
{
let v = v.into_iter();
unsafe {
bindings::Gecko_nsStyleSVG_SetDashArrayLength(&mut self.gecko, v.len() as u32);
}
for (mut gecko, servo) in self.gecko.mStrokeDasharray.iter_mut().zip(v) { match v {
match servo { SVGStrokeDashArray::Values(v) => {
Either::First(number) => gecko.set_value(CoordDataValue::Factor(number)), let v = v.into_iter();
Either::Second(lop) => gecko.set(lop), self.gecko.mContextFlags &= !CONTEXT_VALUE;
unsafe {
bindings::Gecko_nsStyleSVG_SetDashArrayLength(&mut self.gecko, v.len() as u32);
}
for (mut gecko, servo) in self.gecko.mStrokeDasharray.iter_mut().zip(v) {
match servo {
Either::First(number) => gecko.set_value(CoordDataValue::Factor(number)),
Either::Second(lop) => gecko.set(lop),
}
}
}
SVGStrokeDashArray::ContextValue => {
self.gecko.mContextFlags |= CONTEXT_VALUE;
unsafe {
bindings::Gecko_nsStyleSVG_SetDashArrayLength(&mut self.gecko, 0);
}
} }
} }
} }
pub fn copy_stroke_dasharray_from(&mut self, other: &Self) { pub fn copy_stroke_dasharray_from(&mut self, other: &Self) {
use gecko_bindings::structs::nsStyleSVG_STROKE_DASHARRAY_CONTEXT as CONTEXT_VALUE;
unsafe { unsafe {
bindings::Gecko_nsStyleSVG_CopyDashArray(&mut self.gecko, &other.gecko); bindings::Gecko_nsStyleSVG_CopyDashArray(&mut self.gecko, &other.gecko);
} }
self.gecko.mContextFlags =
(self.gecko.mContextFlags & !CONTEXT_VALUE) |
(other.gecko.mContextFlags & CONTEXT_VALUE);
} }
pub fn reset_stroke_dasharray(&mut self, other: &Self) { pub fn reset_stroke_dasharray(&mut self, other: &Self) {
@ -5009,8 +5023,14 @@ clip-path
} }
pub fn clone_stroke_dasharray(&self) -> longhands::stroke_dasharray::computed_value::T { pub fn clone_stroke_dasharray(&self) -> longhands::stroke_dasharray::computed_value::T {
use gecko_bindings::structs::nsStyleSVG_STROKE_DASHARRAY_CONTEXT as CONTEXT_VALUE;
use values::computed::LengthOrPercentage; use values::computed::LengthOrPercentage;
use values::generics::svg::SVGStrokeDashArray;
if self.gecko.mContextFlags & CONTEXT_VALUE != 0 {
debug_assert_eq!(self.gecko.mStrokeDasharray.len(), 0);
return SVGStrokeDashArray::ContextValue;
}
let mut vec = vec![]; let mut vec = vec![];
for gecko in self.gecko.mStrokeDasharray.iter() { for gecko in self.gecko.mStrokeDasharray.iter() {
match gecko.as_value() { match gecko.as_value() {
@ -5024,7 +5044,7 @@ clip-path
_ => unreachable!(), _ => unreachable!(),
} }
} }
longhands::stroke_dasharray::computed_value::T(vec) SVGStrokeDashArray::Values(vec)
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]

View file

@ -46,7 +46,7 @@ use values::computed::{LengthOrPercentage, MaxLength, MozLength, Percentage, ToC
use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius; use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
use values::generics::effects::Filter; use values::generics::effects::Filter;
use values::generics::position as generic_position; use values::generics::position as generic_position;
use values::generics::svg::{SVGLength, SVGPaint, SVGPaintKind}; use values::generics::svg::{SVGLength, SVGPaint, SVGPaintKind, SVGStrokeDashArray};
/// A trait used to implement various procedures used during animation. /// A trait used to implement various procedures used during animation.
pub trait Animatable: Sized { pub trait Animatable: Sized {
@ -3074,6 +3074,48 @@ impl<LengthType> ToAnimatedZero for SVGLength<LengthType> where LengthType : ToA
} }
} }
impl<LengthType> Animatable for SVGStrokeDashArray<LengthType>
where LengthType : RepeatableListAnimatable + Clone
{
#[inline]
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
match (self, other) {
(&SVGStrokeDashArray::Values(ref this), &SVGStrokeDashArray::Values(ref other))=> {
this.add_weighted(other, self_portion, other_portion)
.map(SVGStrokeDashArray::Values)
}
_ => {
Ok(if self_portion > other_portion { self.clone() } else { other.clone() })
}
}
}
#[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
match (self, other) {
(&SVGStrokeDashArray::Values(ref this), &SVGStrokeDashArray::Values(ref other)) => {
this.compute_distance(other)
}
_ => Err(())
}
}
}
impl<LengthType> ToAnimatedZero for SVGStrokeDashArray<LengthType>
where LengthType : ToAnimatedZero + Clone
{
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
match self {
&SVGStrokeDashArray::Values(ref values) => {
values.iter().map(ToAnimatedZero::to_animated_zero)
.collect::<Result<Vec<_>, ()>>().map(SVGStrokeDashArray::Values)
}
&SVGStrokeDashArray::ContextValue => Ok(SVGStrokeDashArray::ContextValue),
}
}
}
<% <%
FILTER_FUNCTIONS = [ 'Blur', 'Brightness', 'Contrast', 'Grayscale', FILTER_FUNCTIONS = [ 'Blur', 'Brightness', 'Contrast', 'Grayscale',
'HueRotate', 'Invert', 'Opacity', 'Saturate', 'HueRotate', 'Invert', 'Opacity', 'Saturate',

View file

@ -91,13 +91,10 @@ ${helpers.predefined_type("stroke-opacity", "Opacity", "1.0",
${helpers.predefined_type( ${helpers.predefined_type(
"stroke-dasharray", "stroke-dasharray",
"LengthOrPercentageOrNumber", "SVGStrokeDashArray",
None, "Default::default()",
"parse_non_negative",
vector=True,
products="gecko", products="gecko",
animation_value_type="ComputedValue", animation_value_type="ComputedValue",
separator="CommaWithSpace",
spec="https://www.w3.org/TR/SVG2/painting.html#StrokeDashing", spec="https://www.w3.org/TR/SVG2/painting.html#StrokeDashing",
)} )}

View file

@ -44,7 +44,7 @@ pub use super::specified::url::SpecifiedUrl;
pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNone, LengthOrNumber, LengthOrPercentage}; pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNone, LengthOrNumber, LengthOrPercentage};
pub use self::length::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone, MaxLength, MozLength, Percentage}; pub use self::length::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone, MaxLength, MozLength, Percentage};
pub use self::position::Position; pub use self::position::Position;
pub use self::svg::{SVGLength, SVGPaint, SVGPaintKind}; pub use self::svg::{SVGLength, SVGPaint, SVGPaintKind, SVGStrokeDashArray};
pub use self::text::{InitialLetter, LetterSpacing, LineHeight, WordSpacing}; pub use self::text::{InitialLetter, LetterSpacing, LineHeight, WordSpacing};
pub use self::transform::{TimingFunction, TransformOrigin}; pub use self::transform::{TimingFunction, TransformOrigin};

View file

@ -42,3 +42,12 @@ impl From<Au> for SVGLength {
generic::SVGLength::Length(Either::Second(length.into())) generic::SVGLength::Length(Either::Second(length.into()))
} }
} }
/// [ <length> | <percentage> | <number> ]# | context-value
pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<LengthOrPercentageOrNumber>;
impl Default for SVGStrokeDashArray {
fn default() -> Self {
generic::SVGStrokeDashArray::Values(vec![])
}
}

View file

@ -6,7 +6,8 @@
use cssparser::Parser; use cssparser::Parser;
use parser::{Parse, ParserContext}; use parser::{Parse, ParserContext};
use style_traits::{ParseError, StyleParseError}; use std::fmt;
use style_traits::{ParseError, StyleParseError, ToCss};
use values::specified::url::SpecifiedUrl; use values::specified::url::SpecifiedUrl;
/// An SVG paint value /// An SVG paint value
@ -104,3 +105,36 @@ pub enum SVGLength<LengthType> {
/// `context-value` /// `context-value`
ContextValue, ContextValue,
} }
/// Generic value for stroke-dasharray.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Debug, PartialEq, HasViewportPercentage, ToComputedValue)]
pub enum SVGStrokeDashArray<LengthType> {
/// `[ <length> | <percentage> | <number> ]#`
Values(Vec<LengthType>),
/// `context-value`
ContextValue,
}
impl<LengthType> ToCss for SVGStrokeDashArray<LengthType> where LengthType: ToCss {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match self {
&SVGStrokeDashArray::Values(ref values) => {
let mut iter = values.iter();
if let Some(first) = iter.next() {
first.to_css(dest)?;
for item in iter {
dest.write_str(", ")?;
item.to_css(dest)?;
}
Ok(())
} else {
dest.write_str("none")
}
}
&SVGStrokeDashArray::ContextValue => {
dest.write_str("context-value")
}
}
}
}

View file

@ -43,7 +43,7 @@ pub use self::length::{LengthOrPercentageOrNone, MaxLength, MozLength};
pub use self::length::{NoCalcLength, Percentage, ViewportPercentageLength}; pub use self::length::{NoCalcLength, Percentage, ViewportPercentageLength};
pub use self::rect::LengthOrNumberRect; pub use self::rect::LengthOrNumberRect;
pub use self::position::{Position, PositionComponent}; pub use self::position::{Position, PositionComponent};
pub use self::svg::{SVGLength, SVGPaint, SVGPaintKind}; pub use self::svg::{SVGLength, SVGPaint, SVGPaintKind, SVGStrokeDashArray};
pub use self::text::{InitialLetter, LetterSpacing, LineHeight, WordSpacing}; pub use self::text::{InitialLetter, LetterSpacing, LineHeight, WordSpacing};
pub use self::transform::{TimingFunction, TransformOrigin}; pub use self::transform::{TimingFunction, TransformOrigin};
pub use super::generics::grid::GridLine; pub use super::generics::grid::GridLine;

View file

@ -6,7 +6,7 @@
use cssparser::Parser; use cssparser::Parser;
use parser::{Parse, ParserContext}; use parser::{Parse, ParserContext};
use style_traits::{ParseError, StyleParseError}; use style_traits::{CommaWithSpace, ParseError, Separator, StyleParseError};
use values::generics::svg as generic; use values::generics::svg as generic;
use values::specified::LengthOrPercentageOrNumber; use values::specified::LengthOrPercentageOrNumber;
use values::specified::color::RGBAColor; use values::specified::color::RGBAColor;
@ -69,3 +69,21 @@ impl From<LengthOrPercentageOrNumber> for SVGLength {
generic::SVGLength::Length(length) generic::SVGLength::Length(length)
} }
} }
/// [ <length> | <percentage> | <number> ]# | context-value
pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<LengthOrPercentageOrNumber>;
impl Parse for SVGStrokeDashArray {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
if let Ok(values) = input.try(|i| CommaWithSpace::parse(i, |i| {
LengthOrPercentageOrNumber::parse_non_negative(context, i)
})) {
Ok(generic::SVGStrokeDashArray::Values(values))
} else if let Ok(_) = input.try(|i| i.expect_ident_matching("none")) {
Ok(generic::SVGStrokeDashArray::Values(vec![]))
} else {
parse_context_value(input, generic::SVGStrokeDashArray::ContextValue)
}
}
}