Bug 1457810: Move CalcComplexColor to StyleComplexColor. r=xidorn
authorDan Glastonbury <dan.glastonbury@gmail.com>
Wed, 09 May 2018 17:03:02 +1000
changeset 417635 91f19dc74d952c92c5057d1bb782b8c71c973677
parent 417634 fc2188a4b2d95e22eea66b4d8887b17cf50de559
child 417636 6feab03068cb0f2216f319bacf6d4df38e488002
push id33974
push userncsoregi@mozilla.com
push dateThu, 10 May 2018 09:47:43 +0000
treeherdermozilla-central@b52b2eb81d1e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersxidorn
bugs1457810
milestone62.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 1457810: Move CalcComplexColor to StyleComplexColor. r=xidorn Move from nsStyleColor::CalcComplexColor to StyleComplexColor::CalcColor. MozReview-Commit-ID: FkYovvPZLc8
accessible/base/TextAttrs.cpp
gfx/src/nsColor.cpp
gfx/src/nsColor.h
layout/generic/nsTextFrame.cpp
layout/painting/nsCSSRendering.cpp
layout/style/ComputedStyle.cpp
layout/style/StyleComplexColor.cpp
layout/style/StyleComplexColor.h
layout/style/moz.build
layout/style/nsComputedDOMStyle.cpp
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/xul/nsTextBoxFrame.cpp
layout/xul/tree/nsTreeBodyFrame.cpp
--- a/accessible/base/TextAttrs.cpp
+++ b/accessible/base/TextAttrs.cpp
@@ -697,18 +697,17 @@ TextAttrsMgr::AutoGeneratedTextAttr::
 // TextDecorTextAttr
 ////////////////////////////////////////////////////////////////////////////////
 
 TextAttrsMgr::TextDecorValue::
   TextDecorValue(nsIFrame* aFrame)
 {
   const nsStyleTextReset* textReset = aFrame->StyleTextReset();
   mStyle = textReset->mTextDecorationStyle;
-  mColor = aFrame->StyleColor()->
-    CalcComplexColor(textReset->mTextDecorationColor);
+  mColor = textReset->mTextDecorationColor.CalcColor(aFrame);
   mLine = textReset->mTextDecorationLine &
     (NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE |
      NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH);
 }
 
 TextAttrsMgr::TextDecorTextAttr::
   TextDecorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
   TTextAttr<TextDecorValue>(!aFrame)
--- a/gfx/src/nsColor.cpp
+++ b/gfx/src/nsColor.cpp
@@ -253,69 +253,16 @@ NS_ComposeColors(nscolor aBG, nscolor aF
   }
   MOZ_BLEND(r, NS_GET_R(aBG), NS_GET_R(aFG), blendAlpha);
   MOZ_BLEND(g, NS_GET_G(aBG), NS_GET_G(aFG), blendAlpha);
   MOZ_BLEND(b, NS_GET_B(aBG), NS_GET_B(aFG), blendAlpha);
 
   return NS_RGBA(r, g, b, a);
 }
 
