Create RGBAColor for colors compute to RGBA. r?manishearth draft
authorXidorn Quan <me@upsuper.org>
Tue, 06 Jun 2017 21:05:41 +1000
changeset 590138 0869b6408b7d7d1d2a6deffbbd3dae169a0552d2
parent 590137 e143b9906704165f1a6374d3a0fde5e57736b9f7
child 590139 899a1a8b3feec08c40a9727b00e424143e042af4
push id62604
push userxquan@mozilla.com
push dateWed, 07 Jun 2017 07:07:54 +0000
reviewersmanishearth
milestone55.0a1
Create RGBAColor for colors compute to RGBA. r?manishearth This is a transitional value type before we support computed-value time currentcolor everywhere. Servo would be slightly regressed for places where Gecko doesn't support computed-value time currentcolor but Servo does, for example, stop color in gradients. This should be fixed in the future as we getting rid of RGBAColor. MozReview-Commit-ID: 4G1WkIcEU8S
servo/components/layout/display_list_builder.rs
servo/components/style/gecko/conversions.rs
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/helpers/animated_properties.mako.rs
servo/components/style/properties/longhand/border.mako.rs
servo/components/style/properties/longhand/svg.mako.rs
servo/components/style/values/computed/color.rs
servo/components/style/values/computed/image.rs
servo/components/style/values/computed/mod.rs
servo/components/style/values/specified/color.rs
servo/components/style/values/specified/image.rs
servo/components/style/values/specified/mod.rs
--- a/servo/components/layout/display_list_builder.rs
+++ b/servo/components/layout/display_list_builder.rs
@@ -607,17 +607,17 @@ fn build_border_radius_for_inner_rect(ou
 
     radii.bottom_left.height = cmp::max(Au(0), radii.bottom_left.height - border_widths.bottom);
     radii.bottom_right.height = cmp::max(Au(0), radii.bottom_right.height - border_widths.bottom);
     radii
 }
 
 fn convert_gradient_stops(gradient_items: &[GradientItem],
                           total_length: Au,
-                          style: &ServoComputedValues) -> Vec<GradientStop> {
+                          _style: &ServoComputedValues) -> Vec<GradientStop> {
     // Determine the position of each stop per CSS-IMAGES ยง 3.4.
 
     // Only keep the color stops, discard the color interpolation hints.
     let mut stop_items = gradient_items.iter().filter_map(|item| {
         match *item {
             GenericGradientItem::ColorStop(ref stop) => Some(*stop),
             _ => None,
         }
@@ -694,17 +694,17 @@ fn convert_gradient_stops(gradient_items
             }
             Some(position) => {
                 stop_run = None;
                 position_to_offset(position, total_length)
             }
         };
         stops.push(GradientStop {
             offset: offset,
-            color: style.resolve_color(stop.color).to_gfx_color()
+            color: stop.color.to_gfx_color()
         })
     }
     stops
 }
 
 #[inline]
 /// Duplicate the first and last stops if necessary.
 ///
--- a/servo/components/style/gecko/conversions.rs
+++ b/servo/components/style/gecko/conversions.rs
@@ -178,17 +178,16 @@ impl nsStyleImage {
                 unsafe {
                     Gecko_SetImageElement(self, element.as_ptr());
                 }
             }
         }
     }
 
     fn set_gradient(&mut self, gradient: Gradient) {
-        use cssparser::Color as CSSColor;
         use gecko_bindings::structs::{NS_STYLE_GRADIENT_SHAPE_CIRCULAR, NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL};
         use gecko_bindings::structs::{NS_STYLE_GRADIENT_SHAPE_LINEAR, NS_STYLE_GRADIENT_SIZE_CLOSEST_CORNER};
         use gecko_bindings::structs::{NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE, NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE};
         use gecko_bindings::structs::{NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER, NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE};
         use gecko_bindings::structs::nsStyleCoord;
         use values::computed::image::LineDirection;
         use values::generics::image::{Circle, Ellipse, EndingShape, GradientKind, ShapeExtent};
         use values::specified::position::{X, Y};
@@ -316,29 +315,17 @@ impl nsStyleImage {
 
             let mut gecko_stop = unsafe {
                 &mut (*gecko_gradient).mStops[index]
             };
             let mut coord = nsStyleCoord::null();
 
             match *item {
                 GradientItem::ColorStop(ref stop) => {
-                    gecko_stop.mColor = match stop.color {
-                        CSSColor::CurrentColor => {
-                            // TODO(emilio): gecko just stores an nscolor,
-                            // and it doesn't seem to support currentColor
-                            // as value in a gradient.
-                            //
-                            // Double-check it and either remove
-                            // currentColor for servo or see how gecko
-                            // handles this.
-                            0
-                        },
-                        CSSColor::RGBA(ref rgba) => convert_rgba_to_nscolor(rgba),
-                    };
+                    gecko_stop.mColor = convert_rgba_to_nscolor(&stop.color);
                     gecko_stop.mIsInterpolationHint = false;
                     coord.set(stop.position);
                 },
                 GradientItem::InterpolationHint(hint) => {
                     gecko_stop.mIsInterpolationHint = true;
                     coord.set(Some(hint));
                 }
             }
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -308,36 +308,28 @@ def set_gecko_property(ffi_name, expr):
             % endfor
             % if keyword.gecko_inexhaustive:
             x => panic!("Found unexpected value in style struct for ${ident} property: {:?}", x),
             % endif
         }
     }
 </%def>
 
-/// 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)]
     pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
         % if complex_color:
             let result = v.into();
         % else:
-            let result = color_to_nscolor_zero_currentcolor(v);
+            let result = match color {
+                Color::RGBA(rgba) => convert_rgba_to_nscolor(&rgba),
+                // FIXME handle currentcolor
+                Color::CurrentColor => 0,
+            };
         % endif
         ${set_gecko_property(gecko_ffi_name, "result")}
     }
 </%def>
 
 <%def name="impl_color_copy(ident, gecko_ffi_name, complex_color=True)">
     #[allow(non_snake_case)]
     pub fn copy_${ident}_from(&mut self, other: &Self) {
@@ -408,16 +400,30 @@ fn color_to_nscolor_zero_currentcolor(co
 <%def name="impl_color(ident, gecko_ffi_name, need_clone=False, complex_color=True)">
 <%call expr="impl_color_setter(ident, gecko_ffi_name, complex_color)"></%call>
 <%call expr="impl_color_copy(ident, gecko_ffi_name, complex_color)"></%call>
 % if need_clone:
     <%call expr="impl_color_clone(ident, gecko_ffi_name, complex_color)"></%call>
 % endif
 </%def>
 
+<%def name="impl_rgba_color(ident, gecko_ffi_name, need_clone=False)">
+    #[allow(non_snake_case)]
+    pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
+        ${set_gecko_property(gecko_ffi_name, "convert_rgba_to_nscolor(&v)")}
+    }
+<%call expr="impl_simple_copy(ident, gecko_ffi_name)"></%call>
+% if need_clone:
+    #[allow(non_snake_case)]
+    pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
+        convert_nscolor_to_rgba(${get_gecko_property(gecko_ffi_name)})
+    }
+% endif
+</%def>
+
 <%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::generics::SVGPaintKind;
         use self::structs::nsStyleSVGPaintType;
         use self::structs::nsStyleSVGFallbackType;
 
         let ref mut paint = ${get_gecko_property(gecko_ffi_name)};
@@ -436,24 +442,24 @@ fn color_to_nscolor_zero_currentcolor(co
             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);
