diff --git a/components/style/build_gecko.rs b/components/style/build_gecko.rs index 2f2d95656fe..e0b3d14452e 100644 --- a/components/style/build_gecko.rs +++ b/components/style/build_gecko.rs @@ -365,6 +365,7 @@ mod bindings { "nsStylePadding", "nsStylePosition", "nsStyleSVG", + "nsStyleSVGPaint", "nsStyleSVGReset", "nsStyleTable", "nsStyleTableBorder", @@ -568,6 +569,7 @@ mod bindings { "nsStylePosition", "nsStyleQuoteValues", "nsStyleSVG", + "nsStyleSVGPaint", "nsStyleSVGReset", "nsStyleTable", "nsStyleTableBorder", diff --git a/components/style/gecko_bindings/bindings.rs b/components/style/gecko_bindings/bindings.rs index 39abe447a98..8b475831452 100644 --- a/components/style/gecko_bindings/bindings.rs +++ b/components/style/gecko_bindings/bindings.rs @@ -118,6 +118,9 @@ unsafe impl Sync for nsStyleQuoteValues {} use gecko_bindings::structs::nsStyleSVG; unsafe impl Send for nsStyleSVG {} unsafe impl Sync for nsStyleSVG {} +use gecko_bindings::structs::nsStyleSVGPaint; +unsafe impl Send for nsStyleSVGPaint {} +unsafe impl Sync for nsStyleSVGPaint {} use gecko_bindings::structs::nsStyleSVGReset; unsafe impl Send for nsStyleSVGReset {} unsafe impl Sync for nsStyleSVGReset {} @@ -719,6 +722,17 @@ extern "C" { pub fn Gecko_nsStyleFilter_SetURLValue(effects: *mut nsStyleFilter, uri: ServoBundledURI); } +extern "C" { + pub fn Gecko_nsStyleSVGPaint_CopyFrom(dest: *mut nsStyleSVGPaint, + src: *const nsStyleSVGPaint); +} +extern "C" { + pub fn Gecko_nsStyleSVGPaint_SetURLValue(paint: *mut nsStyleSVGPaint, + uri: ServoBundledURI); +} +extern "C" { + pub fn Gecko_nsStyleSVGPaint_Reset(paint: *mut nsStyleSVGPaint); +} extern "C" { pub fn Gecko_FillAllBackgroundLists(layers: *mut nsStyleImageLayers, max_len: u32); diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 3a5710643cf..2ba1ca34c30 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -11,6 +11,7 @@ <%namespace name="helpers" file="/helpers.mako.rs" /> use app_units::Au; +use cssparser::Color; use custom_properties::ComputedValuesMap; use gecko_bindings::bindings; % for style_struct in data.style_structs: @@ -274,6 +275,19 @@ def set_gecko_property(ffi_name, expr): } + +/// Convert a Servo color into an nscolor; with currentColor as 0 +/// +/// Call sites will need to be updated after https://bugzilla.mozilla.org/show_bug.cgi?id=760345 +fn color_to_nscolor_zero_currentcolor(color: Color) -> structs::nscolor { + match color { + Color::RGBA(rgba) => { + convert_rgba_to_nscolor(&rgba) + }, + Color::CurrentColor => 0, + } +} + <%def name="impl_color_setter(ident, gecko_ffi_name, complex_color=True)"> #[allow(unreachable_code)] #[allow(non_snake_case)] @@ -281,12 +295,7 @@ def set_gecko_property(ffi_name, expr): % if complex_color: let result = v.into(); % else: - use cssparser::Color; - let result = match v { - Color::RGBA(rgba) => convert_rgba_to_nscolor(&rgba), - // FIXME #13547 - Color::CurrentColor => 0, - }; + let result = color_to_nscolor_zero_currentcolor(v); % endif ${set_gecko_property(gecko_ffi_name, "result")} } @@ -306,7 +315,6 @@ def set_gecko_property(ffi_name, expr): % if complex_color: ${get_gecko_property(gecko_ffi_name)}.into() % else: - use cssparser::Color; Color::RGBA(convert_nscolor_to_rgba(${get_gecko_property(gecko_ffi_name)})) % endif } @@ -369,6 +377,54 @@ def set_gecko_property(ffi_name, expr): % endif +<%def name="impl_svg_paint(ident, gecko_ffi_name, need_clone=False, complex_color=True)"> + #[allow(non_snake_case)] + pub fn set_${ident}(&mut self, mut v: longhands::${ident}::computed_value::T) { + use values::computed::SVGPaintKind; + use self::structs::nsStyleSVGPaintType; + + let ref mut paint = ${get_gecko_property(gecko_ffi_name)}; + unsafe { + bindings::Gecko_nsStyleSVGPaint_Reset(paint); + } + let fallback = v.fallback.take(); + match v.kind { + SVGPaintKind::None => return, + SVGPaintKind::ContextFill => { + paint.mType = nsStyleSVGPaintType::eStyleSVGPaintType_ContextFill; + } + SVGPaintKind::ContextStroke => { + paint.mType = nsStyleSVGPaintType::eStyleSVGPaintType_ContextStroke; + } + SVGPaintKind::PaintServer(url) => { + unsafe { + bindings::Gecko_nsStyleSVGPaint_SetURLValue(paint, url.for_ffi()); + } + } + SVGPaintKind::Color(color) => { + paint.mType = nsStyleSVGPaintType::eStyleSVGPaintType_Color; + unsafe { + *paint.mPaint.mColor.as_mut() = color_to_nscolor_zero_currentcolor(color); + } + } + } + + if let Some(fallback) = fallback { + paint.mFallbackColor = color_to_nscolor_zero_currentcolor(fallback); + } + } + + #[allow(non_snake_case)] + pub fn copy_${ident}_from(&mut self, other: &Self) { + unsafe { + bindings::Gecko_nsStyleSVGPaint_CopyFrom( + &mut ${get_gecko_property(gecko_ffi_name)}, + & ${get_gecko_property(gecko_ffi_name, "other")} + ); + } + } + + <%def name="impl_app_units(ident, gecko_ffi_name, need_clone, round_to_pixels=False)"> #[allow(non_snake_case)] pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) { @@ -543,6 +599,7 @@ impl Debug for ${style_struct.gecko_struct_name} { "Number": impl_simple, "Opacity": impl_simple, "CSSColor": impl_color, + "SVGPaint": impl_svg_paint, } def longhand_method(longhand): @@ -2130,7 +2187,6 @@ fn static_assert() { <%self:impl_trait style_struct_name="Effects" skip_longhands="box-shadow filter"> pub fn set_box_shadow(&mut self, v: longhands::box_shadow::computed_value::T) { - use cssparser::Color; self.gecko.mBoxShadow.replace_with_new(v.0.len() as u32); @@ -2161,8 +2217,6 @@ fn static_assert() { } pub fn clone_box_shadow(&self) -> longhands::box_shadow::computed_value::T { - use cssparser::Color; - let buf = self.gecko.mBoxShadow.iter().map(|shadow| { longhands::box_shadow::single_value::computed_value::T { offset_x: Au(shadow.mXOffset), @@ -2177,7 +2231,6 @@ fn static_assert() { } pub fn set_filter(&mut self, v: longhands::filter::computed_value::T) { - use cssparser::Color; use properties::longhands::filter::computed_value::Filter::*; use gecko_bindings::structs::nsCSSShadowArray; use gecko_bindings::structs::nsStyleFilter; @@ -2304,7 +2357,6 @@ fn static_assert() { ${impl_keyword('text_align', 'mTextAlign', text_align_keyword, need_clone=False)} pub fn set_text_shadow(&mut self, v: longhands::text_shadow::computed_value::T) { - use cssparser::Color; self.gecko.mTextShadow.replace_with_new(v.0.len() as u32); for (servo, gecko_shadow) in v.0.into_iter() @@ -2332,7 +2384,6 @@ fn static_assert() { } pub fn clone_text_shadow(&self) -> longhands::text_shadow::computed_value::T { - use cssparser::Color; let buf = self.gecko.mTextShadow.iter().map(|shadow| { longhands::text_shadow::computed_value::TextShadow { @@ -2720,6 +2771,11 @@ clip-path } +<%self:impl_trait style_struct_name="InheritedSVG" + skip_longhands="" + skip_additionals="*"> + + <%self:impl_trait style_struct_name="Color" skip_longhands="*"> pub fn set_color(&mut self, v: longhands::color::computed_value::T) { diff --git a/components/style/properties/longhand/inherited_svg.mako.rs b/components/style/properties/longhand/inherited_svg.mako.rs index 56987f0ba75..7ac8feb2d1a 100644 --- a/components/style/properties/longhand/inherited_svg.mako.rs +++ b/components/style/properties/longhand/inherited_svg.mako.rs @@ -33,6 +33,14 @@ ${helpers.single_keyword("color-interpolation-filters", "auto sRGB linearRGB", animatable=False, spec="https://www.w3.org/TR/SVG11/painting.html#ColorInterpolationFiltersProperty")} +${helpers.predefined_type( + "fill", "SVGPaint", + "::values::computed::SVGPaint::black()", + products="gecko", + animatable=False, + boxed=True, + spec="https://www.w3.org/TR/SVG2/painting.html#SpecifyingFillPaint")} + ${helpers.predefined_type("fill-opacity", "Opacity", "1.0", products="gecko", animatable=False, spec="https://www.w3.org/TR/SVG11/painting.html#FillOpacityProperty")} @@ -49,6 +57,14 @@ ${helpers.single_keyword("shape-rendering", animatable=False, spec="https://www.w3.org/TR/SVG11/painting.html#ShapeRenderingProperty")} +${helpers.predefined_type( + "stroke", "SVGPaint", + "Default::default()", + products="gecko", + animatable=False, + boxed=True, + spec="https://www.w3.org/TR/SVG2/painting.html#SpecifyingStrokePaint")} + ${helpers.single_keyword("stroke-linecap", "butt round square", products="gecko", animatable=False, spec="https://www.w3.org/TR/SVG11/painting.html#StrokeLinecapProperty")} diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 7df1e1fab67..7549c82420f 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -10,7 +10,7 @@ use font_metrics::FontMetricsProvider; use properties::ComputedValues; use std::fmt; use style_traits::ToCss; -use super::{CSSFloat, specified}; +use super::{CSSFloat, RGBA, specified}; pub use cssparser::Color as CSSColor; pub use self::image::{AngleOrCorner, EndingShape as GradientShape, Gradient, GradientKind, Image}; @@ -197,6 +197,26 @@ pub struct SVGPaint { pub fallback: Option, } +impl Default for SVGPaint { + fn default() -> Self { + SVGPaint { + kind: SVGPaintKind::None, + fallback: None, + } + } +} + +impl SVGPaint { + /// Opaque black color + pub fn black() -> Self { + let rgba = RGBA::from_floats(0., 0., 0., 1.); + SVGPaint { + kind: SVGPaintKind::Color(CSSColor::RGBA(rgba)), + fallback: None, + } + } +} + /// An SVG paint value without the fallback /// /// Whereas the spec only allows PaintServer diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 2987f1cf459..642fb96bec6 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -670,6 +670,8 @@ impl Shadow { } } +no_viewport_percentage!(SVGPaint); + /// An SVG paint value /// /// https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint