aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXidorn Quan <me@upsuper.org>2017-08-02 09:27:49 +1000
committerXidorn Quan <me@upsuper.org>2017-08-02 10:35:18 +1000
commitef4352d2a549ebd8aff28cb606db18ac76e50e3a (patch)
tree6fa2520f7d99c48d1ccf67500323d1a959d68bb4
parent7827ca6bb5faa78dbaf108e1cd6c499a966e52bc (diff)
downloadservo-ef4352d2a549ebd8aff28cb606db18ac76e50e3a.tar.gz
servo-ef4352d2a549ebd8aff28cb606db18ac76e50e3a.zip
Add context-{fill,stroke}-opacity support to {fill,stroke}-opacity.
-rw-r--r--components/style/properties/gecko.mako.rs62
-rw-r--r--components/style/properties/helpers/animated_properties.mako.rs41
-rw-r--r--components/style/properties/longhand/inherited_svg.mako.rs4
-rw-r--r--components/style/values/computed/mod.rs2
-rw-r--r--components/style/values/computed/svg.rs11
-rw-r--r--components/style/values/generics/svg.rs13
-rw-r--r--components/style/values/specified/mod.rs2
-rw-r--r--components/style/values/specified/svg.rs21
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())
+ }
+ }
+}