+                    *paint.mPaint.mColor.as_mut() = convert_rgba_to_nscolor(&color);
                 }
             }
         }
 
         if let Some(fallback) = fallback {
             paint.mFallbackType = nsStyleSVGFallbackType::eStyleSVGFallbackType_Color;
-            paint.mFallbackColor = color_to_nscolor_zero_currentcolor(fallback);
+            paint.mFallbackColor = convert_rgba_to_nscolor(&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)},
@@ -464,30 +470,30 @@ fn color_to_nscolor_zero_currentcolor(co
 
     #[allow(non_snake_case)]
     pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
         use values::generics::{SVGPaint, SVGPaintKind};
         use self::structs::nsStyleSVGPaintType;
         use self::structs::nsStyleSVGFallbackType;
         let ref paint = ${get_gecko_property(gecko_ffi_name)};
         let fallback = if let nsStyleSVGFallbackType::eStyleSVGFallbackType_Color = paint.mFallbackType {
-            Some(Color::RGBA(convert_nscolor_to_rgba(paint.mFallbackColor)))
+            Some(convert_nscolor_to_rgba(paint.mFallbackColor))
         } else {
             None
         };
         let kind = match paint.mType {
             nsStyleSVGPaintType::eStyleSVGPaintType_None => SVGPaintKind::None,
             nsStyleSVGPaintType::eStyleSVGPaintType_ContextFill => SVGPaintKind::ContextFill,
             nsStyleSVGPaintType::eStyleSVGPaintType_ContextStroke => SVGPaintKind::ContextStroke,
             nsStyleSVGPaintType::eStyleSVGPaintType_Server => {
                 // FIXME (bug 1353966) this should animate
                 SVGPaintKind::None
             }
             nsStyleSVGPaintType::eStyleSVGPaintType_Color => {
-                unsafe { SVGPaintKind::Color(Color::RGBA(convert_nscolor_to_rgba(*paint.mPaint.mColor.as_ref()))) }
+                unsafe { SVGPaintKind::Color(convert_nscolor_to_rgba(*paint.mPaint.mColor.as_ref())) }
             }
         };
         SVGPaint {
             kind: kind,
             fallback: fallback,
         }
     }
 </%def>
@@ -709,16 +715,17 @@ impl Debug for ${style_struct.gecko_stru
         "LengthOrNone": impl_style_coord,
         "LengthOrNormal": impl_style_coord,
         "MaxLength": impl_style_coord,
         "MozLength": impl_style_coord,
         "Number": impl_simple,
         "Integer": impl_simple,
         "Opacity": impl_simple,
         "CSSColor": impl_color,
+        "RGBAColor": impl_rgba_color,
         "SVGPaint": impl_svg_paint,
         "UrlOrNone": impl_css_url,
     }
 
     def longhand_method(longhand):
         args = dict(ident=longhand.ident, gecko_ffi_name=longhand.gecko_ffi_name,
                     need_clone=longhand.need_clone)
 
@@ -940,17 +947,17 @@ fn static_assert() {
             },
             Some(ref colors) => {
                 unsafe {
                     bindings::Gecko_EnsureMozBorderColors(&mut self.gecko);
                     bindings::Gecko_ClearMozBorderColors(&mut self.gecko,
                                                          structs::Side::eSide${to_camel_case(side.ident)});
                 }
                 for color in colors {
-                    let c = color_to_nscolor_zero_currentcolor(*color);
+                    let c = convert_rgba_to_nscolor(color);
                     unsafe {
                         bindings::Gecko_AppendMozBorderColors(&mut self.gecko,
                                                               structs::Side::eSide${to_camel_case(side.ident)},
                                                               c);
                     }
                 }
             }
         }
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.rs
@@ -2718,19 +2718,19 @@ impl From<IntermediateColor> for CSSPars
                                                        color.blue,
                                                        color.alpha)),
             IntermediateColor::CurrentColor => CSSParserColor::CurrentColor,
         }
     }
 }
 
 /// Animatable SVGPaint
-pub type IntermediateSVGPaint = SVGPaint<IntermediateColor>;
+pub type IntermediateSVGPaint = SVGPaint<IntermediateRGBA>;
 /// Animatable SVGPaintKind
-pub type IntermediateSVGPaintKind = SVGPaintKind<IntermediateColor>;
+pub type IntermediateSVGPaintKind = SVGPaintKind<IntermediateRGBA>;
 
 impl From<::values::computed::SVGPaint> for IntermediateSVGPaint {
     fn from(paint: ::values::computed::SVGPaint) -> IntermediateSVGPaint {
         paint.convert(|color| (*color).into())
     }
 }
 
 impl From<IntermediateSVGPaint> for ::values::computed::SVGPaint {
--- a/servo/components/style/properties/longhand/border.mako.rs
+++ b/servo/components/style/properties/longhand/border.mako.rs
@@ -61,31 +61,31 @@
 /// These non-spec properties are just for Gecko (Stylo) internal use.
 % for side in PHYSICAL_SIDES:
     <%helpers:longhand name="-moz-border-${side}-colors" animation_value_type="none"
                        spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-border-*-colors)"
                        products="gecko"
                        ignored_when_colors_disabled="True">
         use std::fmt;
         use style_traits::ToCss;
-        use values::specified::CSSColor;
+        use values::specified::RGBAColor;
         no_viewport_percentage!(SpecifiedValue);
 
         pub mod computed_value {
-            use values::computed::CSSColor;
+            use cssparser::RGBA;
             #[derive(Debug, Clone, PartialEq)]
             #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-            pub struct T(pub Option<Vec<CSSColor>>);
+            pub struct T(pub Option<Vec<RGBA>>);
         }
 
         #[derive(Debug, Clone, PartialEq)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub enum SpecifiedValue {
             None,
-            Colors(Vec<CSSColor>),
+            Colors(Vec<RGBAColor>),
         }
 
         impl ToCss for computed_value::T {
             fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
                 match self.0 {
                     None => return dest.write_str("none"),
                     Some(ref vec) => {
                         let mut first = true;
@@ -163,17 +163,17 @@
         #[inline]
         pub fn parse(context: &ParserContext, input: &mut Parser)
                      -> Result<SpecifiedValue, ()> {
             if input.try(|input| input.expect_ident_matching("none")).is_ok() {
                 return Ok(SpecifiedValue::None)
             }
 
             let mut result = Vec::new();
-            while let Ok(value) = input.try(|i| CSSColor::parse(context, i)) {
+            while let Ok(value) = input.try(|i| RGBAColor::parse(context, i)) {
                 result.push(value);
             }
 
             if !result.is_empty() {
                 Ok(SpecifiedValue::Colors(result))
             } else {
                 Err(())
             }
--- a/servo/components/style/properties/longhand/svg.mako.rs
+++ b/servo/components/style/properties/longhand/svg.mako.rs
@@ -15,43 +15,43 @@
 
 ${helpers.single_keyword("vector-effect", "none non-scaling-stroke",
                          products="gecko", animation_value_type="discrete",
                          spec="https://www.w3.org/TR/SVGTiny12/painting.html#VectorEffectProperty")}
 
 // Section 13 - Gradients and Patterns
 
 ${helpers.predefined_type(
-    "stop-color", "CSSColor",
-    "CSSParserColor::RGBA(RGBA::new(0, 0, 0, 255))",
+    "stop-color", "RGBAColor",
+    "RGBA::new(0, 0, 0, 255)",
     products="gecko",
     animation_value_type="none",
     spec="https://www.w3.org/TR/SVGTiny12/painting.html#StopColorProperty")}
 
 ${helpers.predefined_type("stop-opacity", "Opacity", "1.0",
                           products="gecko",
                           animation_value_type="none",
                           spec="https://www.w3.org/TR/SVGTiny12/painting.html#propdef-stop-opacity")}
 
 // Section 15 - Filter Effects
 
 ${helpers.predefined_type(
-    "flood-color", "CSSColor",
-    "CSSParserColor::RGBA(RGBA::new(0, 0, 0, 255))",
+    "flood-color", "RGBAColor",
+    "RGBA::new(0, 0, 0, 255)",
     products="gecko",
     animation_value_type="none",
     spec="https://www.w3.org/TR/SVG/filters.html#FloodColorProperty")}
 
 ${helpers.predefined_type("flood-opacity", "Opacity",
                           "1.0", products="gecko", animation_value_type="none",
                           spec="https://www.w3.org/TR/SVG/filters.html#FloodOpacityProperty")}
 
 ${helpers.predefined_type(
-    "lighting-color", "CSSColor",
-    "CSSParserColor::RGBA(RGBA::new(255, 255, 255, 255))",
+    "lighting-color", "RGBAColor",
+    "RGBA::new(255, 255, 255, 255)",
     products="gecko",
     animation_value_type="none",
     spec="https://www.w3.org/TR/SVG/filters.html#LightingColorProperty")}
 
 // CSS Masking Module Level 1
 // https://drafts.fxtf.org/css-masking
 ${helpers.single_keyword("mask-type", "luminance alpha",
                          products="gecko", animation_value_type="discrete",
new file mode 100644
--- /dev/null
+++ b/servo/components/style/values/computed/color.rs
@@ -0,0 +1,10 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//! Computed color values.
+
+use cssparser::RGBA;
+
+/// Computed value type for the specified RGBAColor.
+pub type RGBAColor = RGBA;
--- a/servo/components/style/values/computed/image.rs
+++ b/servo/components/style/values/computed/image.rs
@@ -2,17 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! CSS handling for the computed value of
 //! [`image`][image]s
 //!
 //! [image]: https://drafts.csswg.org/css-images/#image-values
 
-use cssparser::Color as CSSColor;
+use cssparser::RGBA;
 use std::f32::consts::PI;
 use std::fmt;
 use style_traits::ToCss;
 use values::{Either, None_};
 use values::computed::{Angle, Context, Length, LengthOrPercentage, NumberOrPercentage, ToComputedValue};
 use values::computed::position::Position;
 use values::generics::image::{CompatMode, ColorStop as GenericColorStop, EndingShape as GenericEndingShape};
 use values::generics::image::{Gradient as GenericGradient, GradientItem as GenericGradientItem};
@@ -30,17 +30,17 @@ pub type Image = GenericImage<Gradient, 
 
 /// Computed values for a CSS gradient.
 /// https://drafts.csswg.org/css-images/#gradients
 pub type Gradient = GenericGradient<
     LineDirection,
     Length,
     LengthOrPercentage,
     Position,
-    CSSColor,
+    RGBA,
 >;
 
 /// A computed gradient kind.
 pub type GradientKind = GenericGradientKind<
     LineDirection,
     Length,
     LengthOrPercentage,
     Position,
@@ -55,20 +55,20 @@ pub enum LineDirection {
     /// A corner.
     Corner(X, Y),
 }
 
 /// A computed radial gradient ending shape.
 pub type EndingShape = GenericEndingShape<Length, LengthOrPercentage>;
 
 /// A computed gradient item.
-pub type GradientItem = GenericGradientItem<CSSColor, LengthOrPercentage>;
+pub type GradientItem = GenericGradientItem<RGBA, LengthOrPercentage>;
 
 /// A computed color stop.
-pub type ColorStop = GenericColorStop<CSSColor, LengthOrPercentage>;
+pub type ColorStop = GenericColorStop<RGBA, LengthOrPercentage>;
 
 /// Computed values for ImageRect.
 pub type ImageRect = GenericImageRect<NumberOrPercentage>;
 
 impl GenericLineDirection for LineDirection {
     fn points_downwards(&self) -> bool {
         match *self {
             LineDirection::Angle(angle) => angle.radians() == PI,
--- a/servo/components/style/values/computed/mod.rs
+++ b/servo/components/style/values/computed/mod.rs
@@ -22,16 +22,17 @@ use super::generics::grid::{TrackBreadth
 use super::generics::grid::TrackList as GenericTrackList;
 use super::specified;
 
 pub use app_units::Au;
 pub use cssparser::Color as CSSColor;
 pub use self::background::BackgroundSize;
 pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth};
 pub use self::border::{BorderRadius, BorderCornerRadius};
+pub use self::color::RGBAColor;
 pub use self::image::{Gradient, GradientItem, ImageLayer, LineDirection, Image, ImageRect};
 pub use self::rect::LengthOrNumberRect;
 pub use super::{Auto, Either, None_};
 #[cfg(feature = "gecko")]
 pub use super::specified::{AlignItems, AlignJustifyContent, AlignJustifySelf, JustifyItems};
 pub use super::specified::{BorderStyle, Percentage, UrlOrNone};
 pub use super::generics::grid::GridLine;
 pub use super::specified::url::SpecifiedUrl;
@@ -40,16 +41,17 @@ pub use self::length::{LengthOrPercentag
 pub use self::length::{MaxLength, MozLength};
 pub use self::position::Position;
 pub use self::text::{LetterSpacing, LineHeight, WordSpacing};
 pub use self::transform::{TimingFunction, TransformOrigin};
 
 pub mod background;
 pub mod basic_shape;
 pub mod border;
+pub mod color;
 pub mod image;
 pub mod length;
 pub mod position;
 pub mod rect;
 pub mod text;
 pub mod transform;
 
 /// A `Context` is all the data a specified value could ever need to compute
@@ -469,35 +471,35 @@ impl IntegerOrAuto {
         match *self {
             Either::First(n) => n,
             Either::Second(Auto) => auto_value,
         }
     }
 }
 
 /// Computed SVG Paint value
-pub type SVGPaint = ::values::generics::SVGPaint<CSSColor>;
+pub type SVGPaint = ::values::generics::SVGPaint<RGBA>;
 /// Computed SVG Paint Kind value
-pub type SVGPaintKind = ::values::generics::SVGPaintKind<CSSColor>;
+pub type SVGPaintKind = ::values::generics::SVGPaintKind<RGBA>;
 
 impl Default for SVGPaint {
     fn default() -> Self {
         SVGPaint {
             kind: ::values::generics::SVGPaintKind::None,
             fallback: None,
         }
     }
 }
 
 impl SVGPaint {
     /// Opaque black color
     pub fn black() -> Self {
         let rgba = RGBA::from_floats(0., 0., 0., 1.);
         SVGPaint {
-            kind: ::values::generics::SVGPaintKind::Color(CSSColor::RGBA(rgba)),
+            kind: ::values::generics::SVGPaintKind::Color(rgba),
             fallback: None,
         }
     }
 }
 
 /// <length> | <percentage> | <number>
 pub type LengthOrPercentageOrNumber = Either<Number, LengthOrPercentage>;
 
--- a/servo/components/style/values/specified/color.rs
+++ b/servo/components/style/values/specified/color.rs
@@ -302,8 +302,61 @@ impl ToComputedValue for CSSColor {
     #[inline]
     fn from_computed_value(computed: &CSSParserColor) -> Self {
         (match *computed {
             CSSParserColor::RGBA(rgba) => Color::RGBA(rgba),
             CSSParserColor::CurrentColor => Color::CurrentColor,
         }).into()
     }
 }
+
+/// Specified color value, but resolved to just RGBA for computed value
+/// with value from color property at the same context.
+#[derive(Clone, PartialEq, Debug)]
+#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+pub struct RGBAColor(pub CSSColor);
+
+no_viewport_percentage!(RGBAColor);
+
+impl Parse for RGBAColor {
+    fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
+        CSSColor::parse(context, input).map(RGBAColor)
+    }
+}
+
+impl ToCss for RGBAColor {
+    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+        self.0.to_css(dest)
+    }
+}
+
+impl ToComputedValue for RGBAColor {
+    type ComputedValue = RGBA;
+
+    fn to_computed_value(&self, context: &Context) -> RGBA {
+        match self.0.to_computed_value(context) {
+            CSSParserColor::RGBA(rgba) => rgba,
+            CSSParserColor::CurrentColor => context.style.get_color().clone_color(),
+        }
+    }
+
+    fn from_computed_value(computed: &RGBA) -> Self {
+        RGBAColor(CSSColor {
+            parsed: Color::RGBA(*computed),
+            authored: None,
+        })
+    }
+}
+
+impl From<Color> for RGBAColor {
+    fn from(color: Color) -> RGBAColor {
+        RGBAColor(CSSColor {
+            parsed: color,
+            authored: None,
+        })
+    }
+}
+
+impl From<CSSColor> for RGBAColor {
+    fn from(color: CSSColor) -> RGBAColor {
+        RGBAColor(color)
+    }
+}
--- a/servo/components/style/values/specified/image.rs
+++ b/servo/components/style/values/specified/image.rs
@@ -19,17 +19,17 @@ use style_traits::ToCss;
 use values::{Either, None_};
 use values::generics::image::{Circle, CompatMode, Ellipse, ColorStop as GenericColorStop};
 use values::generics::image::{EndingShape as GenericEndingShape, Gradient as GenericGradient};
 use values::generics::image::{GradientItem as GenericGradientItem, GradientKind as GenericGradientKind};
 use values::generics::image::{Image as GenericImage, ImageRect as GenericImageRect};
 use values::generics::image::{LineDirection as GenericsLineDirection, ShapeExtent};
 use values::generics::position::Position as GenericPosition;
 use values::specified::{Angle, CSSColor, Color, Length, LengthOrPercentage};
-use values::specified::{Number, NumberOrPercentage, Percentage};
+use values::specified::{Number, NumberOrPercentage, Percentage, RGBAColor};
 use values::specified::position::{Position, PositionComponent, Side, X, Y};
 use values::specified::url::SpecifiedUrl;
 
 /// A specified image layer.
 pub type ImageLayer = Either<None_, Image>;
 
 /// Specified values for an image according to CSS-IMAGES.
 /// https://drafts.csswg.org/css-images/#image-values
@@ -37,17 +37,17 @@ pub type Image = GenericImage<Gradient, 
 
 /// Specified values for a CSS gradient.
 /// https://drafts.csswg.org/css-images/#gradients
 pub type Gradient = GenericGradient<
     LineDirection,
     Length,
     LengthOrPercentage,
     Position,
-    CSSColor,
+    RGBAColor,
 >;
 
 /// A specified gradient kind.
 pub type GradientKind = GenericGradientKind<
     LineDirection,
     Length,
     LengthOrPercentage,
     Position,
@@ -66,20 +66,20 @@ pub enum LineDirection {
     /// A direction towards a corner of a box.
     Corner(X, Y),
 }
 
 /// A specified ending shape.
 pub type EndingShape = GenericEndingShape<Length, LengthOrPercentage>;
 
 /// A specified gradient item.
-pub type GradientItem = GenericGradientItem<CSSColor, LengthOrPercentage>;
+pub type GradientItem = GenericGradientItem<RGBAColor, LengthOrPercentage>;
 
 /// A computed color stop.
-pub type ColorStop = GenericColorStop<CSSColor, LengthOrPercentage>;
+pub type ColorStop = GenericColorStop<RGBAColor, LengthOrPercentage>;
 
 /// Specified values for `moz-image-rect`
 /// -moz-image-rect(<uri>, top, right, bottom, left);
 pub type ImageRect = GenericImageRect<NumberOrPercentage>;
 
 impl Parse for Image {
     fn parse(context: &ParserContext, input: &mut Parser) -> Result<Image, ()> {
         #[cfg(feature = "gecko")]
@@ -378,36 +378,36 @@ impl Gradient {
                         "from" => 0.,
                         "to" => 1.,
                         _ => return Err(()),
                     };
                     let color = CSSColor::parse(context, i)?;
                     if color.parsed == Color::CurrentColor {
                         return Err(());
                     }
-                    Ok((color, p))
+                    Ok((color.into(), p))
                 })?;
                 if reverse_stops {
                     p = 1. - p;
                 }
                 Ok(GenericGradientItem::ColorStop(GenericColorStop {
                     color: color,
                     position: Some(LengthOrPercentage::Percentage(Percentage(p))),
                 }))
             })
         }).unwrap_or(vec![]);
 
         if items.is_empty() {
             items = vec![
                 GenericGradientItem::ColorStop(GenericColorStop {
-                    color: CSSColor::transparent(),
+                    color: CSSColor::transparent().into(),
                     position: Some(Percentage(0.).into()),
                 }),
                 GenericGradientItem::ColorStop(GenericColorStop {
-                    color: CSSColor::transparent(),
+                    color: CSSColor::transparent().into(),
                     position: Some(Percentage(1.).into()),
                 }),
             ];
         } else if items.len() == 1 {
             let first = items[0].clone();
             items.push(first);
         } else {
             items.sort_by(|a, b| {
@@ -662,17 +662,17 @@ impl GradientItem {
         }
         Ok(items)
     }
 }
 
 impl Parse for ColorStop {
     fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
         Ok(ColorStop {
-            color: try!(CSSColor::parse(context, input)),
+            color: try!(RGBAColor::parse(context, input)),
             position: input.try(|i| LengthOrPercentage::parse(context, i)).ok(),
         })
     }
 }
 
 impl Parse for ImageRect {
     fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
         input.try(|i| i.expect_function_matching("-moz-image-rect"))?;
--- a/servo/components/style/values/specified/mod.rs
+++ b/servo/components/style/values/specified/mod.rs
@@ -25,17 +25,17 @@ use super::generics::grid::TrackList as 
 use values::computed::ComputedValueAsSpecified;
 use values::specified::calc::CalcNode;
 
 #[cfg(feature = "gecko")]
 pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, JustifyItems};
 pub use self::background::BackgroundSize;
 pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth};
 pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth};
-pub use self::color::{CSSColor, Color};
+pub use self::color::{CSSColor, Color, RGBAColor};
 pub use self::rect::LengthOrNumberRect;
 pub use super::generics::grid::GridLine;
 pub use self::image::{ColorStop, EndingShape as GradientEndingShape, Gradient};
 pub use self::image::{GradientItem, GradientKind, Image, ImageRect, ImageLayer};
 pub use self::length::AbsoluteLength;
 pub use self::length::{FontRelativeLength, ViewportPercentageLength, CharacterWidth, Length, CalcLengthOrPercentage};
 pub use self::length::{Percentage, LengthOrNone, LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrAuto};
 pub use self::length::{LengthOrPercentageOrNone, LengthOrPercentageOrAutoOrContent, NoCalcLength};
@@ -789,20 +789,20 @@ impl Shadow {
             inset: inset,
         })
     }
 }
 
 no_viewport_percentage!(SVGPaint);
 
 /// Specified SVG Paint value
