Bug 1457810: Move CalcComplexColor to StyleComplexColor. r?xidorn
Move from nsStyleColor::CalcComplexColor to StyleComplexColor::CalcColor.
MozReview-Commit-ID: FkYovvPZLc8
--- 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;