Bug 760345 - Remove the last usage of lossy currentcolor. r=heycam
☠☠ backed out by dd4d744643a3 ☠ ☠
authorEmilio Cobos Álvarez <emilio@crisal.io>
Thu, 04 Apr 2019 22:06:03 +0000
changeset 468101 1ea4b3582033d4d9777590af85c7299f68861ffd
parent 468100 cb5bd749696eb4e1518b9d79295a9bd56320b21c
child 468102 97ab0fa26acf85e4291d0831c054449adad37ebd
push id112682
push userbtara@mozilla.com
push dateFri, 05 Apr 2019 09:57:50 +0000
treeherdermozilla-inbound@a9c1e80ab315 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs760345
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 760345 - Remove the last usage of lossy currentcolor. r=heycam We don't have lossy currentcolor in the style system anymore, except for a single property -moz-font-smoothing-background-color. I could've converted it into a proper StyleColor and thread down all the necessary information to the font metrics code. But it doesn't really seem worth it given it's not exposed to the web, so I just did the simplest thing, which is making currentcolor compute to transparent to that specific property. This patch also removes the stores_complex_colors_lossily code and related, since now we always can cache computed colors. Differential Revision: https://phabricator.services.mozilla.com/D26187
accessible/base/TextAttrs.cpp
dom/canvas/CanvasRenderingContext2D.cpp
editor/libeditor/HTMLAbsPositionEditor.cpp
gfx/src/nsFont.cpp
gfx/src/nsFont.h
gfx/thebes/gfxUtils.cpp
gfx/thebes/gfxUtils.h
layout/generic/nsCanvasFrame.cpp
layout/generic/nsImageFrame.cpp
layout/painting/nsDisplayList.cpp
layout/style/ComputedStyle.cpp
layout/style/StyleColor.cpp
layout/style/StyleColorInlines.h
layout/style/nsComputedDOMStyle.cpp
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/svg/nsFilterInstance.cpp
layout/xul/nsTextBoxFrame.cpp
layout/xul/tree/nsTreeBodyFrame.cpp
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/longhands/background.mako.rs
servo/components/style/properties/longhands/font.mako.rs
servo/components/style/properties/properties.mako.rs
servo/components/style/values/computed/color.rs
servo/components/style/values/computed/mod.rs
servo/components/style/values/specified/color.rs
servo/components/style/values/specified/mod.rs
servo/ports/geckolib/cbindgen.toml
--- a/accessible/base/TextAttrs.cpp
+++ b/accessible/base/TextAttrs.cpp
@@ -343,32 +343,31 @@ bool TextAttrsMgr::BGColorTextAttr::GetC
 
 ////////////////////////////////////////////////////////////////////////////////
 // ColorTextAttr
 ////////////////////////////////////////////////////////////////////////////////
 
 TextAttrsMgr::ColorTextAttr::ColorTextAttr(nsIFrame* aRootFrame,
                                            nsIFrame* aFrame)
     : TTextAttr<nscolor>(!aFrame) {
-  mRootNativeValue = aRootFrame->StyleColor()->mColor;
+  mRootNativeValue = aRootFrame->StyleColor()->mColor.ToColor();
   mIsRootDefined = true;
 
   if (aFrame) {
-    mNativeValue = aFrame->StyleColor()->mColor;
+    mNativeValue = aFrame->StyleColor()->mColor.ToColor();
     mIsDefined = true;
   }
 }
 
 bool TextAttrsMgr::ColorTextAttr::GetValueFor(Accessible* aAccessible,
                                               nscolor* aValue) {
   nsIContent* elm = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
   if (elm) {
-    nsIFrame* frame = elm->GetPrimaryFrame();
-    if (frame) {
-      *aValue = frame->StyleColor()->mColor;
+    if (nsIFrame* frame = elm->GetPrimaryFrame()) {
+      *aValue = frame->StyleColor()->mColor.ToColor();
       return true;
     }
   }
   return false;
 }
 
 void TextAttrsMgr::ColorTextAttr::ExposeValue(
     nsIPersistentProperties* aAttributes, const nscolor& aValue) {
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -996,17 +996,17 @@ bool CanvasRenderingContext2D::ParseColo
   }
 
   if (wasCurrentColor && mCanvasElement) {
     // Otherwise, get the value of the color property, flushing style
     // if necessary.
     RefPtr<ComputedStyle> canvasStyle =
         nsComputedDOMStyle::GetComputedStyle(mCanvasElement, nullptr);
     if (canvasStyle) {
-      *aColor = canvasStyle->StyleColor()->mColor;
+      *aColor = canvasStyle->StyleColor()->mColor.ToColor();
     }
     // Beware that the presShell could be gone here.
   }
   return true;
 }
 
 nsresult CanvasRenderingContext2D::Reset() {
   if (mCanvasElement) {
--- a/editor/libeditor/HTMLAbsPositionEditor.cpp
+++ b/editor/libeditor/HTMLAbsPositionEditor.cpp
@@ -618,20 +618,20 @@ nsresult HTMLEditor::GetTemporaryStyleFo
   }
 
   RefPtr<ComputedStyle> style =
       nsComputedDOMStyle::GetComputedStyle(&aElement, nullptr);
   NS_ENSURE_STATE(style);
 
   const uint8_t kBlackBgTrigger = 0xd0;
 
-  nscolor color = style->StyleColor()->mColor;
-  if (NS_GET_R(color) >= kBlackBgTrigger &&
-      NS_GET_G(color) >= kBlackBgTrigger &&
-      NS_GET_B(color) >= kBlackBgTrigger) {
+  const auto& color = style->StyleColor()->mColor;
+  if (color.red >= kBlackBgTrigger &&
+      color.green >= kBlackBgTrigger &&
+      color.blue >= kBlackBgTrigger) {
     aReturn.AssignLiteral("black");
   } else {
     aReturn.AssignLiteral("white");
   }
 
   return NS_OK;
 }
 
--- a/gfx/src/nsFont.cpp
+++ b/gfx/src/nsFont.cpp
@@ -251,17 +251,17 @@ void nsFont::AddFontFeaturesToStyle(gfxF
   // add in features from font-feature-settings
   aStyle->featureSettings.AppendElements(fontFeatureSettings);
 
   // enable grayscale antialiasing for text
   if (smoothing == NS_FONT_SMOOTHING_GRAYSCALE) {
     aStyle->useGrayscaleAntialiasing = true;
   }
 
-  aStyle->fontSmoothingBackgroundColor = fontSmoothingBackgroundColor;
+  aStyle->fontSmoothingBackgroundColor = fontSmoothingBackgroundColor.ToColor();
 }
 
 void nsFont::AddFontVariationsToStyle(gfxFontStyle* aStyle) const {
   // If auto optical sizing is enabled, and if there's no 'opsz' axis in
   // fontVariationSettings, then set the automatic value on the style.
   class VariationTagComparator {
    public:
     bool Equals(const gfxFontVariation& aVariation, uint32_t aTag) const {
--- a/gfx/src/nsFont.h
+++ b/gfx/src/nsFont.h
@@ -10,17 +10,17 @@
 #include <stdint.h>     // for uint8_t, uint16_t
 #include <sys/types.h>  // for int16_t
 #include "gfxFontFamilyList.h"
 #include "gfxFontConstants.h"  // for NS_FONT_KERNING_AUTO, etc
 #include "gfxFontFeatures.h"
 #include "gfxFontVariations.h"
 #include "mozilla/FontPropertyTypes.h"
 #include "mozilla/RefPtr.h"  // for RefPtr
-#include "nsColor.h"         // for nsColor and NS_RGBA
+#include "mozilla/StyleColorInlines.h" // for StyleRGBA
 #include "nsCoord.h"         // for nscoord
 #include "nsTArray.h"        // for nsTArray
 
 struct gfxFontStyle;
 
 // Font structure.
 struct nsFont {
   typedef mozilla::FontStretch FontStretch;
@@ -46,17 +46,18 @@ struct nsFont {
   // The aspect-value (ie., the ratio actualsize:actualxheight) that any
   // actual physical font created from this font structure must have when
   // rendering or measuring a string. A value of -1.0 means no adjustment
   // needs to be done; otherwise the value must be nonnegative.
   float sizeAdjust = -1.0f;
 
   // The estimated background color behind the text. Enables a special
   // rendering mode when NS_GET_A(.) > 0. Only used for text in the chrome.
-  nscolor fontSmoothingBackgroundColor = NS_RGBA(0, 0, 0, 0);
+  mozilla::StyleRGBA fontSmoothingBackgroundColor =
+      mozilla::StyleRGBA::Transparent();
 
   // Language system tag, to override document language;
   // this is an OpenType "language system" tag represented as a 32-bit integer
   // (see http://www.microsoft.com/typography/otspec/languagetags.htm).
   uint32_t languageOverride = 0;
 
   // Font-selection/rendering properties corresponding to CSS font-style,
   // font-weight, font-stretch. These are all 16-bit types.
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -1560,10 +1560,14 @@ Color ToDeviceColor(Color aColor) {
   }
   return aColor;
 }
 
 Color ToDeviceColor(nscolor aColor) {
   return ToDeviceColor(Color::FromABGR(aColor));
 }
 
+Color ToDeviceColor(const StyleRGBA& aColor) {
+  return ToDeviceColor(aColor.ToColor());
+}
+
 }  // namespace gfx
 }  // namespace mozilla
--- a/gfx/thebes/gfxUtils.h
+++ b/gfx/thebes/gfxUtils.h
@@ -322,26 +322,30 @@ class gfxUtils {
       const mozilla::dom::Element* aElement);
   static mozilla::wr::RenderRoot RecursivelyGetRenderRootForFrame(
       const nsIFrame* aFrame);
   static mozilla::wr::RenderRoot RecursivelyGetRenderRootForElement(
       const mozilla::dom::Element* aElement);
 };
 
 namespace mozilla {
+
+struct StyleRGBA;
+
 namespace gfx {
 
 /**
  * If the CMS mode is eCMSMode_All, these functions transform the passed
  * color to a device color using the transform returened by gfxPlatform::
  * GetCMSRGBTransform().  If the CMS mode is some other value, the color is
  * returned unchanged (other than a type change to Moz2D Color, if
  * applicable).
  */
 Color ToDeviceColor(Color aColor);
+Color ToDeviceColor(const StyleRGBA& aColor);
 Color ToDeviceColor(nscolor aColor);
 
 /**
  * Performs a checked multiply of the given width, height, and bytes-per-pixel
  * values.
  */
 static inline CheckedInt<uint32_t> SafeBytesForBitmap(uint32_t aWidth,
                                                       uint32_t aHeight,
--- a/layout/generic/nsCanvasFrame.cpp
+++ b/layout/generic/nsCanvasFrame.cpp
@@ -630,23 +630,18 @@ void nsCanvasFrame::PaintFocus(DrawTarge
     focusRect.height = portRect.height;
     focusRect.MoveBy(scrollableFrame->GetScrollPosition());
   }
 
   // XXX use the root frame foreground color, but should we find BODY frame
   // for HTML documents?
   nsIFrame* root = mFrames.FirstChild();
   const nsStyleColor* color = root ? root->StyleColor() : StyleColor();
-  if (!color) {
-    NS_ERROR("current color cannot be found");
-    return;
-  }
-
   nsCSSRendering::PaintFocus(PresContext(), aDrawTarget, focusRect,
-                             color->mColor);
+                             color->mColor.ToColor());
 }
 
 /* virtual */
 nscoord nsCanvasFrame::GetMinISize(gfxContext* aRenderingContext) {
   nscoord result;
   DISPLAY_MIN_INLINE_SIZE(this, result);
   if (mFrames.IsEmpty())
     result = 0;
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -1152,17 +1152,17 @@ nscoord nsImageFrame::MeasureString(cons
 
 // Formats the alt-text to fit within the specified rectangle. Breaks lines
 // between words if a word would extend past the edge of the rectangle
 void nsImageFrame::DisplayAltText(nsPresContext* aPresContext,
                                   gfxContext& aRenderingContext,
                                   const nsString& aAltText,
                                   const nsRect& aRect) {
   // Set font and color
-  aRenderingContext.SetColor(Color::FromABGR(StyleColor()->mColor));
+  aRenderingContext.SetColor(Color::FromABGR(StyleColor()->mColor.ToColor()));
   RefPtr<nsFontMetrics> fm =
       nsLayoutUtils::GetInflatedFontMetricsForFrame(this);
 
   // Format the text to display within the formatting rect
 
   nscoord maxAscent = fm->MaxAscent();
   nscoord maxDescent = fm->MaxDescent();
   nscoord lineHeight = fm->MaxHeight();  // line-relative, so an x-coordinate
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -456,27 +456,18 @@ static void SetAnimatable(nsCSSPropertyI
     aAnimatable = null_t();
     return;
   }
 
   switch (aProperty) {
     case eCSSProperty_background_color: {
       // We don't support color animation on the compositor yet so that we can
       // resolve currentColor at this moment.
-      nscolor foreground;
-      if (aFrame->Style()->RelevantLinkVisited()) {
-        if (ComputedStyle* styleIfVisited =
-                aFrame->Style()->GetStyleIfVisited()) {
-          foreground = styleIfVisited->StyleColor()->mColor;
-        } else {
-          foreground = aFrame->Style()->StyleColor()->mColor;
-        }
-      } else {
-        foreground = aFrame->Style()->StyleColor()->mColor;
-      }
+      nscolor foreground =
+          aFrame->Style()->GetVisitedDependentColor(&nsStyleColor::mColor);
       aAnimatable = aAnimationValue.GetColor(foreground);
       break;
     }
     case eCSSProperty_opacity:
       aAnimatable = aAnimationValue.GetOpacity();
       break;
     case eCSSProperty_rotate: {
       RefPtr<const nsCSSValueSharedList> list =
--- a/layout/style/ComputedStyle.cpp
+++ b/layout/style/ComputedStyle.cpp
@@ -273,18 +273,18 @@ static nscolor GetVisitedDependentColorI
     colors[1] = aColorFunc(visitedStyle);
     return ComputedStyle::CombineVisitedColors(colors,
                                                aSc->RelevantLinkVisited());
   }
   return colors[0];
 }
 
 static nscolor ExtractColor(const ComputedStyle& aStyle,
-                            const nscolor& aColor) {
-  return aColor;
+                            const StyleRGBA& aColor) {
+  return aColor.ToColor();
 }
 
 static nscolor ExtractColor(const ComputedStyle& aStyle,
                             const StyleColor& aColor) {
   return aColor.CalcColor(aStyle);
 }
 
 // Currently caret-color, the only property in the list which is a ColorOrAuto,
--- a/layout/style/StyleColor.cpp
+++ b/layout/style/StyleColor.cpp
@@ -10,31 +10,31 @@
 #include "mozilla/ComputedStyleInlines.h"
 #include "nsIFrame.h"
 #include "nsStyleStruct.h"
 
 namespace mozilla {
 
 // Blend one RGBA color with another based on a given ratios.
 // It is a linear combination of each channel with alpha premultipled.
-static nscolor LinearBlendColors(nscolor aBg, float aBgRatio, nscolor aFg,
-                                 float aFgRatio) {
+static nscolor LinearBlendColors(const StyleRGBA& aBg, float aBgRatio,
+                                 const StyleRGBA& aFg, float aFgRatio) {
   constexpr float kFactor = 1.0f / 255.0f;
 
   float p1 = aBgRatio;
-  float a1 = kFactor * NS_GET_A(aBg);
-  float r1 = a1 * NS_GET_R(aBg);
-  float g1 = a1 * NS_GET_G(aBg);
-  float b1 = a1 * NS_GET_B(aBg);
+  float a1 = kFactor * aBg.alpha;
+  float r1 = a1 * aBg.red;
+  float g1 = a1 * aBg.green;
+  float b1 = a1 * aBg.blue;
 
   float p2 = aFgRatio;
-  float a2 = kFactor * NS_GET_A(aFg);
-  float r2 = a2 * NS_GET_R(aFg);
-  float g2 = a2 * NS_GET_G(aFg);
-  float b2 = a2 * NS_GET_B(aFg);
+  float a2 = kFactor * aFg.alpha;
+  float r2 = a2 * aFg.red;
+  float g2 = a2 * aFg.green;
+  float b2 = a2 * aFg.blue;
 
   float a = p1 * a1 + p2 * a2;
   if (a <= 0.f) {
     return NS_RGBA(0, 0, 0, 0);
   }
 
   if (a > 1.f) {
     a = 1.f;
@@ -50,45 +50,44 @@ template <>
 bool StyleColor::MaybeTransparent() const {
   // We know that the color is opaque when it's a numeric color with
   // alpha == 255.
   // TODO(djg): Should we extend this to check Complex with bgRatio =
   // 0, and fgRatio * alpha >= 255?
   return !IsNumeric() || AsNumeric().alpha != 255;
 }
 
-static nscolor RGBAToNSColor(const StyleRGBA& aRGBA) {
-  return NS_RGBA(aRGBA.red, aRGBA.green, aRGBA.blue, aRGBA.alpha);
+template <>
+nscolor StyleColor::CalcColor(nscolor aColor) const {
+  return CalcColor(StyleRGBA::FromColor(aColor));
 }
 
 template <>
-nscolor StyleColor::CalcColor(nscolor aForegroundColor) const {
+nscolor StyleColor::CalcColor(const StyleRGBA& aForegroundColor) const {
   if (IsNumeric()) {
-    return RGBAToNSColor(AsNumeric());
+    return AsNumeric().ToColor();
   }
   if (IsCurrentColor()) {
-    return aForegroundColor;
+    return aForegroundColor.ToColor();
   }
   MOZ_ASSERT(IsComplex());
   const auto& complex = AsComplex();
-  return LinearBlendColors(RGBAToNSColor(complex.color), complex.ratios.bg,
+  return LinearBlendColors(complex.color, complex.ratios.bg,
                            aForegroundColor, complex.ratios.fg);
 }
 
 template <>
 nscolor StyleColor::CalcColor(const ComputedStyle& aStyle) const {
   // Common case that is numeric color, which is pure background, we
   // can skip resolving StyleColor().
   // TODO(djg): Is this optimization worth it?
   if (IsNumeric()) {
-    return RGBAToNSColor(AsNumeric());
+    return AsNumeric().ToColor();
   }
-
-  auto fgColor = aStyle.StyleColor()->mColor;
-  return CalcColor(fgColor);
+  return CalcColor(aStyle.StyleColor()->mColor);
 }
 
 template <>
 nscolor StyleColor::CalcColor(const nsIFrame* aFrame) const {
   return CalcColor(*aFrame->Style());
 }
 
 }  // namespace mozilla
--- a/layout/style/StyleColorInlines.h
+++ b/layout/style/StyleColorInlines.h
@@ -9,20 +9,31 @@
 #ifndef mozilla_StyleColorInlines_h_
 #define mozilla_StyleColorInlines_h_
 
 #include "nsColor.h"
 #include "mozilla/ServoStyleConsts.h"
 
 namespace mozilla {
 
+inline StyleRGBA StyleRGBA::FromColor(nscolor aColor) {
+  return {NS_GET_R(aColor), NS_GET_G(aColor), NS_GET_B(aColor), NS_GET_A(aColor)};
+}
+
+inline nscolor StyleRGBA::ToColor() const {
+  return NS_RGBA(red, green, blue, alpha);
+}
+
+inline StyleRGBA StyleRGBA::Transparent() {
+  return {0, 0, 0, 0};
+}
+
 template<>
 inline StyleColor StyleColor::FromColor(nscolor aColor) {
-  return StyleColor::Numeric({NS_GET_R(aColor), NS_GET_G(aColor),
-                              NS_GET_B(aColor), NS_GET_A(aColor)});
+  return StyleColor::Numeric(StyleRGBA::FromColor(aColor));
 }
 
 template<>
 inline StyleColor StyleColor::Black() {
   return FromColor(NS_RGB(0, 0, 0));
 }
 
 template<>
@@ -31,17 +42,20 @@ inline StyleColor StyleColor::White() {
 }
 
 template<>
 inline StyleColor StyleColor::Transparent() {
   return FromColor(NS_RGBA(0, 0, 0, 0));
 }
 
 template <>
-nscolor StyleColor::CalcColor(nscolor aForegroundColor) const;
+nscolor StyleColor::CalcColor(const StyleRGBA&) const;
+
+template <>
+nscolor StyleColor::CalcColor(nscolor) const;
 
 template <>
 nscolor StyleColor::CalcColor(const ComputedStyle&) const;
 
 template <>
 nscolor StyleColor::CalcColor(const nsIFrame*) const;
 
 }  // namespace mozilla
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -1042,17 +1042,17 @@ void nsComputedDOMStyle::SetToRGBAColor(
 
 void nsComputedDOMStyle::SetValueFromComplexColor(
     nsROCSSPrimitiveValue* aValue, const mozilla::StyleColor& aColor) {
   SetToRGBAColor(aValue, aColor.CalcColor(*mComputedStyle));
 }
 
 already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetColor() {
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-  SetToRGBAColor(val, StyleColor()->mColor);
+  SetToRGBAColor(val, StyleColor()->mColor.ToColor());
   return val.forget();
 }
 
 already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetColumnCount() {
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
 
   const nsStyleColumn* column = StyleColumn();
 
@@ -2137,17 +2137,17 @@ already_AddRefed<CSSValue> nsComputedDOM
 }
 
 static_assert(NS_STYLE_UNICODE_BIDI_NORMAL == 0,
               "unicode-bidi style constants not as expected");
 
 already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetCaretColor() {
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
   if (StyleUI()->mCaretColor.IsAuto()) {
-    SetToRGBAColor(val, StyleColor()->mColor);
+    SetToRGBAColor(val, StyleColor()->mColor.ToColor());
   } else {
     SetValueFromComplexColor(val, StyleUI()->mCaretColor.AsColor());
   }
   return val.forget();
 }
 
 already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetBoxFlex() {
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1667,18 +1667,19 @@ nsChangeHint nsStyleTableBorder::CalcDif
     return NS_STYLE_HINT_REFLOW;
   }
 }
 
 // --------------------
 // nsStyleColor
 //
 
-static nscolor DefaultColor(const Document& aDocument) {
-  return PreferenceSheet::PrefsFor(aDocument).mDefaultColor;
+static StyleRGBA DefaultColor(const Document& aDocument) {
+  return
+    StyleRGBA::FromColor(PreferenceSheet::PrefsFor(aDocument).mDefaultColor);
 }
 
 nsStyleColor::nsStyleColor(const Document& aDocument)
     : mColor(DefaultColor(aDocument)) {
   MOZ_COUNT_CTOR(nsStyleColor);
 }
 
 nsStyleColor::nsStyleColor(const nsStyleColor& aSource)
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -461,17 +461,19 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   ~nsStyleColor() { MOZ_COUNT_DTOR(nsStyleColor); }
   void TriggerImageLoads(mozilla::dom::Document&, const nsStyleColor*) {}
   const static bool kHasTriggerImageLoads = false;
 
   nsChangeHint CalcDifference(const nsStyleColor& aNewData) const;
 
   // Don't add ANY members to this struct!  We can achieve caching in the rule
   // tree (rather than the style tree) by letting color stay by itself! -dwh
-  nscolor mColor;
+  //
+  // FIXME(emilio): Not sure having color in its own struct is worth it anymore.
+  mozilla::StyleRGBA mColor;
 };
 
 struct nsStyleImageLayers {
   // Indices into kBackgroundLayerTable and kMaskLayerTable
   enum {
     shorthand = 0,
     color,
     image,
--- a/layout/svg/nsFilterInstance.cpp
+++ b/layout/svg/nsFilterInstance.cpp
@@ -596,17 +596,17 @@ nsresult nsFilterInstance::BuildPrimitiv
                                              mInputImages, aInputIsTainted);
   }
 
   // Build primitives for a CSS filter.
 
   // If we don't have a frame, use opaque black for shadows with unspecified
   // shadow colors.
   nscolor shadowFallbackColor =
-      mTargetFrame ? mTargetFrame->StyleColor()->mColor : NS_RGB(0, 0, 0);
+      mTargetFrame ? mTargetFrame->StyleColor()->mColor.ToColor() : NS_RGB(0, 0, 0);
 
   nsCSSFilterInstance cssFilterInstance(
       aFilter, shadowFallbackColor, mTargetBounds,
       mFrameSpaceInCSSPxToFilterSpaceTransform);
   return cssFilterInstance.BuildPrimitives(aPrimitiveDescriptions,
                                            aInputIsTainted);
 }
 
--- a/layout/xul/nsTextBoxFrame.cpp
+++ b/layout/xul/nsTextBoxFrame.cpp
@@ -278,17 +278,17 @@ void nsDisplayXULTextBox::Paint(nsDispla
                                 gfxContext* aCtx) {
   DrawTargetAutoDisableSubpixelAntialiasing disable(aCtx->GetDrawTarget(),
                                                     mDisableSubpixelAA);
 
   // Paint the text shadow before doing any foreground stuff
   nsRect drawRect =
       static_cast<nsTextBoxFrame*>(mFrame)->mTextDrawRect + ToReferenceFrame();
   nsLayoutUtils::PaintTextShadow(mFrame, aCtx, drawRect, GetPaintRect(),
-                                 mFrame->StyleColor()->mColor,
+                                 mFrame->StyleColor()->mColor.ToColor(),
                                  PaintTextShadowCallback, (void*)this);
 
   PaintTextToContext(aCtx, nsPoint(0, 0), nullptr);
 }
 
 void nsDisplayXULTextBox::PaintTextToContext(gfxContext* aCtx, nsPoint aOffset,
                                              const nscolor* aColor) {
   static_cast<nsTextBoxFrame*>(mFrame)->PaintTitle(
@@ -483,17 +483,17 @@ void nsTextBoxFrame::DrawText(gfxContext
   }
 
   RefPtr<gfxContext> refContext =
       PresShell()->CreateReferenceRenderingContext();
   DrawTarget* refDrawTarget = refContext->GetDrawTarget();
 
   CalculateUnderline(refDrawTarget, *fontMet);
 
-  nscolor c = aOverrideColor ? *aOverrideColor : StyleColor()->mColor;
+  nscolor c = aOverrideColor ? *aOverrideColor : StyleColor()->mColor.ToColor();
   ColorPattern color(ToDeviceColor(c));
   aRenderingContext.SetColor(Color::FromABGR(c));
 
   nsresult rv = NS_ERROR_FAILURE;
 
   if (mState & NS_FRAME_IS_BIDI) {
     presContext->SetBidiEnabled();
     nsBidiLevel level = nsBidiPresUtils::BidiLevelFromStyle(Style());
--- a/layout/xul/tree/nsTreeBodyFrame.cpp
+++ b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -3480,17 +3480,17 @@ ImgDrawResult nsTreeBodyFrame::PaintText
       GetPseudoComputedStyle(nsCSSAnonBoxes::mozTreeCell());
 
   if (opacity != 1.0f) {
     aRenderingContext.PushGroupForBlendBack(gfxContentType::COLOR_ALPHA,
                                             opacity);
   }
 
   aRenderingContext.SetColor(
-      Color::FromABGR(textContext->StyleColor()->mColor));
+      Color::FromABGR(textContext->StyleColor()->mColor.ToColor()));
   nsLayoutUtils::DrawString(
       this, *fontMet, &aRenderingContext, text.get(), text.Length(),
       textRect.TopLeft() + nsPoint(0, baseline), cellContext);
 
   if (opacity != 1.0f) {
     aRenderingContext.PopGroupAndBlend();
   }
 
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -35,18 +35,16 @@ use crate::gecko_bindings::bindings::Gec
 use crate::gecko_bindings::bindings::Gecko_SetListStyleImageImageValue;
 use crate::gecko_bindings::bindings::Gecko_SetNullImageValue;
 use crate::gecko_bindings::bindings::{Gecko_ResetFilters, Gecko_CopyFiltersFrom};
 use crate::gecko_bindings::structs;
 use crate::gecko_bindings::structs::nsCSSPropertyID;
 use crate::gecko_bindings::structs::mozilla::PseudoStyleType;
 use crate::gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut};
 use crate::gecko_bindings::sugar::refptr::RefPtr;
-use crate::gecko::values::convert_nscolor_to_rgba;
-use crate::gecko::values::convert_rgba_to_nscolor;
 use crate::gecko::values::GeckoStyleCoordConvertible;
 use crate::gecko::values::round_border_to_device_pixels;
 use crate::logical_geometry::WritingMode;
 use crate::media_queries::Device;
 use crate::properties::computed_value_flags::*;
 use crate::properties::longhands;
 use crate::rule_tree::StrongRuleNode;
 use crate::selector_parser::PseudoElement;
@@ -416,28 +414,16 @@ def set_gecko_property(ffi_name, expr):
     }
     <%call expr="impl_simple_copy(ident, gecko_ffi_name)"></%call>
     #[allow(non_snake_case)]
     pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
         Au(self.gecko.${gecko_ffi_name}).into()
     }
 </%def>
 
-<%def name="impl_rgba_color(ident, gecko_ffi_name)">
-    #[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>
-    #[allow(non_snake_case)]
-    pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
-        convert_nscolor_to_rgba(${get_gecko_property(gecko_ffi_name)})
-    }
-</%def>
-
 <%def name="impl_svg_length(ident, gecko_ffi_name)">
     // When context-value is used on an SVG length, the corresponding flag is
     // set on mContextFlags, and the length field is set to the initial value.
 
     pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
         use crate::values::generics::svg::SVGLength;
         use crate::gecko_bindings::structs::nsStyleSVG_${ident.upper()}_CONTEXT as CONTEXT_VALUE;
         let length = match v {
@@ -1201,17 +1187,16 @@ impl Clone for ${style_struct.gecko_stru
     style_struct = next(x for x in data.style_structs if x.name == style_struct_name)
     longhands = [x for x in style_struct.longhands
                 if not (skip_longhands == "*" or x.name in skip_longhands.split())]
 
     # Types used with predefined_type()-defined properties that we can auto-generate.
     predefined_types = {
         "length::NonNegativeLengthPercentageOrNormal": impl_style_coord,
         "MozScriptMinSize": impl_absolute_length,
-        "RGBAColor": impl_rgba_color,
         "SVGLength": impl_svg_length,
         "SVGOpacity": impl_svg_opacity,
         "SVGPaint": impl_svg_paint,
         "SVGWidth": impl_svg_length,
         "Transform": impl_transform,
         "url::UrlOrNone": impl_css_url,
     }
 
@@ -4338,18 +4323,17 @@ clip-path
     }
 
     #[allow(non_snake_case)]
     pub fn reset__moz_context_properties(&mut self, other: &Self) {
         self.copy__moz_context_properties_from(other)
     }
 </%self:impl_trait>
 
-<%self:impl_trait style_struct_name="Color" skip_longhands="color">
-    ${impl_rgba_color("color", "mColor")}
+<%self:impl_trait style_struct_name="Color">
 </%self:impl_trait>
 
 <%self:impl_trait style_struct_name="InheritedUI" skip_longhands="cursor">
     pub fn set_cursor(&mut self, v: longhands::cursor::computed_value::T) {
         self.gecko.mCursor = v.keyword;
         unsafe {
             Gecko_SetCursorArrayLength(&mut self.gecko, v.images.len());
         }
--- a/servo/components/style/properties/longhands/background.mako.rs
+++ b/servo/components/style/properties/longhands/background.mako.rs
@@ -4,17 +4,17 @@
 
 <%namespace name="helpers" file="/helpers.mako.rs" />
 
 <% data.new_style_struct("Background", inherited=False) %>
 
 ${helpers.predefined_type(
     "background-color",
     "Color",
-    "computed_value::T::transparent()",
+    "computed::Color::transparent()",
     initial_specified_value="SpecifiedValue::transparent()",
     spec="https://drafts.csswg.org/css-backgrounds/#background-color",
     animation_value_type="AnimatedColor",
     ignored_when_colors_disabled=True,
     allow_quirks=True,
     flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER \
            CAN_ANIMATE_ON_COMPOSITOR",
 )}
--- a/servo/components/style/properties/longhands/font.mako.rs
+++ b/servo/components/style/properties/longhands/font.mako.rs
@@ -516,19 +516,19 @@ https://drafts.csswg.org/css-fonts-4/#lo
     products="gecko",
     spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/font-smooth)",
     flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
     animation_value_type="discrete",
 )}
 
 ${helpers.predefined_type(
     "-moz-font-smoothing-background-color",
-    "RGBAColor",
-    "RGBA::transparent()",
-    animation_value_type="AnimatedRGBA",
+    "color::MozFontSmoothingBackgroundColor",
+    "computed::color::MozFontSmoothingBackgroundColor::transparent()",
+    animation_value_type="none",
     products="gecko",
     gecko_ffi_name="mFont.fontSmoothingBackgroundColor",
     enabled_in="chrome",
     spec="None (Nonstandard internal property)",
 )}
 
 ${helpers.predefined_type(
     "-moz-min-font-size-ratio",
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -1282,42 +1282,16 @@ impl LonghandId {
             LonghandId::TextDecorationLine |
 
             // Needed to properly compute the writing mode, to resolve logical
             // properties, and similar stuff.
             LonghandId::WritingMode |
             LonghandId::Direction
         )
     }
-
-    /// Whether computed values of this property lossily convert any complex
-    /// colors into RGBA colors.
-    ///
-    /// In Gecko, there are some properties still that compute currentcolor
-    /// down to an RGBA color at computed value time, instead of as
-    /// `StyleColor`s. For these properties, we must return `false`,
-    /// so that we correctly avoid caching style data in the rule tree.
-    pub fn stores_complex_colors_lossily(&self) -> bool {
-        % if product == "gecko":
-        matches!(*self,
-            % for property in data.longhands:
-            % if property.predefined_type == "RGBAColor":
-            LonghandId::${property.camel_case} |
-            % endif
-            % endfor
-            LonghandId::BackgroundImage |
-            LonghandId::BorderImageSource |
-            LonghandId::BoxShadow |
-            LonghandId::MaskImage |
-            LonghandId::TextShadow
-        )
-        % else:
-        false
-        % endif
-    }
 }
 
 /// An iterator over all the property ids that are enabled for a given
 /// shorthand, if that shorthand is enabled for all content too.
 pub struct NonCustomPropertyIterator<Item: 'static> {
     filter: bool,
     iter: std::slice::Iter<'static, Item>,
 }
--- a/servo/components/style/values/computed/color.rs
+++ b/servo/components/style/values/computed/color.rs
@@ -6,24 +6,24 @@
 
 use crate::values::animated::color::RGBA as AnimatedRGBA;
 use crate::values::animated::ToAnimatedValue;
 use crate::values::generics::color::{Color as GenericColor, ColorOrAuto as GenericColorOrAuto};
 use cssparser::{Color as CSSParserColor, RGBA};
 use std::fmt;
 use style_traits::{CssWriter, ToCss};
 
-/// Computed value type for the specified RGBAColor.
-pub type RGBAColor = RGBA;
-
 /// The computed value of the `color` property.
 pub type ColorPropertyValue = RGBA;
 
+/// The computed value of `-moz-font-smoothing-background-color`.
+pub type MozFontSmoothingBackgroundColor = RGBA;
+
 /// A computed value for `<color>`.
-pub type Color = GenericColor<RGBAColor>;
+pub type Color = GenericColor<RGBA>;
 
 impl Color {
     /// Returns a complex color value representing transparent.
     pub fn transparent() -> Color {
         Color::rgba(RGBA::transparent())
     }
 
     /// Combine this complex color with the given foreground color into
--- a/servo/components/style/values/computed/mod.rs
+++ b/servo/components/style/values/computed/mod.rs
@@ -38,17 +38,17 @@ pub use self::basic_shape::FillRule;
 pub use self::border::{BorderCornerRadius, BorderRadius, BorderSpacing};
 pub use self::border::{BorderImageRepeat, BorderImageSideWidth};
 pub use self::border::{BorderImageSlice, BorderImageWidth};
 pub use self::box_::{AnimationIterationCount, AnimationName, Contain};
 pub use self::box_::{Appearance, BreakBetween, BreakWithin, Clear, Float};
 pub use self::box_::{Display, Overflow, OverflowAnchor, TransitionProperty};
 pub use self::box_::{OverflowClipBox, OverscrollBehavior, Perspective, Resize};
 pub use self::box_::{ScrollSnapAlign, ScrollSnapType, TouchAction, VerticalAlign, WillChange};
-pub use self::color::{Color, ColorOrAuto, ColorPropertyValue, RGBAColor};
+pub use self::color::{Color, ColorOrAuto, ColorPropertyValue};
 pub use self::column::ColumnCount;
 pub use self::counters::{Content, ContentItem, CounterIncrement, CounterSetOrReset};
 pub use self::easing::TimingFunction;
 pub use self::effects::{BoxShadow, Filter, SimpleShadow};
 pub use self::flex::FlexBasis;
 pub use self::font::{FontFamily, FontLanguageOverride, FontStyle};
 pub use self::font::{FontFeatureSettings, FontVariantLigatures, FontVariantNumeric};
 pub use self::font::{FontSize, FontSizeAdjust, FontStretch, FontSynthesis};
--- a/servo/components/style/values/specified/color.rs
+++ b/servo/components/style/values/specified/color.rs
@@ -368,67 +368,55 @@ impl Color {
         }
     }
 }
 
 impl ToComputedValue for Color {
     type ComputedValue = ComputedColor;
 
     fn to_computed_value(&self, context: &Context) -> ComputedColor {
-        let result = self.to_computed_color(Some(context)).unwrap();
-        if !result.is_numeric() {
-            if let Some(longhand) = context.for_non_inherited_property {
-                if longhand.stores_complex_colors_lossily() {
-                    context.rule_cache_conditions.borrow_mut().set_uncacheable();
-                }
-            }
-        }
-        result
+        self.to_computed_color(Some(context)).unwrap()
     }
 
     fn from_computed_value(computed: &ComputedColor) -> Self {
         match *computed {
             GenericColor::Numeric(color) => Color::rgba(color),
             GenericColor::CurrentColor => Color::currentcolor(),
             GenericColor::Complex { .. } => Color::Complex(*computed),
         }
     }
 }
 
-/// Specified color value, but resolved to just RGBA for computed value
-/// with value from color property at the same context.
+/// Specified color value for `-moz-font-smoothing-background-color`.
+///
+/// This property does not support `currentcolor`. We could drop it at
+/// parse-time, but it's not exposed to the web so it doesn't really matter.
+///
+/// We resolve it to `transparent` instead.
 #[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
-pub struct RGBAColor(pub Color);
+pub struct MozFontSmoothingBackgroundColor(pub Color);
 
-impl Parse for RGBAColor {
+impl Parse for MozFontSmoothingBackgroundColor {
     fn parse<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<Self, ParseError<'i>> {
-        Color::parse(context, input).map(RGBAColor)
+        Color::parse(context, input).map(MozFontSmoothingBackgroundColor)
     }
 }
 
-impl ToComputedValue for RGBAColor {
+impl ToComputedValue for MozFontSmoothingBackgroundColor {
     type ComputedValue = RGBA;
 
     fn to_computed_value(&self, context: &Context) -> RGBA {
-        self.0
-            .to_computed_value(context)
-            .to_rgba(context.style().get_color().clone_color())
+        self.0.to_computed_value(context).to_rgba(RGBA::transparent())
     }
 
     fn from_computed_value(computed: &RGBA) -> Self {
-        RGBAColor(Color::rgba(*computed))
-    }
-}
-
-impl From<Color> for RGBAColor {
-    fn from(color: Color) -> RGBAColor {
-        RGBAColor(color)
+        MozFontSmoothingBackgroundColor(Color::rgba(*computed))
     }
 }
 
 impl SpecifiedValueInfo for Color {
     const SUPPORTED_TYPES: u8 = CssType::COLOR;
 
     fn collect_completion_keywords(f: KeywordsCollectFn) {
         // We are not going to insert all the color names here. Caller and
--- a/servo/components/style/values/specified/mod.rs
+++ b/servo/components/style/values/specified/mod.rs
@@ -37,17 +37,17 @@ pub use self::border::{BorderCornerRadiu
 pub use self::border::{BorderImageRepeat, BorderImageSideWidth};
 pub use self::border::{BorderRadius, BorderSideWidth, BorderSpacing, BorderStyle};
 pub use self::box_::{AnimationIterationCount, AnimationName, Contain, Display};
 pub use self::box_::{Appearance, BreakBetween, BreakWithin};
 pub use self::box_::{Clear, Float, Overflow, OverflowAnchor};
 pub use self::box_::{OverflowClipBox, OverscrollBehavior, Perspective, Resize};
 pub use self::box_::{ScrollSnapAlign, ScrollSnapType};
 pub use self::box_::{TouchAction, TransitionProperty, VerticalAlign, WillChange};
-pub use self::color::{Color, ColorOrAuto, ColorPropertyValue, RGBAColor};
+pub use self::color::{Color, ColorOrAuto, ColorPropertyValue};
 pub use self::column::ColumnCount;
 pub use self::counters::{Content, ContentItem, CounterIncrement, CounterSetOrReset};
 pub use self::easing::TimingFunction;
 pub use self::effects::{BoxShadow, Filter, SimpleShadow};
 pub use self::flex::FlexBasis;
 pub use self::font::{FontFamily, FontLanguageOverride, FontStyle};
 pub use self::font::{FontFeatureSettings, FontVariantLigatures, FontVariantNumeric};
 pub use self::font::{FontSize, FontSizeAdjust, FontStretch, FontSynthesis};
--- a/servo/ports/geckolib/cbindgen.toml
+++ b/servo/ports/geckolib/cbindgen.toml
@@ -305,9 +305,17 @@ renaming_overrides_prefixing = true
    * Compute the final color, taking into account the foreground color from the
    * style.
    */
   nscolor CalcColor(const ComputedStyle&) const;
   /**
    * Compute the final color, making the argument the foreground color.
    */
   nscolor CalcColor(nscolor) const;
+  nscolor CalcColor(const StyleRGBA&) const;
 """
+
+"RGBA" = """
+  static inline StyleRGBA Transparent();
+  static inline StyleRGBA FromColor(nscolor);
+
+  inline nscolor ToColor() const;
+"""