-pub type SVGPaint = ::values::generics::SVGPaint<CSSColor>;
+pub type SVGPaint = ::values::generics::SVGPaint<RGBAColor>;
 
 /// Specified SVG Paint Kind value
-pub type SVGPaintKind = ::values::generics::SVGPaintKind<CSSColor>;
+pub type SVGPaintKind = ::values::generics::SVGPaintKind<RGBAColor>;
 
 impl ToComputedValue for SVGPaint {
     type ComputedValue = super::computed::SVGPaint;
 
     #[inline]
     fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
         super::computed::SVGPaint {
             kind: self.kind.to_computed_value(context),
@@ -819,22 +819,17 @@ impl ToComputedValue for SVGPaint {
     }
 }
 
 impl ToComputedValue for SVGPaintKind {
     type ComputedValue = super::computed::SVGPaintKind;
 
     #[inline]
     fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
-        self.convert(|color| {
-            match color.parsed {
-                Color::CurrentColor => cssparser::Color::RGBA(context.style().get_color().clone_color()),
-                _ => color.to_computed_value(context),
-            }
-        })
+        self.convert(|color| color.to_computed_value(context))
     }
 
     #[inline]
     fn from_computed_value(computed: &Self::ComputedValue) -> Self {
         computed.convert(ToComputedValue::from_computed_value)
     }
 }