mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Make stroke-dasharray accept context-value.
This commit is contained in:
parent
aa80859a71
commit
7827ca6bb5
8 changed files with 143 additions and 23 deletions
|
@ -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)]
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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",
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
@ -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};
|
||||||
|
|
||||||
|
|
|
@ -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![])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue