diff options
author | Xidorn Quan <me@upsuper.org> | 2017-08-02 09:27:49 +1000 |
---|---|---|
committer | Xidorn Quan <me@upsuper.org> | 2017-08-02 10:35:18 +1000 |
commit | ef4352d2a549ebd8aff28cb606db18ac76e50e3a (patch) | |
tree | 6fa2520f7d99c48d1ccf67500323d1a959d68bb4 | |
parent | 7827ca6bb5faa78dbaf108e1cd6c499a966e52bc (diff) | |
download | servo-ef4352d2a549ebd8aff28cb606db18ac76e50e3a.tar.gz servo-ef4352d2a549ebd8aff28cb606db18ac76e50e3a.zip |
Add context-{fill,stroke}-opacity support to {fill,stroke}-opacity.
-rw-r--r-- | components/style/properties/gecko.mako.rs | 62 | ||||
-rw-r--r-- | components/style/properties/helpers/animated_properties.mako.rs | 41 | ||||
-rw-r--r-- | components/style/properties/longhand/inherited_svg.mako.rs | 4 | ||||
-rw-r--r-- | components/style/values/computed/mod.rs | 2 | ||||
-rw-r--r-- | components/style/values/computed/svg.rs | 11 | ||||
-rw-r--r-- | components/style/values/generics/svg.rs | 13 | ||||
-rw-r--r-- | components/style/values/specified/mod.rs | 2 | ||||
-rw-r--r-- | components/style/values/specified/svg.rs | 21 |
8 files changed, 149 insertions, 7 deletions
diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 09bb7d8397e..be27f6bcdd4 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -634,6 +634,67 @@ def set_gecko_property(ffi_name, expr): } </%def> +<%def name="impl_svg_opacity(ident, gecko_ffi_name, need_clone=False)"> + <% source_prefix = ident.split("_")[0].upper() + "_OPACITY_SOURCE" %> + + pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) { + use gecko_bindings::structs::nsStyleSVG_${source_prefix}_MASK as MASK; + use gecko_bindings::structs::nsStyleSVG_${source_prefix}_SHIFT as SHIFT; + use gecko_bindings::structs::nsStyleSVGOpacitySource::*; + use values::generics::svg::SVGOpacity; + self.gecko.mContextFlags &= !MASK; + match v { + SVGOpacity::Opacity(opacity) => { + self.gecko.mContextFlags |= + (eStyleSVGOpacitySource_Normal as u8) << SHIFT; + self.gecko.${gecko_ffi_name} = opacity; + } + SVGOpacity::ContextFillOpacity => { + self.gecko.mContextFlags |= + (eStyleSVGOpacitySource_ContextFillOpacity as u8) << SHIFT; + self.gecko.${gecko_ffi_name} = 1.; + } + SVGOpacity::ContextStrokeOpacity => { + self.gecko.mContextFlags |= + (eStyleSVGOpacitySource_ContextStrokeOpacity as u8) << SHIFT; + self.gecko.${gecko_ffi_name} = 1.; + } + } + } + + pub fn copy_${ident}_from(&mut self, other: &Self) { + use gecko_bindings::structs::nsStyleSVG_${source_prefix}_MASK as MASK; + self.gecko.${gecko_ffi_name} = other.gecko.${gecko_ffi_name}; + self.gecko.mContextFlags = + (self.gecko.mContextFlags & !MASK) | + (other.gecko.mContextFlags & MASK); + } + + pub fn reset_${ident}(&mut self, other: &Self) { + self.copy_${ident}_from(other) + } + + pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { + use gecko_bindings::structs::nsStyleSVG_${source_prefix}_MASK as MASK; + use gecko_bindings::structs::nsStyleSVG_${source_prefix}_SHIFT as SHIFT; + use gecko_bindings::structs::nsStyleSVGOpacitySource::*; + use values::generics::svg::SVGOpacity; + + let source = (self.gecko.mContextFlags & MASK) >> SHIFT; + if source == eStyleSVGOpacitySource_Normal as u8 { + return SVGOpacity::Opacity(self.gecko.${gecko_ffi_name}); + } else { + debug_assert_eq!(self.gecko.${gecko_ffi_name}, 1.0); + if source == eStyleSVGOpacitySource_ContextFillOpacity as u8 { + SVGOpacity::ContextFillOpacity + } else { + debug_assert_eq!(source, eStyleSVGOpacitySource_ContextStrokeOpacity as u8); + SVGOpacity::ContextStrokeOpacity + } + } + } +</%def> + <%def name="impl_svg_paint(ident, gecko_ffi_name, need_clone=False)"> #[allow(non_snake_case)] pub fn set_${ident}(&mut self, mut v: longhands::${ident}::computed_value::T) { @@ -1024,6 +1085,7 @@ impl Clone for ${style_struct.gecko_struct_name} { "Color": impl_color, "RGBAColor": impl_rgba_color, "SVGLength": impl_svg_length, + "SVGOpacity": impl_svg_opacity, "SVGPaint": impl_svg_paint, "UrlOrNone": impl_css_url, } diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index 3ddbac0b2b7..4419e2921fe 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -46,7 +46,7 @@ use values::computed::{LengthOrPercentage, MaxLength, MozLength, Percentage, ToC use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius; use values::generics::effects::Filter; use values::generics::position as generic_position; -use values::generics::svg::{SVGLength, SVGPaint, SVGPaintKind, SVGStrokeDashArray}; +use values::generics::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind, SVGStrokeDashArray}; /// A trait used to implement various procedures used during animation. pub trait Animatable: Sized { @@ -3116,6 +3116,45 @@ impl<LengthType> ToAnimatedZero for SVGStrokeDashArray<LengthType> } } +impl<OpacityType> Animatable for SVGOpacity<OpacityType> + where OpacityType: Animatable + Clone +{ + #[inline] + fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> { + match (self, other) { + (&SVGOpacity::Opacity(ref this), &SVGOpacity::Opacity(ref other)) => { + this.add_weighted(other, self_portion, other_portion).map(SVGOpacity::Opacity) + } + _ => { + Ok(if self_portion > other_portion { self.clone() } else { other.clone() }) + } + } + } + + #[inline] + fn compute_distance(&self, other: &Self) -> Result<f64, ()> { + match (self, other) { + (&SVGOpacity::Opacity(ref this), &SVGOpacity::Opacity(ref other)) => { + this.compute_distance(other) + } + _ => Err(()) + } + } +} + +impl<OpacityType> ToAnimatedZero for SVGOpacity<OpacityType> + where OpacityType: ToAnimatedZero + Clone +{ + #[inline] + fn to_animated_zero(&self) -> Result<Self, ()> { + match self { + &SVGOpacity::Opacity(ref opacity) => + opacity.to_animated_zero().map(SVGOpacity::Opacity), + other => Ok(other.clone()), + } + } +} + <% FILTER_FUNCTIONS = [ 'Blur', 'Brightness', 'Contrast', 'Grayscale', 'HueRotate', 'Invert', 'Opacity', 'Saturate', diff --git a/components/style/properties/longhand/inherited_svg.mako.rs b/components/style/properties/longhand/inherited_svg.mako.rs index 5e95b81f8c5..053dd168629 100644 --- a/components/style/properties/longhand/inherited_svg.mako.rs +++ b/components/style/properties/longhand/inherited_svg.mako.rs @@ -39,7 +39,7 @@ ${helpers.predefined_type( boxed=True, spec="https://www.w3.org/TR/SVG2/painting.html#SpecifyingFillPaint")} -${helpers.predefined_type("fill-opacity", "Opacity", "1.0", +${helpers.predefined_type("fill-opacity", "SVGOpacity", "Default::default()", products="gecko", animation_value_type="ComputedValue", spec="https://www.w3.org/TR/SVG11/painting.html#FillOpacityProperty")} @@ -85,7 +85,7 @@ ${helpers.predefined_type("stroke-miterlimit", "Number", "4.0", animation_value_type="ComputedValue", spec="https://www.w3.org/TR/SVG11/painting.html#StrokeMiterlimitProperty")} -${helpers.predefined_type("stroke-opacity", "Opacity", "1.0", +${helpers.predefined_type("stroke-opacity", "SVGOpacity", "Default::default()", products="gecko", animation_value_type="ComputedValue", spec="https://www.w3.org/TR/SVG11/painting.html#StrokeOpacityProperty")} diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index e795e46436b..75dea7bf87b 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -44,7 +44,7 @@ pub use super::specified::url::SpecifiedUrl; pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNone, LengthOrNumber, LengthOrPercentage}; pub use self::length::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone, MaxLength, MozLength, Percentage}; pub use self::position::Position; -pub use self::svg::{SVGLength, SVGPaint, SVGPaintKind, SVGStrokeDashArray}; +pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind, SVGStrokeDashArray}; pub use self::text::{InitialLetter, LetterSpacing, LineHeight, WordSpacing}; pub use self::transform::{TimingFunction, TransformOrigin}; diff --git a/components/style/values/computed/svg.rs b/components/style/values/computed/svg.rs index c75df522adc..9edc7a36220 100644 --- a/components/style/values/computed/svg.rs +++ b/components/style/values/computed/svg.rs @@ -6,7 +6,7 @@ use app_units::Au; use values::{Either, RGBA}; -use values::computed::LengthOrPercentageOrNumber; +use values::computed::{LengthOrPercentageOrNumber, Opacity}; use values::generics::svg as generic; /// Computed SVG Paint value @@ -51,3 +51,12 @@ impl Default for SVGStrokeDashArray { generic::SVGStrokeDashArray::Values(vec![]) } } + +/// <opacity-value> | context-fill-opacity | context-stroke-opacity +pub type SVGOpacity = generic::SVGOpacity<Opacity>; + +impl Default for SVGOpacity { + fn default() -> Self { + generic::SVGOpacity::Opacity(1.) + } +} diff --git a/components/style/values/generics/svg.rs b/components/style/values/generics/svg.rs index 4ed833a9600..0970cd9b4fd 100644 --- a/components/style/values/generics/svg.rs +++ b/components/style/values/generics/svg.rs @@ -138,3 +138,16 @@ impl<LengthType> ToCss for SVGStrokeDashArray<LengthType> where LengthType: ToCs } } } + +/// An SVG opacity value accepts `context-{fill,stroke}-opacity` in +/// addition to opacity value. +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[derive(Clone, Copy, Debug, PartialEq, HasViewportPercentage, ToComputedValue, ToCss)] +pub enum SVGOpacity<OpacityType> { + /// `<opacity-value>` + Opacity(OpacityType), + /// `context-fill-opacity` + ContextFillOpacity, + /// `context-stroke-opacity` + ContextStrokeOpacity, +} diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index ae806c24c10..1728d4113d4 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -43,7 +43,7 @@ pub use self::length::{LengthOrPercentageOrNone, MaxLength, MozLength}; pub use self::length::{NoCalcLength, Percentage, ViewportPercentageLength}; pub use self::rect::LengthOrNumberRect; pub use self::position::{Position, PositionComponent}; -pub use self::svg::{SVGLength, SVGPaint, SVGPaintKind, SVGStrokeDashArray}; +pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind, SVGStrokeDashArray}; pub use self::text::{InitialLetter, LetterSpacing, LineHeight, WordSpacing}; pub use self::transform::{TimingFunction, TransformOrigin}; pub use super::generics::grid::GridLine; diff --git a/components/style/values/specified/svg.rs b/components/style/values/specified/svg.rs index 7c364f59773..a89ba3ad15e 100644 --- a/components/style/values/specified/svg.rs +++ b/components/style/values/specified/svg.rs @@ -8,7 +8,7 @@ use cssparser::Parser; use parser::{Parse, ParserContext}; use style_traits::{CommaWithSpace, ParseError, Separator, StyleParseError}; use values::generics::svg as generic; -use values::specified::LengthOrPercentageOrNumber; +use values::specified::{LengthOrPercentageOrNumber, Opacity}; use values::specified::color::RGBAColor; /// Specified SVG Paint value @@ -87,3 +87,22 @@ impl Parse for SVGStrokeDashArray { } } } + +/// <opacity-value> | context-fill-opacity | context-stroke-opacity +pub type SVGOpacity = generic::SVGOpacity<Opacity>; + +impl Parse for SVGOpacity { + fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) + -> Result<Self, ParseError<'i>> { + if let Ok(opacity) = input.try(|i| Opacity::parse(context, i)) { + Ok(generic::SVGOpacity::Opacity(opacity)) + } else if is_context_value_enabled() { + try_match_ident_ignore_ascii_case! { input.expect_ident()?, + "context-fill-opacity" => Ok(generic::SVGOpacity::ContextFillOpacity), + "context-stroke-opacity" => Ok(generic::SVGOpacity::ContextStrokeOpacity), + } + } else { + Err(StyleParseError::UnspecifiedError.into()) + } + } +} |