-namespace mozilla {
-
-static uint32_t
-BlendColorComponent(uint32_t aBg, uint32_t aFg, uint32_t aFgAlpha)
-{
-  return RoundingDivideBy255(aBg * (255 - aFgAlpha) + aFg * aFgAlpha);
-}
-
-nscolor
-LinearBlendColors(nscolor aBg, nscolor aFg, uint_fast8_t aFgRatio)
-{
-  // Common case that either pure background or pure foreground
-  if (aFgRatio == 0) {
-    return aBg;
-  }
-  if (aFgRatio == 255) {
-    return aFg;
-  }
-  // Common case that alpha channel is equal (usually both are opaque)
-  if (NS_GET_A(aBg) == NS_GET_A(aFg)) {
-    auto r = BlendColorComponent(NS_GET_R(aBg), NS_GET_R(aFg), aFgRatio);
-    auto g = BlendColorComponent(NS_GET_G(aBg), NS_GET_G(aFg), aFgRatio);
-    auto b = BlendColorComponent(NS_GET_B(aBg), NS_GET_B(aFg), aFgRatio);
-    return NS_RGBA(r, g, b, NS_GET_A(aFg));
-  }
-
-  constexpr float kFactor = 1.0f / 255.0f;
-
-  float p1 = kFactor * (255 - aFgRatio);
-  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 p2 = 1.0f - p1;
-  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 a = p1 * a1 + p2 * a2;
-  if (a == 0.0) {
-    return NS_RGBA(0, 0, 0, 0);
-  }
-
-  auto r = ClampColor((p1 * r1 + p2 * r2) / a);
-  auto g = ClampColor((p1 * g1 + p2 * g2) / a);
-  auto b = ClampColor((p1 * b1 + p2 * b2) / a);
-  return NS_RGBA(r, g, b, NSToIntRound(a * 255));
-}
-
-} // namespace mozilla
-
 // Functions to convert from HSL color space to RGB color space.
 // This is the algorithm described in the CSS3 specification
 
 // helper
 static float
 HSL_HueToRGB(float m1, float m2, float h)
 {
   if (h < 0.0f)
--- a/gfx/src/nsColor.h
+++ b/gfx/src/nsColor.h
@@ -81,20 +81,16 @@ namespace mozilla {
 inline uint32_t RoundingDivideBy255(uint32_t n)
 {
   // There is an approximate alternative: ((n << 8) + n + 32896) >> 16
   // But that is actually slower than this simple expression on a modern
   // machine with a modern compiler.
   return (n + 127) / 255;
 }
 
-// Blend one RGBA color with another based on a given ratio.
-// It is a linear interpolation on each channel with alpha premultipled.
-nscolor LinearBlendColors(nscolor aBg, nscolor aFg, uint_fast8_t aFgRatio);
-
 } // namespace mozilla
 
 // Translate a hex string to a color. Return true if it parses ok,
 // otherwise return false.
 // This version accepts 1 to 9 digits (missing digits are 0)
 bool NS_LooseHexToRGB(const nsString& aBuf, nscolor* aResult);
 
 // There is no function to translate a color to a hex string, because
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -339,18 +339,17 @@ public:
   nscolor GetTextColor();
 
   // SVG text has its own painting process, so we should never get its stroke
   // property from here.
   nscolor GetWebkitTextStrokeColor() {
     if (nsSVGUtils::IsInSVGTextSubtree(mFrame)) {
       return 0;
     }
-    return mFrame->StyleColor()->
-      CalcComplexColor(mFrame->StyleText()->mWebkitTextStrokeColor);
+    return mFrame->StyleText()->mWebkitTextStrokeColor.CalcColor(mFrame);
   }
   float GetWebkitTextStrokeWidth() {
     if (nsSVGUtils::IsInSVGTextSubtree(mFrame)) {
       return 0.0f;
     }
     nscoord coord = mFrame->StyleText()->mWebkitTextStrokeWidth;
     return mFrame->PresContext()->AppUnitsToFloatDevPixels(coord);
   }
@@ -5190,21 +5189,20 @@ void
 nsTextFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsDisplayListSet& aLists)
 {
   if (!IsVisibleForPainting(aBuilder))
     return;
 
   DO_GLOBAL_REFLOW_COUNT_DSP("nsTextFrame");
 
-  const nsStyleColor* sc = StyleColor();
   const nsStyleText* st = StyleText();
   bool isTextTransparent =
-    NS_GET_A(sc->CalcComplexColor(st->mWebkitTextFillColor)) == 0 &&
-    NS_GET_A(sc->CalcComplexColor(st->mWebkitTextStrokeColor)) == 0;
+    NS_GET_A(st->mWebkitTextFillColor.CalcColor(this)) == 0 &&
+    NS_GET_A(st->mWebkitTextStrokeColor.CalcColor(this)) == 0;
   Maybe<bool> isSelected;
   if (((GetStateBits() & TEXT_NO_RENDERED_GLYPHS) ||
        (isTextTransparent && !StyleText()->HasTextShadow())) &&
       aBuilder->IsForPainting() && !nsSVGUtils::IsInSVGTextSubtree(this)) {
     isSelected.emplace(IsSelected());
     if (!isSelected.value()) {
       TextDecorations textDecs;
       GetTextDecorations(PresContext(), eResolvedColors, textDecs);
--- a/layout/painting/nsCSSRendering.cpp
+++ b/layout/painting/nsCSSRendering.cpp
@@ -795,19 +795,16 @@ ConstructBorderRenderer(nsPresContext* a
                         const nsRect& aDirtyRect,
                         const nsRect& aBorderArea,
                         const nsStyleBorder& aStyleBorder,
                         Sides aSkipSides,
                         bool* aNeedsClip)
 {
   nsMargin border = aStyleBorder.GetComputedBorder();
 
-  // Get our ComputedStyle's color struct.
-  const nsStyleColor* ourColor = aComputedStyle->StyleColor();
-
   // In NavQuirks mode we want to use the parent's context as a starting point
   // for determining the background color.
   bool quirks = aPresContext->CompatibilityMode() == eCompatibility_NavQuirks;
   nsIFrame* bgFrame = nsCSSRendering::FindNonTransparentBackgroundFrame(aForFrame, quirks);
   ComputedStyle* bgContext = bgFrame->Style();
   nscolor bgColor = bgContext->
     GetVisitedDependentColor(&nsStyleBackground::mBackgroundColor);
 
@@ -856,17 +853,17 @@ ConstructBorderRenderer(nsPresContext* a
   Rect dirtyRect = NSRectToRect(aDirtyRect, oneDevPixel);
 
   uint8_t borderStyles[4];
   nscolor borderColors[4];
 
   // pull out styles, colors
   NS_FOR_CSS_SIDES (i) {
     borderStyles[i] = aStyleBorder.GetBorderStyle(i);
-    borderColors[i] = ourColor->CalcComplexColor(aStyleBorder.mBorderColor[i]);
+    borderColors[i] = aStyleBorder.mBorderColor[i].CalcColor(aComputedStyle);
   }
 
   PrintAsFormatString(" borderStyles: %d %d %d %d\n", borderStyles[0], borderStyles[1], borderStyles[2], borderStyles[3]);
 
   nsIDocument* document = nullptr;
   nsIContent* content = aForFrame->GetContent();
   if (content) {
     document = content->OwnerDoc();
--- a/layout/style/ComputedStyle.cpp
+++ b/layout/style/ComputedStyle.cpp
@@ -336,17 +336,17 @@ static nscolor
 ExtractColor(ComputedStyle* aStyle, const nscolor& aColor)
 {
   return aColor;
 }
 
 static nscolor
 ExtractColor(ComputedStyle* aStyle, const StyleComplexColor& aColor)
 {
-  return aStyle->StyleColor()->CalcComplexColor(aColor);
+  return aColor.CalcColor(aStyle);
 }
 
 static nscolor
 ExtractColor(ComputedStyle* aStyle, const nsStyleSVGPaint& aPaintServer)
 {
   return aPaintServer.Type() == eStyleSVGPaintType_Color
     ? aPaintServer.GetColor() : NS_RGBA(0, 0, 0, 0);
 }
new file mode 100644
--- /dev/null
+++ b/layout/style/StyleComplexColor.cpp
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#include "mozilla/StyleComplexColor.h"
+
+#include "mozilla/ComputedStyle.h"
+#include "mozilla/ComputedStyleInlines.h"
+#include "nsIFrame.h"
+#include "nsStyleStruct.h"
+
+using namespace mozilla;
+
+static uint32_t
+BlendColorComponent(uint32_t aBg, uint32_t aFg, uint32_t aFgAlpha)
+{
+  return RoundingDivideBy255(aBg * (255 - aFgAlpha) + aFg * aFgAlpha);
+}
+
+// Blend one RGBA color with another based on a given ratio.
+// It is a linear interpolation on each channel with alpha premultipled.
+static nscolor
+LinearBlendColors(nscolor aBg, nscolor aFg, uint_fast8_t aFgRatio)
+{
+  // Common case that either pure background or pure foreground
+  if (aFgRatio == 0) {
+    return aBg;
+  }
+  if (aFgRatio == 255) {
+    return aFg;
+  }
+  // Common case that alpha channel is equal (usually both are opaque)
+  if (NS_GET_A(aBg) == NS_GET_A(aFg)) {
+    auto r = BlendColorComponent(NS_GET_R(aBg), NS_GET_R(aFg), aFgRatio);
+    auto g = BlendColorComponent(NS_GET_G(aBg), NS_GET_G(aFg), aFgRatio);
+    auto b = BlendColorComponent(NS_GET_B(aBg), NS_GET_B(aFg), aFgRatio);
+    return NS_RGBA(r, g, b, NS_GET_A(aFg));
+  }
+
+  constexpr float kFactor = 1.0f / 255.0f;
+
+  float p1 = kFactor * (255 - aFgRatio);
+  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 p2 = 1.0f - p1;
+  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 a = p1 * a1 + p2 * a2;
+  if (a == 0.0) {
+    return NS_RGBA(0, 0, 0, 0);
+  }
+
+  auto r = ClampColor((p1 * r1 + p2 * r2) / a);
+  auto g = ClampColor((p1 * g1 + p2 * g2) / a);
+  auto b = ClampColor((p1 * b1 + p2 * b2) / a);
+  return NS_RGBA(r, g, b, NSToIntRound(a * 255));
+}
+
+nscolor
+StyleComplexColor::CalcColor(mozilla::ComputedStyle* aStyle) const {
+  MOZ_ASSERT(aStyle);
+  auto foregroundColor = aStyle->StyleColor()->mColor;
+  return LinearBlendColors(mColor, foregroundColor, mForegroundRatio);
+}
+
+nscolor
+StyleComplexColor::CalcColor(const nsIFrame* aFrame) const {
+  return CalcColor(aFrame->Style());
+}
--- a/layout/style/StyleComplexColor.h
+++ b/layout/style/StyleComplexColor.h
@@ -6,18 +6,22 @@
 
 /* represent a color combines a numeric color and currentcolor */
 
 #ifndef mozilla_StyleComplexColor_h_
 #define mozilla_StyleComplexColor_h_
 
 #include "nsColor.h"
 
+class nsIFrame;
+
 namespace mozilla {
 
+class ComputedStyle;
+
 /**
  * This struct represents a combined color from a numeric color and
  * the current foreground color (currentcolor keyword).
  * Conceptually, the formula is "color * (1 - p) + currentcolor * p"
  * where p is mForegroundRatio. See mozilla::LinearBlendColors for
  * the actual algorithm.
  */
 struct StyleComplexColor
@@ -46,13 +50,25 @@ struct StyleComplexColor
   bool operator==(const StyleComplexColor& aOther) const {
     return mForegroundRatio == aOther.mForegroundRatio &&
            (IsCurrentColor() || mColor == aOther.mColor) &&
            mIsAuto == aOther.mIsAuto;
   }
   bool operator!=(const StyleComplexColor& aOther) const {
     return !(*this == aOther);
   }
+
+  /**
+   * Compute the color for this StyleComplexColor, taking into account
+   * the foreground color from aStyle.
+   */
+  nscolor CalcColor(mozilla::ComputedStyle* aStyle) const;
+
+  /**
+   * Compute the color for this StyleComplexColor, taking into account
+   * the foreground color from aFrame's ComputedStyle.
+   */
+  nscolor CalcColor(const nsIFrame* aFrame) const;
 };
 
 }
 
 #endif // mozilla_StyleComplexColor_h_
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -216,16 +216,17 @@ UNIFIED_SOURCES += [
     'ServoNamespaceRule.cpp',
     'ServoPageRule.cpp',
     'ServoSpecifiedValues.cpp',
     'ServoStyleRule.cpp',
     'ServoStyleSet.cpp',
     'ServoSupportsRule.cpp',
     'StreamLoader.cpp',
     'StyleAnimationValue.cpp',
+    'StyleComplexColor.cpp',
     'StyleSheet.cpp',
     'URLExtraData.cpp',
 ]
 
 SOURCES += [
     'nsCSSAnonBoxes.cpp',
     'nsCSSPseudoElements.cpp',
     # nsLayoutStylesheetCache.cpp uses nsExceptionHandler.h, which includes
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -1183,17 +1183,17 @@ nsComputedDOMStyle::SetToRGBAColor(nsROC
 
   aValue->SetColor(rgbColor);
 }
 
 void
 nsComputedDOMStyle::SetValueFromComplexColor(nsROCSSPrimitiveValue* aValue,
                                              const StyleComplexColor& aColor)
 {
-  SetToRGBAColor(aValue, StyleColor()->CalcComplexColor(aColor));
+  SetToRGBAColor(aValue, aColor.CalcColor(mComputedStyle));
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetColor()
 {
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
   SetToRGBAColor(val, StyleColor()->mColor);
   return val.forget();
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -3367,17 +3367,17 @@ nsStyleBackground::BackgroundColor(const
 
 nscolor
 nsStyleBackground::BackgroundColor(mozilla::ComputedStyle* aStyle) const
 {
   // In majority of cases, background-color should just be a numeric color.
   // In that case, we can skip resolving StyleColor().
   return mBackgroundColor.IsNumericColor()
     ? mBackgroundColor.mColor
-    : aStyle->StyleColor()->CalcComplexColor(mBackgroundColor);
+    : mBackgroundColor.CalcColor(aStyle);
 }
 
 bool
 nsStyleBackground::IsTransparent(const nsIFrame* aFrame) const
 {
   return IsTransparent(aFrame->Style());
 }
 
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -517,21 +517,16 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   explicit nsStyleColor(const nsPresContext* aContext);
   nsStyleColor(const nsStyleColor& aOther);
   ~nsStyleColor() {
     MOZ_COUNT_DTOR(nsStyleColor);
   }
   void FinishStyle(nsPresContext*, const nsStyleColor*) {}
   const static bool kHasFinishStyle = false;
 
-  nscolor CalcComplexColor(const mozilla::StyleComplexColor& aColor) const {
-    return mozilla::LinearBlendColors(aColor.mColor, mColor,
-                                      aColor.mForegroundRatio);
-  }
-
   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;                 // [inherited]
 };
 
 struct nsStyleImageLayers {
--- a/layout/xul/nsTextBoxFrame.cpp
+++ b/layout/xul/nsTextBoxFrame.cpp
@@ -422,18 +422,17 @@ nsTextBoxFrame::DrawText(gfxContext&    
       }
       const nsStyleTextReset* styleText = context->StyleTextReset();
 
       if (decorMask & styleText->mTextDecorationLine) {  // a decoration defined here
         nscolor color;
         if (aOverrideColor) {
           color = *aOverrideColor;
         } else {
-          color = context->StyleColor()->
-            CalcComplexColor(styleText->mTextDecorationColor);
+          color = styleText->mTextDecorationColor.CalcColor(context);
         }
         uint8_t style = styleText->mTextDecorationStyle;
 
         if (NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE & decorMask &
               styleText->mTextDecorationLine) {
           underColor = color;
           underStyle = style;
           decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
--- a/layout/xul/tree/nsTreeBodyFrame.cpp
+++ b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -3302,18 +3302,17 @@ nsTreeBodyFrame::PaintCell(int32_t      
                     twistyContext);
 
       nsMargin twistyMargin;
       twistyContext->StyleMargin()->GetMargin(twistyMargin);
       twistyRect.Inflate(twistyMargin);
 
       const nsStyleBorder* borderStyle = lineContext->StyleBorder();
       // Resolve currentcolor values against the treeline context
-      nscolor color = lineContext->StyleColor()->
-        CalcComplexColor(borderStyle->mBorderLeftColor);
+      nscolor color = borderStyle->mBorderLeftColor.CalcColor(lineContext);
       ColorPattern colorPatt(ToDeviceColor(color));
 
       uint8_t style = borderStyle->GetBorderStyle(eSideLeft);
       StrokeOptions strokeOptions;
       nsLayoutUtils::InitDashPattern(strokeOptions, style);
 
       nscoord srcX = currX + twistyRect.width - mIndentation / 2;
       nscoord lineY = (aRowIndex - mTopRowIndex) * mRowHeight + aPt.y;