Bug 1457810: Move CalcComplexColor to StyleComplexColor. r?xidorn draft
authorDan Glastonbury <dan.glastonbury@gmail.com>
Wed, 09 May 2018 17:03:02 +1000
changeset 793433 8c13b22c94fed0c2de9e0f02912227c6ff582438
parent 792270 59005ba3cd3e7b3f9e8804bea881bf4c3a755d7c
push id109379
push userbmo:dglastonbury@mozilla.com
push dateThu, 10 May 2018 00:25:00 +0000
reviewersxidorn
bugs1457810
milestone62.0a1
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);
   }
@@ -5189,21 +5188,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;